Transactions
Token Transfers
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- FarmPACT
- Optimization enabled
- true
- Compiler version
- v0.6.12+commit.27d51765
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2026-04-22T01:58:53.315598Z
Constructor Arguments
00000000000000000000000013c674c7f56232592c19e5fbba345b8d3a9dc99f00000000000000000000000066e7ce35578a37209d01f99f3d2ff271f981f581000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000108b2a2c28029094000000
Arg [0] (address) : 0x13c674c7f56232592c19e5fbba345b8d3a9dc99f
Arg [1] (address) : 0x66e7ce35578a37209d01f99f3d2ff271f981f581
Arg [2] (uint256) : 15
Arg [3] (uint256) : 20000000000000000000000000
/app/contracts/pactFarm/FarmPACT.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "./AbstractFarm.sol";
import "../vendors/libraries/SafeMath.sol";
import "../vendors/contracts/access/GovernanceOwnable.sol";
// Cloned and modified from https://github.com/ltonetwork/uniswap-farming/blob/master/contracts/Farm.sol
contract FarmPACT is GovernanceOwnable, AbstractFarm {
using SafeMath for uint256;
uint256 _blockGenerationFrequency;
function blockGenerationFrequency() public view returns (uint256) {
return _blockGenerationFrequency;
}
// etherium - block_generation_frequency_ ~ 15s
// binance smart chain - block_generation_frequency_ ~ 4s
constructor(
address governance_,
IERC20 pact_,
uint256 blockGenerationFrequency_,
uint256 totalRewardAmount_
) GovernanceOwnable(governance_) AbstractFarm(pact_, totalRewardAmount_) public {
require(blockGenerationFrequency_ > 0, "constructor: blockGenerationFrequency is empty");
_blockGenerationFrequency = blockGenerationFrequency_;
}
function startFarming(uint256 startBlock) public onlyGovernance {
require(_lastStageEndBlock == 0, "startFarming: already started");
uint currentBalance = _pact.balanceOf(address(this));
require(currentBalance >= _totalRewardAmount, "startFarming: currentBalance is not enough");
_addFirstStage(startBlock, 10 days / _blockGenerationFrequency, _totalRewardAmount / 8);
_addStage(20 days / _blockGenerationFrequency, _totalRewardAmount / 8);
_addStage(150 days / _blockGenerationFrequency, _totalRewardAmount / 8);
_addStage(180 days / _blockGenerationFrequency, _totalRewardAmount / 8);
_addStage(1080 days / _blockGenerationFrequency, _totalRewardAmount / 2);
}
function addLpToken(uint256 _allocPoint, address _lpToken, bool _withUpdate) public onlyGovernance {
_addLpToken(_allocPoint, IUniswapV2Pair(_lpToken), _withUpdate);
}
function updateLpToken(uint256 poolId, uint256 allocPoint, bool withUpdate) public onlyGovernance {
_updateLpToken(poolId, allocPoint, withUpdate);
}
}
/IUniswapV2ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "./IERC20.sol";
interface IUniswapV2ERC20 is IERC20 {
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}
/
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "../vendors/libraries/SafeMath.sol";
abstract contract StagesStorage {
using SafeMath for uint256;
uint256 _totalRewardAmount;
function totalRewardAmount() public view returns (uint256) {
return _totalRewardAmount;
}
constructor(
uint256 totalRewardAmount_
) public {
require(totalRewardAmount_ > 0, "constructor: totalRewardAmount is empty");
_totalRewardAmount = totalRewardAmount_;
}
struct StageInfo {
uint256 id;
uint256 startBlock;
uint256 endBlock;
uint256 rewardPerBlock;
}
// stageId => StageInfo
StageInfo[] _stageInfo;
uint256 _stageInfoCount = 0;
uint256 _totalRewardInStages;
uint256 _lastStageEndBlock;
function stageInfo(uint256 stageId) public view returns (StageInfo memory) {
return _stageInfo[stageId];
}
function stageInfoCount() public view returns (uint256) {
return _stageInfoCount;
}
function totalRewardInStages() public view returns (uint256) {
return _totalRewardInStages;
}
function _addFirstStage(
uint256 startBlock,
uint256 periodInBlocks,
uint256 rewardAmount
) internal {
require(_lastStageEndBlock == 0, "_addFirstStage: first stage is already installed");
startBlock = block.number > startBlock ? block.number : startBlock;
__addStage(
startBlock,
periodInBlocks,
rewardAmount
);
}
function _addStage(
uint256 periodInBlocks,
uint256 rewardAmount
) internal {
require(_lastStageEndBlock > 0, "_addStage: first stage is not installed yet");
__addStage(
_lastStageEndBlock,
periodInBlocks,
rewardAmount
);
}
function __addStage(
uint256 startBlock,
uint256 periodInBlocks,
uint256 rewardAmount
) private {
StageInfo memory newStage = StageInfo({
id: _stageInfoCount,
startBlock: startBlock,
endBlock: startBlock.add(periodInBlocks),
rewardPerBlock: rewardAmount.div(periodInBlocks)
});
++_stageInfoCount;
_stageInfo.push(newStage);
_lastStageEndBlock = newStage.endBlock.add(1);
_totalRewardInStages = _totalRewardInStages.add(rewardAmount);
require(_totalRewardInStages <= _totalRewardAmount, "__addStage: _totalRewardInStages > _totalRewardAmount");
}
function stagesLength() external view returns (uint256) {
return _stageInfo.length;
}
}
/
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "../vendors/libraries/SafeMath.sol";
import "../vendors/interfaces/IERC20.sol";
import "../vendors/interfaces/IUniswapV2Pair.sol";
abstract contract LpTokensStorage {
using SafeMath for uint256;
// Address of the ERC20 Token contract.
IERC20 _pact;
constructor(IERC20 pact_) public {
require(address(pact_) != address(0), "LpTokensStorage::constructor: pact_ - is empty");
_pact = pact_;
}
function pact() public view returns (address) {
return address(_pact);
}
struct PoolInfo {
uint256 id;
IUniswapV2Pair lpToken; // Address of LP token contract.
uint256 allocPoint; // How many allocation points assigned to this pool. ERC20s to distribute per block.
}
// poolId => PoolInfo
PoolInfo[] _poolInfo;
uint256 _poolInfoCount = 0;
mapping (address => bool) _lpTokensList;
// Total allocation points. Must be the sum of all allocation points in all pools.
uint256 _totalAllocPoint = 0;
function poolInfoCount() public view returns (uint256) {
return _poolInfoCount;
}
function poolInfo(uint256 poolId) public view returns (PoolInfo memory) {
return _poolInfo[poolId];
}
function totalAllocPoint() public view returns (uint256) {
return _totalAllocPoint;
}
function _addLpToken(uint256 allocPoint, IUniswapV2Pair lpToken) internal {
require(_lpTokensList[address(lpToken)] == false, "_addLpToken: LP Token exists");
_totalAllocPoint = _totalAllocPoint.add(allocPoint);
_poolInfo.push(PoolInfo({
id: _poolInfoCount,
lpToken: lpToken,
allocPoint: allocPoint
}));
++_poolInfoCount;
_lpTokensList[address(lpToken)] = true;
}
function _updateLpToken(uint256 poolId, uint256 allocPoint) internal {
require(poolId < _poolInfoCount, "_updateLpToken: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
_totalAllocPoint = _totalAllocPoint.sub(pool.allocPoint).add(allocPoint);
pool.allocPoint = allocPoint;
}
}
/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return add(a, b, "SafeMath: Add Overflow");
}
function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);// "SafeMath: Add Overflow"
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: Underflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;// "SafeMath: Underflow"
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return mul(a, b, "SafeMath: Mul Overflow");
}
function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, errorMessage);// "SafeMath: Mul Overflow"
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: division by zero");
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}
/SafeERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "../interfaces/IERC20.sol";
library SafeERC20 {
function safeSymbol(IERC20 token) internal view returns(string memory) {
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41));
return success && data.length > 0 ? abi.decode(data, (string)) : "???";
}
function safeName(IERC20 token) internal view returns(string memory) {
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03));
return success && data.length > 0 ? abi.decode(data, (string)) : "???";
}
function safeDecimals(IERC20 token) public view returns (uint8) {
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567));
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
}
function safeTransfer(IERC20 token, address to, uint256 amount) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount));
require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: Transfer failed");
}
function safeApprove(IERC20 token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransferFrom(IERC20 token, address from, uint256 amount) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, address(this), amount));
require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: TransferFrom failed");
}
}
/IUniswapV2Pair.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "./IUniswapV2ERC20.sol";
interface IUniswapV2Pair is IUniswapV2ERC20 {
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
/
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "../vendors/libraries/SafeMath.sol";
import "../vendors/libraries/SafeERC20.sol";
import "../vendors/interfaces/IERC20.sol";
import "./UsersStorage.sol";
import "./StagesStorage.sol";
abstract contract AbstractFarm is UsersStorage, StagesStorage {
using SafeMath for uint256;
using SafeERC20 for IERC20;
constructor(IERC20 pact_, uint256 totalRewardAmount_) LpTokensStorage(pact_) StagesStorage(totalRewardAmount_) public {}
////////////////////////////////////////////////////////////
struct PoolInfoInFarmStage {
uint256 lastRewardBlock; // Last block number that ERC20s distribution occurs.
uint256 accERC20PerShare; // Accumulated ERC20s per share, times 1e36.
}
// stageId => poolId => PoolInfoInFarmStage
mapping (uint256 => mapping (uint256 => PoolInfoInFarmStage)) public _poolInfoInFarmStages;
// Update reward variables for all pools. Be careful of gas spending!
function massUpdatePools() public {
for (uint256 poolId = 0; poolId < _poolInfoCount; ++poolId) {
updatePool(poolId);
}
}
// poolId => firstNotFinishedStage
mapping (uint256 => uint256) _firstNotFinishedStages;
function updatePool(uint256 poolId) public {
require(poolId < _poolInfoCount, "updatePool: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
_updatePool(pool);
}
function _updatePool(PoolInfo storage pool) internal {
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
StageInfo storage stage;
for (uint256 stageId = _firstNotFinishedStages[pool.id]; stageId < _stageInfoCount; ++stageId) {
stage = _stageInfo[stageId];
if (stage.startBlock > block.number) {
return;
}
if (_updatePoolInfoInFarmStage(stage, pool, lpSupply)) {
_firstNotFinishedStages[pool.id] = stageId.add(1);
}
}
}
function _updatePoolInfoInFarmStage(
StageInfo storage stage,
PoolInfo storage pool,
uint256 lpSupply
) internal returns (bool) {
uint256 lastBlock = block.number < stage.endBlock ? block.number : stage.endBlock;
PoolInfoInFarmStage storage poolInFarmStage = _poolInfoInFarmStages[stage.id][pool.id];
if (poolInFarmStage.lastRewardBlock < stage.startBlock) {
poolInFarmStage.lastRewardBlock = stage.startBlock;
}
if (lastBlock <= poolInFarmStage.lastRewardBlock) {
return true;
}
if (lpSupply == 0) {
poolInFarmStage.lastRewardBlock = lastBlock;
return false;
}
uint256 nrOfBlocks = lastBlock.sub(poolInFarmStage.lastRewardBlock);
uint256 erc20Reward = nrOfBlocks.mul(stage.rewardPerBlock).mul(pool.allocPoint).div(_totalAllocPoint);
poolInFarmStage.accERC20PerShare = poolInFarmStage.accERC20PerShare.add(erc20Reward.mul(1e36).div(lpSupply));
poolInFarmStage.lastRewardBlock = block.number;
return false;
}
////////////////////////////////////////////////////////////
function pending(uint256 poolId, address account) external view returns (uint256) {
require(poolId < _poolInfoCount, "pending: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
UserInfo storage user = _userInfo[poolId][account];
uint256 rewardPending = user.rewardPending;
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
for (uint256 stageId = 0; stageId < _stageInfoCount; ++stageId) {
StageInfo storage stage = _stageInfo[stageId];
if (stage.startBlock > block.number) {
break;
}
PoolInfoInFarmStage storage poolInFarmStage = _poolInfoInFarmStages[stageId][poolId];
uint256 accERC20PerShare = poolInFarmStage.accERC20PerShare;
uint256 lastBlock = block.number < stage.endBlock ? block.number : stage.endBlock;
if (lastBlock > poolInFarmStage.lastRewardBlock && lpSupply != 0) {
uint256 startBlock = poolInFarmStage.lastRewardBlock < stage.startBlock ? stage.startBlock : poolInFarmStage.lastRewardBlock;
uint256 nrOfBlocks = lastBlock.sub(startBlock);
uint256 erc20Reward = nrOfBlocks.mul(stage.rewardPerBlock).mul(pool.allocPoint).div(_totalAllocPoint);
accERC20PerShare = accERC20PerShare.add(erc20Reward.mul(1e36).div(lpSupply));
}
uint256 pendingAmount = user.amount.mul(accERC20PerShare).div(1e36).sub(_userRewardDebt[stageId][poolId][account]);
rewardPending = rewardPending.add(pendingAmount);
}
return rewardPending;
}
////////////////////////////////////////////////////////////
function _addLpToken(uint256 allocPoint, IUniswapV2Pair lpToken, bool withUpdate) internal {
if (withUpdate) {
massUpdatePools();
}
_addLpToken(allocPoint, lpToken);
}
function _updateLpToken(uint256 poolId, uint256 allocPoint, bool withUpdate) internal {
if (withUpdate) {
massUpdatePools();
}
_updateLpToken(poolId, allocPoint);
}
////////////////////////////////////////////////////////////
uint256 _totalRewardPending;
// stageId => poolId => account => userRewardDebt
mapping (uint256 => mapping (uint256 => mapping (address => uint256))) public _userRewardDebt;
function _beforeBalanceChange(PoolInfo storage pool, address account) internal virtual override {
_updatePool(pool);
UserInfo storage user = _userInfo[pool.id][account];
StageInfo storage stage;
for (uint256 stageId = 0; stageId < _stageInfoCount; ++stageId) {
stage = _stageInfo[stageId];
if (stage.startBlock > block.number) {
return;
}
PoolInfoInFarmStage storage poolInFarmStage = _poolInfoInFarmStages[stage.id][pool.id];
uint256 pendingAmount = user.amount
.mul(poolInFarmStage.accERC20PerShare)
.div(1e36)
.sub(_userRewardDebt[stage.id][pool.id][account]);
user.rewardPending = user.rewardPending.add(pendingAmount);
_totalRewardPending = _totalRewardPending.add(pendingAmount);
}
}
function _afterBalanceChange(PoolInfo storage pool, address account) internal virtual override {
UserInfo storage user = _userInfo[pool.id][account];
StageInfo storage stage;
for (uint256 stageId = 0; stageId < _stageInfoCount; ++stageId) {
stage = _stageInfo[stageId];
if (stage.startBlock > block.number) {
return;
}
PoolInfoInFarmStage storage poolInFarmStage = _poolInfoInFarmStages[stage.id][pool.id];
_userRewardDebt[stage.id][pool.id][account] = user.amount.mul(poolInFarmStage.accERC20PerShare).div(1e36);
}
}
function _updateUserRewardDebtAndPending(PoolInfo storage pool, address account) internal {
_updatePool(pool);
UserInfo storage user = _userInfo[pool.id][account];
StageInfo storage stage;
for (uint256 stageId = 0; stageId < _stageInfoCount; ++stageId) {
stage = _stageInfo[stageId];
if (stage.startBlock > block.number) {
return;
}
PoolInfoInFarmStage storage poolInFarmStage = _poolInfoInFarmStages[stage.id][pool.id];
uint256 pendingAmount = user.amount
.mul(poolInFarmStage.accERC20PerShare)
.div(1e36)
.sub(_userRewardDebt[stage.id][pool.id][account])
;
user.rewardPending = user.rewardPending.add(pendingAmount);
_totalRewardPending = _totalRewardPending.add(pendingAmount);
_userRewardDebt[stage.id][pool.id][account] = user.amount.mul(poolInFarmStage.accERC20PerShare).div(1e36);
}
}
////////////////////////////////////////////////////////////
event Harvest(address indexed user, uint256 indexed poolId, uint256 amount);
// Withdraw LP tokens from Farm.
function withdrawAndHarvest(uint256 poolId, uint256 amount) public {
require(poolId < _poolInfoCount, "withdrawAndHarvest: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
require(amount > 0, "withdrawAndHarvest: can't withdraw zero amount");
UserInfo storage user = _userInfo[poolId][msg.sender];
require(user.amount >= amount, "withdrawAndHarvest: can't withdraw more than deposit");
_beforeBalanceChange(pool, msg.sender);
user.amount = user.amount.sub(amount);
pool.lpToken.safeTransfer(address(msg.sender), amount);
emit Withdraw(msg.sender, poolId, amount);
_pact.transfer(msg.sender, user.rewardPending);
_totalRewardPending = _totalRewardPending.sub(user.rewardPending);
emit Harvest(msg.sender, poolId, user.rewardPending);
user.rewardPending = 0;
_afterBalanceChange(pool, msg.sender);
}
// Harvest PACTs from Farm.
function harvest(uint256 poolId) public {
require(poolId < _poolInfoCount, "harvest: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
UserInfo storage user = _userInfo[poolId][msg.sender];
require(user.userExists, "harvest: can't harvest from new user");
_updateUserRewardDebtAndPending(pool, msg.sender);
_pact.transfer(msg.sender, user.rewardPending);
_totalRewardPending = _totalRewardPending.sub(user.rewardPending);
emit Harvest(msg.sender, poolId, user.rewardPending);
user.rewardPending = 0;
}
}
/IGovernanceOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
interface IGovernanceOwnable {
event GovernanceSetTransferred(address indexed previousGovernance, address indexed newGovernance);
function governance() external view returns (address);
function setGovernance(address newGovernance) external;
}
/IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address tokenOwner) external view returns (uint balance);
function allowance(address tokenOwner, address spender) external view returns (uint remaining);
function approve(address spender, uint tokens) external returns (bool success);
function transfer(address to, uint tokens) external returns (bool success);
function transferFrom(address from, address to, uint tokens) external returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
/access/GovernanceOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "../../interfaces/IGovernanceOwnable.sol";
abstract contract GovernanceOwnable is IGovernanceOwnable {
address private _governanceAddress;
event GovernanceSetTransferred(address indexed previousGovernance, address indexed newGovernance);
constructor (address governance_) public {
require(governance_ != address(0), "Governance address should be not null");
_governanceAddress = governance_;
emit GovernanceSetTransferred(address(0), governance_);
}
/**
* @dev Returns the address of the current governanceAddress.
*/
function governance() public view override returns (address) {
return _governanceAddress;
}
/**
* @dev Throws if called by any account other than the governanceAddress.
*/
modifier onlyGovernance() {
require(_governanceAddress == msg.sender, "Governance: caller is not the governance");
_;
}
/**
* @dev SetGovernance of the contract to a new account (`newGovernance`).
* Can only be called by the current onlyGovernance.
*/
function setGovernance(address newGovernance) public virtual override onlyGovernance {
require(newGovernance != address(0), "GovernanceOwnable: new governance is the zero address");
emit GovernanceSetTransferred(_governanceAddress, newGovernance);
_governanceAddress = newGovernance;
}
}
/
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "../vendors/libraries/SafeMath.sol";
import "../vendors/libraries/SafeERC20.sol";
import "../vendors/interfaces/IUniswapV2Pair.sol";
import "./LpTokensStorage.sol";
abstract contract UsersStorage is LpTokensStorage {
using SafeMath for uint256;
using SafeERC20 for IUniswapV2Pair;
struct UserInfo {
bool userExists;
uint256 amount;
uint256 rewardPending;
}
// poolId => account => UserInfo
mapping (uint256 => mapping (address => UserInfo)) public _userInfo;
event Deposit(address indexed user, uint256 indexed poolId, uint256 amount);
event Withdraw(address indexed user, uint256 indexed poolId, uint256 amount);
// Deposit LP tokens to Farm for ERC20 allocation.
function deposit(uint256 poolId, uint256 amount) public {
require(poolId < _poolInfoCount, "deposit: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
require(amount > 0, "deposit: can't deposit zero amount");
UserInfo storage user = _userInfo[poolId][msg.sender];
user.userExists = true;
_beforeBalanceChange(pool, msg.sender);
user.amount = user.amount.add(amount);
pool.lpToken.safeTransferFrom(address(msg.sender), amount);
emit Deposit(msg.sender, poolId, amount);
_afterBalanceChange(pool, msg.sender);
}
// Withdraw LP tokens from Farm.
function withdraw(uint256 poolId, uint256 amount) public {
require(poolId < _poolInfoCount, "withdraw: Pool is not exists");
PoolInfo storage pool = _poolInfo[poolId];
require(amount > 0, "withdraw: can't withdraw zero amount");
UserInfo storage user = _userInfo[poolId][msg.sender];
require(user.amount >= amount, "withdraw: can't withdraw more than deposit");
_beforeBalanceChange(pool, msg.sender);
user.amount = user.amount.sub(amount);
pool.lpToken.safeTransfer(address(msg.sender), amount);
emit Withdraw(msg.sender, poolId, amount);
_afterBalanceChange(pool, msg.sender);
}
function _beforeBalanceChange(PoolInfo storage pool, address account) internal virtual {}
function _afterBalanceChange(PoolInfo storage pool, address account) internal virtual {}
}
Compiler Settings
{"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"istanbul","compilationTarget":{"/app/contracts/pactFarm/FarmPACT.sol":"FarmPACT"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"governance_","internalType":"address"},{"type":"address","name":"pact_","internalType":"contract IERC20"},{"type":"uint256","name":"blockGenerationFrequency_","internalType":"uint256"},{"type":"uint256","name":"totalRewardAmount_","internalType":"uint256"}]},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceSetTransferred","inputs":[{"type":"address","name":"previousGovernance","internalType":"address","indexed":true},{"type":"address","name":"newGovernance","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Harvest","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"poolId","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"lastRewardBlock","internalType":"uint256"},{"type":"uint256","name":"accERC20PerShare","internalType":"uint256"}],"name":"_poolInfoInFarmStages","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"userExists","internalType":"bool"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"rewardPending","internalType":"uint256"}],"name":"_userInfo","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"_userRewardDebt","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addLpToken","inputs":[{"type":"uint256","name":"_allocPoint","internalType":"uint256"},{"type":"address","name":"_lpToken","internalType":"address"},{"type":"bool","name":"_withUpdate","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"blockGenerationFrequency","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deposit","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"harvest","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"massUpdatePools","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pact","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pending","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct LpTokensStorage.PoolInfo","components":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"address","name":"lpToken","internalType":"contract IUniswapV2Pair"},{"type":"uint256","name":"allocPoint","internalType":"uint256"}]}],"name":"poolInfo","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolInfoCount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setGovernance","inputs":[{"type":"address","name":"newGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct StagesStorage.StageInfo","components":[{"type":"uint256","name":"id","internalType":"uint256"},{"type":"uint256","name":"startBlock","internalType":"uint256"},{"type":"uint256","name":"endBlock","internalType":"uint256"},{"type":"uint256","name":"rewardPerBlock","internalType":"uint256"}]}],"name":"stageInfo","inputs":[{"type":"uint256","name":"stageId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"stageInfoCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"stagesLength","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"startFarming","inputs":[{"type":"uint256","name":"startBlock","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalAllocPoint","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewardAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewardInStages","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateLpToken","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"uint256","name":"allocPoint","internalType":"uint256"},{"type":"bool","name":"withUpdate","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updatePool","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawAndHarvest","inputs":[{"type":"uint256","name":"poolId","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]}]
Contract Creation Code
0x60806040526000600355600060055560006009553480156200002057600080fd5b506040516200287b3803806200287b83398101604081905262000043916200015e565b82818082876001600160a01b0381166200007a5760405162461bcd60e51b815260040162000071906200028d565b60405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040519091907ff5b58f4b82655edcd8644d0e54fd6d2d37321f54f4755e4e67fd6af851c43fec908290a3506001600160a01b038116620000ec5760405162461bcd60e51b81526004016200007190620001f8565b600180546001600160a01b0319166001600160a01b0392909216919091179055806200012c5760405162461bcd60e51b8152600401620000719062000246565b600755505081620001515760405162461bcd60e51b81526004016200007190620001aa565b5060105550620002eb9050565b6000806000806080858703121562000174578384fd5b84516200018181620002d2565b60208601519094506200019481620002d2565b6040860151606090960151949790965092505050565b6020808252602e908201527f636f6e7374727563746f723a20626c6f636b47656e65726174696f6e4672657160408201526d75656e637920697320656d70747960901b606082015260800190565b6020808252602e908201527f4c70546f6b656e7353746f726167653a3a636f6e7374727563746f723a20706160408201526d63745f202d20697320656d70747960901b606082015260800190565b60208082526027908201527f636f6e7374727563746f723a20746f74616c526577617264416d6f756e7420696040820152667320656d70747960c81b606082015260800190565b60208082526025908201527f476f7665726e616e636520616464726573732073686f756c64206265206e6f74604082015264081b9d5b1b60da1b606082015260800190565b6001600160a01b0381168114620002e857600080fd5b50565b61258080620002fb6000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c8063750c5d74116100de5780638e73064f11610097578063cecf757a11610071578063cecf757a146102f5578063ddc6326214610308578063e2bbb1581461031b578063e4c75c271461032e57610173565b80638e73064f146102d2578063ab033ea9146102da578063cc70292c146102ed57610173565b8063750c5d7414610259578063792c02ea1461026c57806379e59ce41461027457806387fff3c6146102955780638ca77a5b1461029d5780638ceaf0aa146102bf57610173565b8063515ff44311610130578063515ff4431461020657806351eb05a61461021b57806355bb14f21461022e5780635aa6e67514610236578063630b5ba11461023e57806369fb3c2d1461024657610173565b80631526fe271461017857806317caf6f1146101a1578063243af193146101b6578063348b597f146101d6578063441a3e70146101eb578063489ac75d146101fe575b600080fd5b61018b610186366004611c8f565b610341565b60405161019891906124a4565b60405180910390f35b6101a96103a0565b60405161019891906124f9565b6101c96101c4366004611c8f565b6103a6565b60405161019891906124ce565b6101e96101e4366004611d2b565b610403565b005b6101e96101f9366004611d2b565b610617565b6101a9610739565b61020e61073f565b6040516101989190611dcd565b6101e9610229366004611c8f565b61074e565b6101a961079b565b61020e6107a1565b6101e96107b0565b6101a9610254366004611d4c565b6107d1565b6101e9610267366004611d84565b6107f4565b6101a961082e565b610287610282366004611d2b565b610834565b604051610198929190612502565b6101a9610858565b6102b06102ab366004611cbf565b61085e565b60405161019893929190611e1e565b6101e96102cd366004611ceb565b61088e565b6101a96108c3565b6101e96102e8366004611c58565b6108c9565b6101a9610974565b6101e9610303366004611c8f565b61097a565b6101e9610316366004611c8f565b610af3565b6101e9610329366004611d2b565b610c5e565b6101a961033c366004611cbf565b610d58565b610349611bef565b6002828154811061035657fe5b60009182526020918290206040805160608101825260039093029091018054835260018101546001600160a01b031693830193909352600290920154918101919091529050919050565b60055490565b6103ae611c19565b600882815481106103bb57fe5b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050919050565b600354821061042d5760405162461bcd60e51b815260040161042490611fca565b60405180910390fd5b60006002838154811061043c57fe5b906000526020600020906003020190506000821161046c5760405162461bcd60e51b815260040161042490612219565b6000838152600660209081526040808320338452909152902060018101548311156104a95760405162461bcd60e51b815260040161042490612406565b6104b38233610fe1565b60018101546104c290846110f3565b6001808301919091558201546104e2906001600160a01b03163385611132565b83336001600160a01b03167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5688560405161051c91906124f9565b60405180910390a3600154600282015460405163a9059cbb60e01b81526001600160a01b039092169163a9059cbb9161055a91339190600401611de1565b602060405180830381600087803b15801561057457600080fd5b505af1158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611c73565b506002810154600e546105be916110f3565b600e556002810154604051859133917f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae0660924954916105f8916124f9565b60405180910390a3600060028201556106118233611219565b50505050565b60035482106106385760405162461bcd60e51b8152600401610424906121e2565b60006002838154811061064757fe5b90600052602060002090600302019050600082116106775760405162461bcd60e51b81526004016104249061219e565b6000838152600660209081526040808320338452909152902060018101548311156106b45760405162461bcd60e51b815260040161042490612267565b6106be8233610fe1565b60018101546106cd90846110f3565b6001808301919091558201546106ed906001600160a01b03163385611132565b83336001600160a01b03167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5688560405161072791906124f9565b60405180910390a36106118233611219565b60105490565b6001546001600160a01b031690565b600354811061076f5760405162461bcd60e51b8152600401610424906123cf565b60006002828154811061077e57fe5b90600052602060002090600302019050610797816112f5565b5050565b60035490565b6000546001600160a01b031690565b60005b6003548110156107ce576107c68161074e565b6001016107b3565b50565b600f60209081526000938452604080852082529284528284209052825290205481565b6000546001600160a01b0316331461081e5760405162461bcd60e51b815260040161042490611ef6565b6108298383836113fe565b505050565b60085490565b600c6020908152600092835260408084209091529082529020805460019091015482565b60095490565b600660209081526000928352604080842090915290825290208054600182015460029092015460ff909116919083565b6000546001600160a01b031633146108b85760405162461bcd60e51b815260040161042490611ef6565b610829838383611416565b60075490565b6000546001600160a01b031633146108f35760405162461bcd60e51b815260040161042490611ef6565b6001600160a01b0381166109195760405162461bcd60e51b815260040161042490611f3e565b600080546040516001600160a01b03808516939216917ff5b58f4b82655edcd8644d0e54fd6d2d37321f54f4755e4e67fd6af851c43fec91a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600a5490565b6000546001600160a01b031633146109a45760405162461bcd60e51b815260040161042490611ef6565b600b54156109c45760405162461bcd60e51b815260040161042490612398565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906109f5903090600401611dcd565b60206040518083038186803b158015610a0d57600080fd5b505afa158015610a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a459190611ca7565b9050600754811015610a695760405162461bcd60e51b81526004016104249061245a565b610a8e82601054620d2f0081610a7b57fe5b04600860075481610a8857fe5b0461142e565b610ab2601054621a5e0081610a9f57fe5b04600860075481610aac57fe5b0461146a565b610ac360105462c5c10081610a9f57fe5b610ad460105462ed4e0081610a9f57fe5b61079760105463058fd40081610ae657fe5b04600260075481610aac57fe5b6003548110610b145760405162461bcd60e51b815260040161042490611f93565b600060028281548110610b2357fe5b60009182526020808320858452600682526040808520338652909252922080546003909202909201925060ff16610b6c5760405162461bcd60e51b8152600401610424906120b5565b610b768233611499565b600154600282015460405163a9059cbb60e01b81526001600160a01b039092169163a9059cbb91610bac91339190600401611de1565b602060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfe9190611c73565b506002810154600e54610c10916110f3565b600e556002810154604051849133917f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae066092495491610c4a916124f9565b60405180910390a360006002909101555050565b6003548210610c7f5760405162461bcd60e51b815260040161042490612010565b600060028381548110610c8e57fe5b9060005260206000209060030201905060008211610cbe5760405162461bcd60e51b8152600401610424906122b1565b6000838152600660209081526040808320338085529252909120805460ff1916600117815590610cef908390610fe1565b6001810154610cfe90846115f9565b600180830191909155820154610d1e906001600160a01b03163385611634565b83336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158560405161072791906124f9565b60006003548310610d7b5760405162461bcd60e51b8152600401610424906122f3565b600060028481548110610d8a57fe5b600091825260208083208784526006825260408085206001600160a01b03898116875293528085206002810154600395909502909201600181015491516370a0823160e01b815290965091949216906370a0823190610ded903090600401611dcd565b60206040518083038186803b158015610e0557600080fd5b505afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d9190611ca7565b905060005b600954811015610fd357600060088281548110610e5b57fe5b906000526020600020906004020190504381600101541115610e7d5750610fd3565b6000828152600c602090815260408083208c8452909152812060018101546002840154919290914310610eb4578360020154610eb6565b435b835490915081118015610ec857508515155b15610f5c5760008460010154846000015410610ee5578354610eeb565b84600101545b90506000610ef983836110f3565b90506000610f2e600554610f288e60020154610f228b600301548761171d90919063ffffffff16565b9061171d565b90611758565b9050610f56610f4f8a610f28846a0c097ce7bc90715b34b9f160241b61171d565b86906115f9565b94505050505b6000858152600f602090815260408083208f845282528083206001600160a01b038f16845290915281205460018a0154610fb59190610faf906a0c097ce7bc90715b34b9f160241b90610f28908861171d565b906110f3565b9050610fc188826115f9565b97505050505050806001019050610e42565b509093505050505b92915050565b610fea826112f5565b815460009081526006602090815260408083206001600160a01b0385168452909152812090805b6009548110156110ec576008818154811061102857fe5b90600052602060002090600402019150438260010154111561104c57505050610797565b81546000818152600c602090815260408083208954808552908352818420948452600f835281842090845282528083206001600160a01b0389168452909152812054600180840154908701546110bb9291610faf916a0c097ce7bc90715b34b9f160241b91610f28919061171d565b60028601549091506110cd90826115f9565b6002860155600e546110df90826115f9565b600e555050600101611011565b5050505050565b600061112b838360405180604001604052806013815260200172536166654d6174683a20556e646572666c6f7760681b81525061178b565b9392505050565b60006060846001600160a01b031663a9059cbb8585604051602401611158929190611de1565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516111919190611db1565b6000604051808303816000865af19150503d80600081146111ce576040519150601f19603f3d011682016040523d82523d6000602084013e6111d3565b606091505b50915091508180156111fd5750805115806111fd5750808060200190518101906111fd9190611c73565b6110ec5760405162461bcd60e51b815260040161042490612361565b815460009081526006602090815260408083206001600160a01b0385168452909152812090805b6009548110156110ec576008818154811061125757fe5b90600052602060002090600402019150438260010154111561127b57505050610797565b81546000908152600c60209081526040808320885484529091529020600180820154908501546112be916a0c097ce7bc90715b34b9f160241b91610f289161171d565b83546000908152600f602090815260408083208a54845282528083206001600160a01b038a16845290915290205550600101611240565b60018101546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611328903090600401611dcd565b60206040518083038186803b15801561134057600080fd5b505afa158015611354573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113789190611ca7565b82546000908152600d6020526040812054919250905b60095481101561061157600881815481106113a557fe5b9060005260206000209060040201915043826001015411156113c9575050506107ce565b6113d48285856117b7565b156113f6576113e48160016115f9565b84546000908152600d60205260409020555b60010161138e565b801561140c5761140c6107b0565b61082983836118a2565b8015611424576114246107b0565b610829838361190f565b600b541561144e5760405162461bcd60e51b8152600401610424906120f9565b82431161145b578261145d565b435b9250610829838383611a3b565b6000600b541161148c5760405162461bcd60e51b815260040161042490611eab565b610797600b548383611a3b565b6114a2826112f5565b815460009081526006602090815260408083206001600160a01b0385168452909152812090805b6009548110156110ec57600881815481106114e057fe5b90600052602060002090600402019150438260010154111561150457505050610797565b81546000818152600c602090815260408083208954808552908352818420948452600f835281842090845282528083206001600160a01b0389168452909152812054600180840154908701546115739291610faf916a0c097ce7bc90715b34b9f160241b91610f28919061171d565b600286015490915061158590826115f9565b6002860155600e5461159790826115f9565b600e55600180830154908601546115c1916a0c097ce7bc90715b34b9f160241b91610f289161171d565b84546000908152600f602090815260408083208b54845282528083206001600160a01b038b16845290915290205550506001016114c9565b600061112b838360405180604001604052806016815260200175536166654d6174683a20416464204f766572666c6f7760501b815250611b82565b60006060846001600160a01b03166323b872dd85308660405160240161165c93929190611dfa565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516116959190611db1565b6000604051808303816000865af19150503d80600081146116d2576040519150601f19603f3d011682016040523d82523d6000602084013e6116d7565b606091505b50915091508180156117015750805115806117015750808060200190518101906117019190611c73565b6110ec5760405162461bcd60e51b81526004016104249061207e565b600061112b838360405180604001604052806016815260200175536166654d6174683a204d756c204f766572666c6f7760501b815250611bb2565b6000816117775760405162461bcd60e51b815260040161042490612047565b600082848161178257fe5b04949350505050565b600081848411156117af5760405162461bcd60e51b81526004016104249190611e36565b505050900390565b600080846002015443106117cf5784600201546117d1565b435b85546000908152600c60209081526040808320885484529091529020600187015481549293509091101561180757600186015481555b8054821161181a5760019250505061112b565b83611828575550600061112b565b80546000906118389084906110f3565b90506000611861600554610f288960020154610f228c600301548761171d90919063ffffffff16565b905061188d61188287610f28846a0c097ce7bc90715b34b9f160241b61171d565b6001850154906115f9565b60018401555050439055506000949350505050565b60035482106118c35760405162461bcd60e51b815260040161042490611e69565b6000600283815481106118d257fe5b90600052602060002090600302019050611905826118ff83600201546005546110f390919063ffffffff16565b906115f9565b6005556002015550565b6001600160a01b03811660009081526004602052604090205460ff16156119485760405162461bcd60e51b81526004016104249061232a565b60055461195590836115f9565b600555604080516060810182526003805482526001600160a01b0393841660208084018281528486019788526002805460018082018355600092835296517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9187029182015591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf830180546001600160a01b031916919099161790975596517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad09097019690965581548301909155835260049093529020805460ff19169091179055565b611a43611c19565b60408051608081018252600954815260208101869052908101611a6686866115f9565b8152602001611a758486611758565b905260098054600190810190915560088054808301825560009190915282517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee360049092029182015560208301517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee482015560408301517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee5820181905560608401517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee690920191909155919250611b4c91906115f9565b600b55600a54611b5c90836115f9565b600a81905560075410156106115760405162461bcd60e51b815260040161042490612149565b60008383018285821015611ba95760405162461bcd60e51b81526004016104249190611e36565b50949350505050565b600083611bc15750600061112b565b83830283858281611bce57fe5b04148390611ba95760405162461bcd60e51b81526004016104249190611e36565b60405180606001604052806000815260200160006001600160a01b03168152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b80356001600160a01b0381168114610fdb57600080fd5b600060208284031215611c69578081fd5b61112b8383611c41565b600060208284031215611c84578081fd5b815161112b8161253c565b600060208284031215611ca0578081fd5b5035919050565b600060208284031215611cb8578081fd5b5051919050565b60008060408385031215611cd1578081fd5b82359150611ce28460208501611c41565b90509250929050565b600080600060608486031215611cff578081fd5b83359250611d108560208601611c41565b91506040840135611d208161253c565b809150509250925092565b60008060408385031215611d3d578182fd5b50508035926020909101359150565b600080600060608486031215611d60578283fd5b833592506020840135915060408401356001600160a01b0381168114611d20578182fd5b600080600060608486031215611d98578283fd5b83359250602084013591506040840135611d208161253c565b60008251611dc3818460208701612510565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b92151583526020830191909152604082015260600190565b6000602082528251806020840152611e55816040850160208701612510565b601f01601f19169190910160400192915050565b60208082526022908201527f5f7570646174654c70546f6b656e3a20506f6f6c206973206e6f742065786973604082015261747360f01b606082015260800190565b6020808252602b908201527f5f61646453746167653a206669727374207374616765206973206e6f7420696e60408201526a1cdd185b1b1959081e595d60aa1b606082015260800190565b60208082526028908201527f476f7665726e616e63653a2063616c6c6572206973206e6f742074686520676f6040820152677665726e616e636560c01b606082015260800190565b60208082526035908201527f476f7665726e616e63654f776e61626c653a206e657720676f7665726e616e636040820152746520697320746865207a65726f206164647265737360581b606082015260800190565b6020808252601b908201527f686172766573743a20506f6f6c206973206e6f74206578697374730000000000604082015260600190565b60208082526026908201527f7769746864726177416e64486172766573743a20506f6f6c206973206e6f742060408201526565786973747360d01b606082015260800190565b6020808252601b908201527f6465706f7369743a20506f6f6c206973206e6f74206578697374730000000000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252601e908201527f5361666545524332303a205472616e7366657246726f6d206661696c65640000604082015260600190565b60208082526024908201527f686172766573743a2063616e277420686172766573742066726f6d206e6577206040820152633ab9b2b960e11b606082015260800190565b60208082526030908201527f5f616464466972737453746167653a206669727374207374616765206973206160408201526f1b1c9958591e481a5b9cdd185b1b195960821b606082015260800190565b60208082526035908201527f5f5f61646453746167653a205f746f74616c526577617264496e537461676573604082015274080f8817dd1bdd185b14995dd85c99105b5bdd5b9d605a1b606082015260800190565b60208082526024908201527f77697468647261773a2063616e2774207769746864726177207a65726f20616d6040820152631bdd5b9d60e21b606082015260800190565b6020808252601c908201527f77697468647261773a20506f6f6c206973206e6f742065786973747300000000604082015260600190565b6020808252602e908201527f7769746864726177416e64486172766573743a2063616e27742077697468647260408201526d185dc81e995c9bc8185b5bdd5b9d60921b606082015260800190565b6020808252602a908201527f77697468647261773a2063616e2774207769746864726177206d6f7265207468604082015269185b8819195c1bdcda5d60b21b606082015260800190565b60208082526022908201527f6465706f7369743a2063616e2774206465706f736974207a65726f20616d6f756040820152611b9d60f21b606082015260800190565b6020808252601b908201527f70656e64696e673a20506f6f6c206973206e6f74206578697374730000000000604082015260600190565b6020808252601c908201527f5f6164644c70546f6b656e3a204c5020546f6b656e2065786973747300000000604082015260600190565b6020808252601a908201527f5361666545524332303a205472616e73666572206661696c6564000000000000604082015260600190565b6020808252601d908201527f73746172744661726d696e673a20616c72656164792073746172746564000000604082015260600190565b6020808252601e908201527f757064617465506f6f6c3a20506f6f6c206973206e6f74206578697374730000604082015260600190565b60208082526034908201527f7769746864726177416e64486172766573743a2063616e277420776974686472604082015273185dc81b5bdc99481d1a185b8819195c1bdcda5d60621b606082015260800190565b6020808252602a908201527f73746172744661726d696e673a2063757272656e7442616c616e6365206973206040820152690dcdee840cadcdeeaced60b31b606082015260800190565b815181526020808301516001600160a01b0316908201526040918201519181019190915260600190565b8151815260208083015190820152604080830151908201526060918201519181019190915260800190565b90815260200190565b918252602082015260400190565b60005b8381101561252b578181015183820152602001612513565b838111156106115750506000910152565b80151581146107ce57600080fdfea26469706673582212208c98afc9f9a9f724a0993769dbf4ef1dcc1b8739aaa621d828efe9c843a89b5764736f6c634300060c003300000000000000000000000013c674c7f56232592c19e5fbba345b8d3a9dc99f00000000000000000000000066e7ce35578a37209d01f99f3d2ff271f981f581000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000108b2a2c28029094000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101735760003560e01c8063750c5d74116100de5780638e73064f11610097578063cecf757a11610071578063cecf757a146102f5578063ddc6326214610308578063e2bbb1581461031b578063e4c75c271461032e57610173565b80638e73064f146102d2578063ab033ea9146102da578063cc70292c146102ed57610173565b8063750c5d7414610259578063792c02ea1461026c57806379e59ce41461027457806387fff3c6146102955780638ca77a5b1461029d5780638ceaf0aa146102bf57610173565b8063515ff44311610130578063515ff4431461020657806351eb05a61461021b57806355bb14f21461022e5780635aa6e67514610236578063630b5ba11461023e57806369fb3c2d1461024657610173565b80631526fe271461017857806317caf6f1146101a1578063243af193146101b6578063348b597f146101d6578063441a3e70146101eb578063489ac75d146101fe575b600080fd5b61018b610186366004611c8f565b610341565b60405161019891906124a4565b60405180910390f35b6101a96103a0565b60405161019891906124f9565b6101c96101c4366004611c8f565b6103a6565b60405161019891906124ce565b6101e96101e4366004611d2b565b610403565b005b6101e96101f9366004611d2b565b610617565b6101a9610739565b61020e61073f565b6040516101989190611dcd565b6101e9610229366004611c8f565b61074e565b6101a961079b565b61020e6107a1565b6101e96107b0565b6101a9610254366004611d4c565b6107d1565b6101e9610267366004611d84565b6107f4565b6101a961082e565b610287610282366004611d2b565b610834565b604051610198929190612502565b6101a9610858565b6102b06102ab366004611cbf565b61085e565b60405161019893929190611e1e565b6101e96102cd366004611ceb565b61088e565b6101a96108c3565b6101e96102e8366004611c58565b6108c9565b6101a9610974565b6101e9610303366004611c8f565b61097a565b6101e9610316366004611c8f565b610af3565b6101e9610329366004611d2b565b610c5e565b6101a961033c366004611cbf565b610d58565b610349611bef565b6002828154811061035657fe5b60009182526020918290206040805160608101825260039093029091018054835260018101546001600160a01b031693830193909352600290920154918101919091529050919050565b60055490565b6103ae611c19565b600882815481106103bb57fe5b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050919050565b600354821061042d5760405162461bcd60e51b815260040161042490611fca565b60405180910390fd5b60006002838154811061043c57fe5b906000526020600020906003020190506000821161046c5760405162461bcd60e51b815260040161042490612219565b6000838152600660209081526040808320338452909152902060018101548311156104a95760405162461bcd60e51b815260040161042490612406565b6104b38233610fe1565b60018101546104c290846110f3565b6001808301919091558201546104e2906001600160a01b03163385611132565b83336001600160a01b03167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5688560405161051c91906124f9565b60405180910390a3600154600282015460405163a9059cbb60e01b81526001600160a01b039092169163a9059cbb9161055a91339190600401611de1565b602060405180830381600087803b15801561057457600080fd5b505af1158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611c73565b506002810154600e546105be916110f3565b600e556002810154604051859133917f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae0660924954916105f8916124f9565b60405180910390a3600060028201556106118233611219565b50505050565b60035482106106385760405162461bcd60e51b8152600401610424906121e2565b60006002838154811061064757fe5b90600052602060002090600302019050600082116106775760405162461bcd60e51b81526004016104249061219e565b6000838152600660209081526040808320338452909152902060018101548311156106b45760405162461bcd60e51b815260040161042490612267565b6106be8233610fe1565b60018101546106cd90846110f3565b6001808301919091558201546106ed906001600160a01b03163385611132565b83336001600160a01b03167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5688560405161072791906124f9565b60405180910390a36106118233611219565b60105490565b6001546001600160a01b031690565b600354811061076f5760405162461bcd60e51b8152600401610424906123cf565b60006002828154811061077e57fe5b90600052602060002090600302019050610797816112f5565b5050565b60035490565b6000546001600160a01b031690565b60005b6003548110156107ce576107c68161074e565b6001016107b3565b50565b600f60209081526000938452604080852082529284528284209052825290205481565b6000546001600160a01b0316331461081e5760405162461bcd60e51b815260040161042490611ef6565b6108298383836113fe565b505050565b60085490565b600c6020908152600092835260408084209091529082529020805460019091015482565b60095490565b600660209081526000928352604080842090915290825290208054600182015460029092015460ff909116919083565b6000546001600160a01b031633146108b85760405162461bcd60e51b815260040161042490611ef6565b610829838383611416565b60075490565b6000546001600160a01b031633146108f35760405162461bcd60e51b815260040161042490611ef6565b6001600160a01b0381166109195760405162461bcd60e51b815260040161042490611f3e565b600080546040516001600160a01b03808516939216917ff5b58f4b82655edcd8644d0e54fd6d2d37321f54f4755e4e67fd6af851c43fec91a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600a5490565b6000546001600160a01b031633146109a45760405162461bcd60e51b815260040161042490611ef6565b600b54156109c45760405162461bcd60e51b815260040161042490612398565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906109f5903090600401611dcd565b60206040518083038186803b158015610a0d57600080fd5b505afa158015610a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a459190611ca7565b9050600754811015610a695760405162461bcd60e51b81526004016104249061245a565b610a8e82601054620d2f0081610a7b57fe5b04600860075481610a8857fe5b0461142e565b610ab2601054621a5e0081610a9f57fe5b04600860075481610aac57fe5b0461146a565b610ac360105462c5c10081610a9f57fe5b610ad460105462ed4e0081610a9f57fe5b61079760105463058fd40081610ae657fe5b04600260075481610aac57fe5b6003548110610b145760405162461bcd60e51b815260040161042490611f93565b600060028281548110610b2357fe5b60009182526020808320858452600682526040808520338652909252922080546003909202909201925060ff16610b6c5760405162461bcd60e51b8152600401610424906120b5565b610b768233611499565b600154600282015460405163a9059cbb60e01b81526001600160a01b039092169163a9059cbb91610bac91339190600401611de1565b602060405180830381600087803b158015610bc657600080fd5b505af1158015610bda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfe9190611c73565b506002810154600e54610c10916110f3565b600e556002810154604051849133917f71bab65ced2e5750775a0613be067df48ef06cf92a496ebf7663ae066092495491610c4a916124f9565b60405180910390a360006002909101555050565b6003548210610c7f5760405162461bcd60e51b815260040161042490612010565b600060028381548110610c8e57fe5b9060005260206000209060030201905060008211610cbe5760405162461bcd60e51b8152600401610424906122b1565b6000838152600660209081526040808320338085529252909120805460ff1916600117815590610cef908390610fe1565b6001810154610cfe90846115f9565b600180830191909155820154610d1e906001600160a01b03163385611634565b83336001600160a01b03167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158560405161072791906124f9565b60006003548310610d7b5760405162461bcd60e51b8152600401610424906122f3565b600060028481548110610d8a57fe5b600091825260208083208784526006825260408085206001600160a01b03898116875293528085206002810154600395909502909201600181015491516370a0823160e01b815290965091949216906370a0823190610ded903090600401611dcd565b60206040518083038186803b158015610e0557600080fd5b505afa158015610e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3d9190611ca7565b905060005b600954811015610fd357600060088281548110610e5b57fe5b906000526020600020906004020190504381600101541115610e7d5750610fd3565b6000828152600c602090815260408083208c8452909152812060018101546002840154919290914310610eb4578360020154610eb6565b435b835490915081118015610ec857508515155b15610f5c5760008460010154846000015410610ee5578354610eeb565b84600101545b90506000610ef983836110f3565b90506000610f2e600554610f288e60020154610f228b600301548761171d90919063ffffffff16565b9061171d565b90611758565b9050610f56610f4f8a610f28846a0c097ce7bc90715b34b9f160241b61171d565b86906115f9565b94505050505b6000858152600f602090815260408083208f845282528083206001600160a01b038f16845290915281205460018a0154610fb59190610faf906a0c097ce7bc90715b34b9f160241b90610f28908861171d565b906110f3565b9050610fc188826115f9565b97505050505050806001019050610e42565b509093505050505b92915050565b610fea826112f5565b815460009081526006602090815260408083206001600160a01b0385168452909152812090805b6009548110156110ec576008818154811061102857fe5b90600052602060002090600402019150438260010154111561104c57505050610797565b81546000818152600c602090815260408083208954808552908352818420948452600f835281842090845282528083206001600160a01b0389168452909152812054600180840154908701546110bb9291610faf916a0c097ce7bc90715b34b9f160241b91610f28919061171d565b60028601549091506110cd90826115f9565b6002860155600e546110df90826115f9565b600e555050600101611011565b5050505050565b600061112b838360405180604001604052806013815260200172536166654d6174683a20556e646572666c6f7760681b81525061178b565b9392505050565b60006060846001600160a01b031663a9059cbb8585604051602401611158929190611de1565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516111919190611db1565b6000604051808303816000865af19150503d80600081146111ce576040519150601f19603f3d011682016040523d82523d6000602084013e6111d3565b606091505b50915091508180156111fd5750805115806111fd5750808060200190518101906111fd9190611c73565b6110ec5760405162461bcd60e51b815260040161042490612361565b815460009081526006602090815260408083206001600160a01b0385168452909152812090805b6009548110156110ec576008818154811061125757fe5b90600052602060002090600402019150438260010154111561127b57505050610797565b81546000908152600c60209081526040808320885484529091529020600180820154908501546112be916a0c097ce7bc90715b34b9f160241b91610f289161171d565b83546000908152600f602090815260408083208a54845282528083206001600160a01b038a16845290915290205550600101611240565b60018101546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611328903090600401611dcd565b60206040518083038186803b15801561134057600080fd5b505afa158015611354573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113789190611ca7565b82546000908152600d6020526040812054919250905b60095481101561061157600881815481106113a557fe5b9060005260206000209060040201915043826001015411156113c9575050506107ce565b6113d48285856117b7565b156113f6576113e48160016115f9565b84546000908152600d60205260409020555b60010161138e565b801561140c5761140c6107b0565b61082983836118a2565b8015611424576114246107b0565b610829838361190f565b600b541561144e5760405162461bcd60e51b8152600401610424906120f9565b82431161145b578261145d565b435b9250610829838383611a3b565b6000600b541161148c5760405162461bcd60e51b815260040161042490611eab565b610797600b548383611a3b565b6114a2826112f5565b815460009081526006602090815260408083206001600160a01b0385168452909152812090805b6009548110156110ec57600881815481106114e057fe5b90600052602060002090600402019150438260010154111561150457505050610797565b81546000818152600c602090815260408083208954808552908352818420948452600f835281842090845282528083206001600160a01b0389168452909152812054600180840154908701546115739291610faf916a0c097ce7bc90715b34b9f160241b91610f28919061171d565b600286015490915061158590826115f9565b6002860155600e5461159790826115f9565b600e55600180830154908601546115c1916a0c097ce7bc90715b34b9f160241b91610f289161171d565b84546000908152600f602090815260408083208b54845282528083206001600160a01b038b16845290915290205550506001016114c9565b600061112b838360405180604001604052806016815260200175536166654d6174683a20416464204f766572666c6f7760501b815250611b82565b60006060846001600160a01b03166323b872dd85308660405160240161165c93929190611dfa565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516116959190611db1565b6000604051808303816000865af19150503d80600081146116d2576040519150601f19603f3d011682016040523d82523d6000602084013e6116d7565b606091505b50915091508180156117015750805115806117015750808060200190518101906117019190611c73565b6110ec5760405162461bcd60e51b81526004016104249061207e565b600061112b838360405180604001604052806016815260200175536166654d6174683a204d756c204f766572666c6f7760501b815250611bb2565b6000816117775760405162461bcd60e51b815260040161042490612047565b600082848161178257fe5b04949350505050565b600081848411156117af5760405162461bcd60e51b81526004016104249190611e36565b505050900390565b600080846002015443106117cf5784600201546117d1565b435b85546000908152600c60209081526040808320885484529091529020600187015481549293509091101561180757600186015481555b8054821161181a5760019250505061112b565b83611828575550600061112b565b80546000906118389084906110f3565b90506000611861600554610f288960020154610f228c600301548761171d90919063ffffffff16565b905061188d61188287610f28846a0c097ce7bc90715b34b9f160241b61171d565b6001850154906115f9565b60018401555050439055506000949350505050565b60035482106118c35760405162461bcd60e51b815260040161042490611e69565b6000600283815481106118d257fe5b90600052602060002090600302019050611905826118ff83600201546005546110f390919063ffffffff16565b906115f9565b6005556002015550565b6001600160a01b03811660009081526004602052604090205460ff16156119485760405162461bcd60e51b81526004016104249061232a565b60055461195590836115f9565b600555604080516060810182526003805482526001600160a01b0393841660208084018281528486019788526002805460018082018355600092835296517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9187029182015591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf830180546001600160a01b031916919099161790975596517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad09097019690965581548301909155835260049093529020805460ff19169091179055565b611a43611c19565b60408051608081018252600954815260208101869052908101611a6686866115f9565b8152602001611a758486611758565b905260098054600190810190915560088054808301825560009190915282517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee360049092029182015560208301517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee482015560408301517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee5820181905560608401517ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee690920191909155919250611b4c91906115f9565b600b55600a54611b5c90836115f9565b600a81905560075410156106115760405162461bcd60e51b815260040161042490612149565b60008383018285821015611ba95760405162461bcd60e51b81526004016104249190611e36565b50949350505050565b600083611bc15750600061112b565b83830283858281611bce57fe5b04148390611ba95760405162461bcd60e51b81526004016104249190611e36565b60405180606001604052806000815260200160006001600160a01b03168152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b80356001600160a01b0381168114610fdb57600080fd5b600060208284031215611c69578081fd5b61112b8383611c41565b600060208284031215611c84578081fd5b815161112b8161253c565b600060208284031215611ca0578081fd5b5035919050565b600060208284031215611cb8578081fd5b5051919050565b60008060408385031215611cd1578081fd5b82359150611ce28460208501611c41565b90509250929050565b600080600060608486031215611cff578081fd5b83359250611d108560208601611c41565b91506040840135611d208161253c565b809150509250925092565b60008060408385031215611d3d578182fd5b50508035926020909101359150565b600080600060608486031215611d60578283fd5b833592506020840135915060408401356001600160a01b0381168114611d20578182fd5b600080600060608486031215611d98578283fd5b83359250602084013591506040840135611d208161253c565b60008251611dc3818460208701612510565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b92151583526020830191909152604082015260600190565b6000602082528251806020840152611e55816040850160208701612510565b601f01601f19169190910160400192915050565b60208082526022908201527f5f7570646174654c70546f6b656e3a20506f6f6c206973206e6f742065786973604082015261747360f01b606082015260800190565b6020808252602b908201527f5f61646453746167653a206669727374207374616765206973206e6f7420696e60408201526a1cdd185b1b1959081e595d60aa1b606082015260800190565b60208082526028908201527f476f7665726e616e63653a2063616c6c6572206973206e6f742074686520676f6040820152677665726e616e636560c01b606082015260800190565b60208082526035908201527f476f7665726e616e63654f776e61626c653a206e657720676f7665726e616e636040820152746520697320746865207a65726f206164647265737360581b606082015260800190565b6020808252601b908201527f686172766573743a20506f6f6c206973206e6f74206578697374730000000000604082015260600190565b60208082526026908201527f7769746864726177416e64486172766573743a20506f6f6c206973206e6f742060408201526565786973747360d01b606082015260800190565b6020808252601b908201527f6465706f7369743a20506f6f6c206973206e6f74206578697374730000000000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252601e908201527f5361666545524332303a205472616e7366657246726f6d206661696c65640000604082015260600190565b60208082526024908201527f686172766573743a2063616e277420686172766573742066726f6d206e6577206040820152633ab9b2b960e11b606082015260800190565b60208082526030908201527f5f616464466972737453746167653a206669727374207374616765206973206160408201526f1b1c9958591e481a5b9cdd185b1b195960821b606082015260800190565b60208082526035908201527f5f5f61646453746167653a205f746f74616c526577617264496e537461676573604082015274080f8817dd1bdd185b14995dd85c99105b5bdd5b9d605a1b606082015260800190565b60208082526024908201527f77697468647261773a2063616e2774207769746864726177207a65726f20616d6040820152631bdd5b9d60e21b606082015260800190565b6020808252601c908201527f77697468647261773a20506f6f6c206973206e6f742065786973747300000000604082015260600190565b6020808252602e908201527f7769746864726177416e64486172766573743a2063616e27742077697468647260408201526d185dc81e995c9bc8185b5bdd5b9d60921b606082015260800190565b6020808252602a908201527f77697468647261773a2063616e2774207769746864726177206d6f7265207468604082015269185b8819195c1bdcda5d60b21b606082015260800190565b60208082526022908201527f6465706f7369743a2063616e2774206465706f736974207a65726f20616d6f756040820152611b9d60f21b606082015260800190565b6020808252601b908201527f70656e64696e673a20506f6f6c206973206e6f74206578697374730000000000604082015260600190565b6020808252601c908201527f5f6164644c70546f6b656e3a204c5020546f6b656e2065786973747300000000604082015260600190565b6020808252601a908201527f5361666545524332303a205472616e73666572206661696c6564000000000000604082015260600190565b6020808252601d908201527f73746172744661726d696e673a20616c72656164792073746172746564000000604082015260600190565b6020808252601e908201527f757064617465506f6f6c3a20506f6f6c206973206e6f74206578697374730000604082015260600190565b60208082526034908201527f7769746864726177416e64486172766573743a2063616e277420776974686472604082015273185dc81b5bdc99481d1a185b8819195c1bdcda5d60621b606082015260800190565b6020808252602a908201527f73746172744661726d696e673a2063757272656e7442616c616e6365206973206040820152690dcdee840cadcdeeaced60b31b606082015260800190565b815181526020808301516001600160a01b0316908201526040918201519181019190915260600190565b8151815260208083015190820152604080830151908201526060918201519181019190915260800190565b90815260200190565b918252602082015260400190565b60005b8381101561252b578181015183820152602001612513565b838111156106115750506000910152565b80151581146107ce57600080fdfea26469706673582212208c98afc9f9a9f724a0993769dbf4ef1dcc1b8739aaa621d828efe9c843a89b5764736f6c634300060c0033