Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- BuyBurn
- Optimization enabled
- false
- Compiler version
- v0.8.24+commit.e11b9ed9
- EVM Version
- Verified at
- 2026-09-17T19:05:47.057931Z
Constructor Arguments
000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a000000000000000000000000ad5c70588101d168b52577004a3a209ab90ab49a000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f7
Arg [0] (address) : 0x688d8bf5237a42432ee6b4092e15e73c6bcbb80a
Arg [1] (address) : 0xad5c70588101d168b52577004a3a209ab90ab49a
Arg [2] (address) : 0xdae9dd3d1a52cfce9d5f2fac7fde164d500e50f7
contracts/BuyBurn.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
interface IEKG {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function burnFrom(address account, uint256 amount) external;
}
interface IPulseXFactory {
function getPair(address a, address b) external view returns (address);
}
interface IPulseXPair {
function getReserves() external view returns (uint112, uint112, uint32);
function token0() external view returns (address);
}
interface IPulseXRouter {
function factory() external view returns (address);
function WPLS() external view returns (address);
function swapExactETHForTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline)
external
payable
returns (uint256[] memory amounts);
}
/// @title BuyBurn
/// @notice Seven percent of every mine lands here, and the only thing this
/// contract can do with it is walk onto PulseX, buy EKG on the open
/// market at whatever the market is asking, and destroy what it buys.
///
/// There is no owner, no pause, no withdraw and no way to point it at
/// a different token or a different pool. It does not add to the
/// liquidity pool, it does not hold EKG, and it never sells. PLS goes
/// in from the Mine and leaves as a market buy; EKG arrives from the
/// pool and leaves by being burned. Those are the only two directions
/// that exist in this code.
///
/// Anyone may fire it. That is deliberate: a buyback that depends on
/// one particular wallet remembering to call it is a buyback that
/// stops the day that wallet stops caring.
contract BuyBurn is ReentrancyGuard {
IEKG public immutable token;
/// @notice The only address allowed to add PLS. See `receive`.
address public immutable mine;
IPulseXRouter public immutable router;
IPulseXFactory public immutable factory;
address public immutable WPLS;
/// @notice The most a single buy is allowed to lift the pool price, in
/// basis points. Fifteen percent.
///
/// Without it, a queue that has grown large against a thin pool
/// would go through in one transaction, spike the price on a candle
/// nobody can trade against, and hand most of the money to whoever
/// was watching the mempool. With it, the buy is cut to the largest
/// size whose price impact lands on this number, the rest stays
/// queued, and the next call can spend more because the pool it is
/// buying into is deeper than it was.
uint256 public constant GATE_BPS = 1500;
/// @notice PulseX takes 0.29 percent of a swap. Measured against the live
/// router rather than assumed: 1,000 PLS through the WPLS/DAI pool
/// returns exactly the amount 9971/10000 predicts.
uint256 public constant FEE_NUM = 9971;
uint256 public constant FEE_DEN = 10000;
/// @notice Below this the gas costs more than the burn is worth.
uint256 public constant MIN_BUY = 1e18;
/// @notice One buy per minute at most, so the queue cannot be ground down
/// by a run of sandwiched calls inside a single block.
uint256 public constant COOLDOWN = 60;
/// @notice PLS waiting to be spent.
uint256 public queued;
/// @notice PLS this contract has ever spent buying EKG.
uint256 public spent;
/// @notice EKG this contract has ever destroyed.
uint256 public burned;
/// @notice When the last buy landed.
uint64 public lastBuyAt;
event Funded(address indexed from, uint256 amount);
event BoughtAndBurned(
address indexed caller, uint256 plsSpent, uint256 ekgBurned, uint256 queuedAfter, uint256 priceImpactBps
);
error NotTheMine();
error NoPair();
error NothingQueued();
error TooSoon();
error BelowMinimum();
error GotNothing();
constructor(address token_, address mine_, address router_) {
token = IEKG(token_);
mine = mine_;
router = IPulseXRouter(router_);
factory = IPulseXFactory(IPulseXRouter(router_).factory());
WPLS = IPulseXRouter(router_).WPLS();
// The token gates burning to this address and still spends an
// allowance, so this contract has to be allowed to burn its own
// balance. Set once, here, where nobody has to remember to do it.
IEKG(token_).approve(address(this), type(uint256).max);
}
// ------------------------------------------------------------------ views
/// @notice The EKG/PLS pair, once somebody has created it. Read from the
/// factory every time rather than stored, so this contract can be
/// deployed before the pool exists.
function pair() public view returns (address) {
return factory.getPair(address(token), WPLS);
}
/// @notice What the pool is holding, PLS side first.
function reserves() public view returns (uint256 plsSide, uint256 ekgSide) {
address p = pair();
if (p == address(0)) return (0, 0);
(uint112 r0, uint112 r1,) = IPulseXPair(p).getReserves();
return IPulseXPair(p).token0() == WPLS ? (uint256(r0), uint256(r1)) : (uint256(r1), uint256(r0));
}
/// @notice The largest amount of PLS that can be spent into a pool holding
/// `plsSide` without lifting the price by more than GATE_BPS.
///
/// Buying with x against reserves (R, T) leaves the pool at
///
/// newPrice / oldPrice = (R + x)(R + fx) / R^2, f = FEE_NUM/FEE_DEN
///
/// Setting that equal to 1 + g and solving the quadratic gives
///
/// x = R * ( sqrt(10000*A^2 + 4*n*d*g_bps) - 100*A ) / (200*n)
///
/// with A = n + d. At a 15 percent gate and a 0.29 percent fee that
/// is 7.2486 percent of the PLS side of the pool. The square root is
/// taken on a value scaled by 1e12 so the ratio keeps seven digits,
/// and it truncates downwards, which can only ever make the buy
/// smaller than the gate allows. Never larger.
function gateCap(uint256 plsSide) public pure returns (uint256) {
if (plsSide == 0) return 0;
uint256 A = FEE_NUM + FEE_DEN;
uint256 disc = (10_000 * A * A + 4 * FEE_NUM * FEE_DEN * GATE_BPS) * 1e12;
uint256 num = _sqrt(disc) - 100 * A * 1e6;
uint256 den = 200 * FEE_NUM * 1e6;
return (plsSide * num) / den;
}
/// @notice What the next call to `executeBuyback` would actually spend.
/// Zero when there is no pool, nothing queued, or the clock is not
/// up yet.
function spendable() public view returns (uint256) {
if (block.timestamp < uint256(lastBuyAt) + COOLDOWN) return 0;
(uint256 plsSide,) = reserves();
if (plsSide == 0) return 0;
uint256 cap = gateCap(plsSide);
uint256 amount = queued < cap ? queued : cap;
return amount < MIN_BUY ? 0 : amount;
}
/// @notice Standard constant product output, at the router's own fee.
function amountOut(uint256 amountIn, uint256 rIn, uint256 rOut) public pure returns (uint256) {
if (amountIn == 0 || rIn == 0 || rOut == 0) return 0;
uint256 inAfterFee = amountIn * FEE_NUM;
return (inAfterFee * rOut) / (rIn * FEE_DEN + inAfterFee);
}
// ----------------------------------------------------------------- action
/// @notice Spend what the gate allows, buy EKG with it, and burn every
/// token that comes back. Anyone may call this and the caller takes
/// nothing: there is no reward, no refund and no discount, so the
/// only reason to call it is to want the supply smaller.
///
/// @param minOut A floor the caller can demand on top of the contract's
/// own. The contract computes what the pool should return from the
/// reserves it has just read and will not accept less, so passing
/// zero is safe; passing a higher number makes the call revert
/// rather than execute at a price the caller dislikes.
function executeBuyback(uint256 minOut) external nonReentrant returns (uint256 plsSpent, uint256 ekgBurned) {
if (block.timestamp < uint256(lastBuyAt) + COOLDOWN) revert TooSoon();
address p = pair();
if (p == address(0)) revert NoPair();
if (queued == 0) revert NothingQueued();
(uint256 plsSide, uint256 ekgSide) = reserves();
if (plsSide == 0 || ekgSide == 0) revert NoPair();
uint256 cap = gateCap(plsSide);
plsSpent = queued < cap ? queued : cap;
if (plsSpent < MIN_BUY) revert BelowMinimum();
// What this pool owes for that much PLS, from the reserves as they are
// in this transaction. A router that returns less than its own maths
// says is a router this contract will not trade with.
uint256 floorOut = amountOut(plsSpent, plsSide, ekgSide);
if (floorOut == 0) revert GotNothing();
uint256 demand = minOut > floorOut ? minOut : floorOut;
// Books first, then the call out. Nothing here reads a balance to
// decide anything, so a token that behaves oddly cannot move the
// accounting, and the queue is already reduced before any external
// code runs.
queued -= plsSpent;
spent += plsSpent;
lastBuyAt = uint64(block.timestamp);
address[] memory path = new address[](2);
path[0] = WPLS;
path[1] = address(token);
router.swapExactETHForTokens{value: plsSpent}(demand, path, address(this), block.timestamp);
// Burn the whole balance rather than the swap's return value, so EKG
// anybody sends to this address is destroyed on the next buy instead of
// sitting here forever.
ekgBurned = token.balanceOf(address(this));
if (ekgBurned == 0) revert GotNothing();
burned += ekgBurned;
token.burnFrom(address(this), ekgBurned);
emit BoughtAndBurned(msg.sender, plsSpent, ekgBurned, queued, _impactBps(plsSide, plsSpent));
}
/// @notice Destroy any EKG sitting here without waiting for a buy. Anyone
/// may call it and it can only ever reduce the supply.
function burnStray() external nonReentrant returns (uint256 amount) {
amount = token.balanceOf(address(this));
if (amount == 0) revert GotNothing();
burned += amount;
token.burnFrom(address(this), amount);
}
// --------------------------------------------------------------- internal
/// @notice What a buy of `x` into a pool holding `R` did to the price, in
/// basis points. Reported on the event so the gate can be checked
/// against the chain rather than taken on trust.
function _impactBps(uint256 R, uint256 x) internal pure returns (uint256) {
if (R == 0) return 0;
uint256 after_ = (R + x) * (R * FEE_DEN + x * FEE_NUM);
uint256 before_ = R * R * FEE_DEN;
return ((after_ * 10_000) / before_) - 10_000;
}
function _sqrt(uint256 x) internal pure returns (uint256 y) {
if (x == 0) return 0;
uint256 z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}
/// @notice PLS in, and only from the Mine. There is no other way to fund
/// this contract and no way at all to take PLS back out of it
/// except by buying EKG with it.
receive() external payable {
if (msg.sender != mine) revert NotTheMine();
queued += msg.value;
emit Funded(msg.sender, msg.value);
}
}
@openzeppelin/contracts/utils/ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
/**
* @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 EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* 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].
*
* IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced
* by the {ReentrancyGuardTransient} variant in v6.0.
*
* @custom:stateless
*/
abstract contract ReentrancyGuard {
using StorageSlot for bytes32;
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant REENTRANCY_GUARD_STORAGE =
0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;
// 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;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_reentrancyGuardStorageSlot().getUint256Slot().value = 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();
}
/**
* @dev A `view` only version of {nonReentrant}. Use to block view functions
* from being called, preventing reading from inconsistent contract state.
*
* CAUTION: This is a "view" modifier and does not change the reentrancy
* status. Use it only on view functions. For payable or non-payable functions,
* use the standard {nonReentrant} modifier instead.
*/
modifier nonReentrantView() {
_nonReentrantBeforeView();
_;
}
function _nonReentrantBeforeView() private view {
if (_reentrancyGuardEntered()) {
revert ReentrancyGuardReentrantCall();
}
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
_nonReentrantBeforeView();
// Any calls to nonReentrant after this point will fail
_reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_reentrancyGuardStorageSlot().getUint256Slot().value = 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 _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;
}
function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
return REENTRANCY_GUARD_STORAGE;
}
}
@openzeppelin/contracts/utils/StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}
Compiler Settings
{"viaIR":false,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"token_","internalType":"address"},{"type":"address","name":"mine_","internalType":"address"},{"type":"address","name":"router_","internalType":"address"}]},{"type":"error","name":"BelowMinimum","inputs":[]},{"type":"error","name":"GotNothing","inputs":[]},{"type":"error","name":"NoPair","inputs":[]},{"type":"error","name":"NotTheMine","inputs":[]},{"type":"error","name":"NothingQueued","inputs":[]},{"type":"error","name":"ReentrancyGuardReentrantCall","inputs":[]},{"type":"error","name":"TooSoon","inputs":[]},{"type":"event","name":"BoughtAndBurned","inputs":[{"type":"address","name":"caller","internalType":"address","indexed":true},{"type":"uint256","name":"plsSpent","internalType":"uint256","indexed":false},{"type":"uint256","name":"ekgBurned","internalType":"uint256","indexed":false},{"type":"uint256","name":"queuedAfter","internalType":"uint256","indexed":false},{"type":"uint256","name":"priceImpactBps","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Funded","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"COOLDOWN","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"FEE_DEN","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"FEE_NUM","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"GATE_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_BUY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"WPLS","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"amountOut","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"rIn","internalType":"uint256"},{"type":"uint256","name":"rOut","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"burnStray","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burned","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"plsSpent","internalType":"uint256"},{"type":"uint256","name":"ekgBurned","internalType":"uint256"}],"name":"executeBuyback","inputs":[{"type":"uint256","name":"minOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IPulseXFactory"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"gateCap","inputs":[{"type":"uint256","name":"plsSide","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"lastBuyAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"mine","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"queued","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"plsSide","internalType":"uint256"},{"type":"uint256","name":"ekgSide","internalType":"uint256"}],"name":"reserves","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IPulseXRouter"}],"name":"router","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"spendable","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"spent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IEKG"}],"name":"token","inputs":[]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x6101206040523480156200001257600080fd5b5060405162001693380380620016938339810160408190526200003591620001f8565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0380841660805282811660a052811660c08190526040805163c45a015560e01b8152905163c45a0155916004808201926020929091908290030181865afa158015620000b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d6919062000242565b6001600160a01b031660e0816001600160a01b031681525050806001600160a01b031663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200012e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000154919062000242565b6001600160a01b039081166101005260405163095ea7b360e01b815230600482015260001960248201529084169063095ea7b3906044016020604051808303816000875af1158015620001ab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d1919062000267565b505050506200028b565b80516001600160a01b0381168114620001f357600080fd5b919050565b6000806000606084860312156200020e57600080fd5b6200021984620001db565b92506200022960208501620001db565b91506200023960408501620001db565b90509250925092565b6000602082840312156200025557600080fd5b6200026082620001db565b9392505050565b6000602082840312156200027a57600080fd5b815180151581146200026057600080fd5b60805160a05160c05160e0516101005161136f62000324600039600081816104150152818161085501528181610bdd0152610dd80152600081816103cc0152610e03015260008181610449015261090001526000818161013e015261035601526000818161047d0152818161053d01528181610606015281816108a90152818161099c01528181610a650152610db0015261136f6000f3fe60806040526004361061012e5760003560e01c806378e2432a116100ab578063c45a01551161006f578063c45a0155146103ba578063e6f124c2146103ee578063ef8ef56f14610403578063f887ea4014610437578063fc0c546a1461046b578063fe08b58c1461049f57600080fd5b806378e2432a1461030e5780637ab71b7a1461032e57806399f4b25114610344578063a2724a4d14610390578063a8aa1b31146103a557600080fd5b80633af96b90116100f25780633af96b901461027c578063624aa407146102985780636869c673146102ae57806373f42561146102e357806375172a8b146102f957600080fd5b806304af6a60146101ce57806316049ddf146102015780631605b17f1461021757806321753cff1461022d57806327e399771461024257600080fd5b366101c957336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461017c57604051636626984560e11b815260040160405180910390fd5b3460008082825461018d9190611071565b909155505060405134815233907f5af8184bef8e4b45eb9f6ed7734d04da38ced226495548f46e0c8ff8d7d9a5249060200160405180910390a2005b600080fd5b3480156101da57600080fd5b506101ee6101e9366004611084565b6104b5565b6040519081526020015b60405180910390f35b34801561020d57600080fd5b506101ee60005481565b34801561022357600080fd5b506101ee61271081565b34801561023957600080fd5b506101ee61051e565b34801561024e57600080fd5b506003546102639067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101f8565b34801561028857600080fd5b506101ee670de0b6b3a764000081565b3480156102a457600080fd5b506101ee6105dc81565b3480156102ba57600080fd5b506102ce6102c93660046110b0565b610684565b604080519283526020830191909152016101f8565b3480156102ef57600080fd5b506101ee60025481565b34801561030557600080fd5b506102ce610b49565b34801561031a57600080fd5b506101ee6103293660046110b0565b610cae565b34801561033a57600080fd5b506101ee60015481565b34801561035057600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101f8565b34801561039c57600080fd5b506101ee603c81565b3480156103b157600080fd5b50610378610d99565b3480156103c657600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b3480156103fa57600080fd5b506101ee610e75565b34801561040f57600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b34801561044357600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b34801561047757600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b3480156104ab57600080fd5b506101ee6126f381565b60008315806104c2575082155b806104cb575081155b156104d857506000610517565b60006104e66126f3866110c9565b9050806104f5612710866110c9565b6104ff9190611071565b61050984836110c9565b61051391906110e0565b9150505b9392505050565b6000610528610eff565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561058c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b09190611102565b9050806000036105d357604051635070cdd160e01b815260040160405180910390fd5b80600260008282546105e59190611071565b909155505060405163079cc67960e41b8152306004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906379cc679090604401600060405180830381600087803b15801561065257600080fd5b505af1158015610666573d6000803e3d6000fd5b50505050610681600160008051602061131a83398151915255565b90565b60008061068f610eff565b6003546106a890603c9067ffffffffffffffff16611071565b4210156106c857604051636fed7d8560e01b815260040160405180910390fd5b60006106d2610d99565b90506001600160a01b0381166106fb57604051631830f95560e11b815260040160405180910390fd5b60005460000361071e576040516301440ac160e21b815260040160405180910390fd5b600080610729610b49565b91509150816000148061073a575080155b1561075857604051631830f95560e11b815260040160405180910390fd5b600061076383610cae565b905080600054106107745780610778565b6000545b9550670de0b6b3a76400008610156107a35760405163860b82a960e01b815260040160405180910390fd5b60006107b08785856104b5565b9050806000036107d357604051635070cdd160e01b815260040160405180910390fd5b60008189116107e257816107e4565b885b9050876000808282546107f7919061111b565b9250508190555087600160008282546108109190611071565b90915550506003805467ffffffffffffffff19164267ffffffffffffffff161790556040805160028082526060820183526000926020830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061088757610887611144565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816001815181106108db576108db611144565b6001600160a01b039283166020918202929092010152604051637ff36ab560e01b81527f000000000000000000000000000000000000000000000000000000000000000090911690637ff36ab5908b9061093f90869086903090429060040161115a565b60006040518083038185885af115801561095d573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405261098691908101906111c6565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156109eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0f9190611102565b975087600003610a3257604051635070cdd160e01b815260040160405180910390fd5b8760026000828254610a449190611071565b909155505060405163079cc67960e41b8152306004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906379cc679090604401600060405180830381600087803b158015610ab157600080fd5b505af1158015610ac5573d6000803e3d6000fd5b50505050336001600160a01b03167f726db8a1d59f0306383ffde7a9f1a21ecf9e532e824e1bf4d3a8efe73bbb9f948a8a600054610b038b8f610f1b565b60408051948552602085019390935291830152606082015260800160405180910390a250505050505050610b44600160008051602061131a83398151915255565b915091565b6000806000610b56610d99565b90506001600160a01b038116610b7157506000928392509050565b600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd691906112a0565b50915091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6791906112f0565b6001600160a01b031614610c8e57806001600160701b0316826001600160701b0316610ca3565b816001600160701b0316816001600160701b03165b945094505050509091565b600081600003610cc057506000919050565b6000610cd06127106126f3611071565b905060006105dc612710610ce76126f360046110c9565b610cf191906110c9565b610cfb91906110c9565b82610d08816127106110c9565b610d1291906110c9565b610d1c9190611071565b610d2b9064e8d4a510006110c9565b90506000610d3a8360646110c9565b610d4790620f42406110c9565b610d5083610faf565b610d5a919061111b565b90506000610d6b6126f360c86110c9565b610d7890620f42406110c9565b905080610d8583886110c9565b610d8f91906110e0565b9695505050505050565b60405163e6a4390560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a4390590604401602060405180830381865afa158015610e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7091906112f0565b905090565b600354600090610e9190603c9067ffffffffffffffff16611071565b421015610e9e5750600090565b6000610ea8610b49565b50905080600003610ebb57600091505090565b6000610ec682610cae565b905060008160005410610ed95781610edd565b6000545b9050670de0b6b3a76400008110610ef45780610ef7565b60005b935050505090565b610f07611019565b600260008051602061131a83398151915255565b600082600003610f2d57506000610fa9565b6000610f3b6126f3846110c9565b610f47612710866110c9565b610f519190611071565b610f5b8486611071565b610f6591906110c9565b90506000612710610f7686806110c9565b610f8091906110c9565b905061271081610f9084836110c9565b610f9a91906110e0565b610fa4919061111b565b925050505b92915050565b600081600003610fc157506000919050565b60006002610fd0846001611071565b610fda91906110e0565b90508291505b8181101561101357905080600281610ff881866110e0565b6110029190611071565b61100c91906110e0565b9050610fe0565b50919050565b6110346000600260008051602061131a833981519152611054565b1561105257604051633ee5aeb560e01b815260040160405180910390fd5b565b5414919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610fa957610fa961105b565b60008060006060848603121561109957600080fd5b505081359360208301359350604090920135919050565b6000602082840312156110c257600080fd5b5035919050565b8082028115828204841417610fa957610fa961105b565b6000826110fd57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561111457600080fd5b5051919050565b81810381811115610fa957610fa961105b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60006080820186835260206080602085015281875180845260a08601915060208901935060005b818110156111a65784516001600160a01b031683529383019391830191600101611181565b50506001600160a01b039690961660408501525050506060015292915050565b600060208083850312156111d957600080fd5b825167ffffffffffffffff808211156111f157600080fd5b818501915085601f83011261120557600080fd5b8151818111156112175761121761112e565b8060051b604051601f19603f8301168101818110858211171561123c5761123c61112e565b60405291825284820192508381018501918883111561125a57600080fd5b938501935b828510156112785784518452938501939285019261125f565b98975050505050505050565b80516001600160701b038116811461129b57600080fd5b919050565b6000806000606084860312156112b557600080fd5b6112be84611284565b92506112cc60208501611284565b9150604084015163ffffffff811681146112e557600080fd5b809150509250925092565b60006020828403121561130257600080fd5b81516001600160a01b038116811461051757600080fdfe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a264697066735822122002bcd88d7ee9d40283ffb17c6c59d69fae25f48ba8d9494c768a18ea462c0ba164736f6c63430008180033000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a000000000000000000000000ad5c70588101d168b52577004a3a209ab90ab49a000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f7
Deployed ByteCode
0x60806040526004361061012e5760003560e01c806378e2432a116100ab578063c45a01551161006f578063c45a0155146103ba578063e6f124c2146103ee578063ef8ef56f14610403578063f887ea4014610437578063fc0c546a1461046b578063fe08b58c1461049f57600080fd5b806378e2432a1461030e5780637ab71b7a1461032e57806399f4b25114610344578063a2724a4d14610390578063a8aa1b31146103a557600080fd5b80633af96b90116100f25780633af96b901461027c578063624aa407146102985780636869c673146102ae57806373f42561146102e357806375172a8b146102f957600080fd5b806304af6a60146101ce57806316049ddf146102015780631605b17f1461021757806321753cff1461022d57806327e399771461024257600080fd5b366101c957336001600160a01b037f000000000000000000000000ad5c70588101d168b52577004a3a209ab90ab49a161461017c57604051636626984560e11b815260040160405180910390fd5b3460008082825461018d9190611071565b909155505060405134815233907f5af8184bef8e4b45eb9f6ed7734d04da38ced226495548f46e0c8ff8d7d9a5249060200160405180910390a2005b600080fd5b3480156101da57600080fd5b506101ee6101e9366004611084565b6104b5565b6040519081526020015b60405180910390f35b34801561020d57600080fd5b506101ee60005481565b34801561022357600080fd5b506101ee61271081565b34801561023957600080fd5b506101ee61051e565b34801561024e57600080fd5b506003546102639067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101f8565b34801561028857600080fd5b506101ee670de0b6b3a764000081565b3480156102a457600080fd5b506101ee6105dc81565b3480156102ba57600080fd5b506102ce6102c93660046110b0565b610684565b604080519283526020830191909152016101f8565b3480156102ef57600080fd5b506101ee60025481565b34801561030557600080fd5b506102ce610b49565b34801561031a57600080fd5b506101ee6103293660046110b0565b610cae565b34801561033a57600080fd5b506101ee60015481565b34801561035057600080fd5b506103787f000000000000000000000000ad5c70588101d168b52577004a3a209ab90ab49a81565b6040516001600160a01b0390911681526020016101f8565b34801561039c57600080fd5b506101ee603c81565b3480156103b157600080fd5b50610378610d99565b3480156103c657600080fd5b506103787f000000000000000000000000ff0538782d122d3112f75dc7121f61562261c0f781565b3480156103fa57600080fd5b506101ee610e75565b34801561040f57600080fd5b506103787f00000000000000000000000070499adebb11efd915e3b69e700c33177862870781565b34801561044357600080fd5b506103787f000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f781565b34801561047757600080fd5b506103787f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a81565b3480156104ab57600080fd5b506101ee6126f381565b60008315806104c2575082155b806104cb575081155b156104d857506000610517565b60006104e66126f3866110c9565b9050806104f5612710866110c9565b6104ff9190611071565b61050984836110c9565b61051391906110e0565b9150505b9392505050565b6000610528610eff565b6040516370a0823160e01b81523060048201527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316906370a0823190602401602060405180830381865afa15801561058c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b09190611102565b9050806000036105d357604051635070cdd160e01b815260040160405180910390fd5b80600260008282546105e59190611071565b909155505060405163079cc67960e41b8152306004820152602481018290527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316906379cc679090604401600060405180830381600087803b15801561065257600080fd5b505af1158015610666573d6000803e3d6000fd5b50505050610681600160008051602061131a83398151915255565b90565b60008061068f610eff565b6003546106a890603c9067ffffffffffffffff16611071565b4210156106c857604051636fed7d8560e01b815260040160405180910390fd5b60006106d2610d99565b90506001600160a01b0381166106fb57604051631830f95560e11b815260040160405180910390fd5b60005460000361071e576040516301440ac160e21b815260040160405180910390fd5b600080610729610b49565b91509150816000148061073a575080155b1561075857604051631830f95560e11b815260040160405180910390fd5b600061076383610cae565b905080600054106107745780610778565b6000545b9550670de0b6b3a76400008610156107a35760405163860b82a960e01b815260040160405180910390fd5b60006107b08785856104b5565b9050806000036107d357604051635070cdd160e01b815260040160405180910390fd5b60008189116107e257816107e4565b885b9050876000808282546107f7919061111b565b9250508190555087600160008282546108109190611071565b90915550506003805467ffffffffffffffff19164267ffffffffffffffff161790556040805160028082526060820183526000926020830190803683370190505090507f00000000000000000000000070499adebb11efd915e3b69e700c3317786287078160008151811061088757610887611144565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a816001815181106108db576108db611144565b6001600160a01b039283166020918202929092010152604051637ff36ab560e01b81527f000000000000000000000000dae9dd3d1a52cfce9d5f2fac7fde164d500e50f790911690637ff36ab5908b9061093f90869086903090429060040161115a565b60006040518083038185885af115801561095d573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405261098691908101906111c6565b506040516370a0823160e01b81523060048201527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316906370a0823190602401602060405180830381865afa1580156109eb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0f9190611102565b975087600003610a3257604051635070cdd160e01b815260040160405180910390fd5b8760026000828254610a449190611071565b909155505060405163079cc67960e41b8152306004820152602481018990527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316906379cc679090604401600060405180830381600087803b158015610ab157600080fd5b505af1158015610ac5573d6000803e3d6000fd5b50505050336001600160a01b03167f726db8a1d59f0306383ffde7a9f1a21ecf9e532e824e1bf4d3a8efe73bbb9f948a8a600054610b038b8f610f1b565b60408051948552602085019390935291830152606082015260800160405180910390a250505050505050610b44600160008051602061131a83398151915255565b915091565b6000806000610b56610d99565b90506001600160a01b038116610b7157506000928392509050565b600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd691906112a0565b50915091507f00000000000000000000000070499adebb11efd915e3b69e700c3317786287076001600160a01b0316836001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6791906112f0565b6001600160a01b031614610c8e57806001600160701b0316826001600160701b0316610ca3565b816001600160701b0316816001600160701b03165b945094505050509091565b600081600003610cc057506000919050565b6000610cd06127106126f3611071565b905060006105dc612710610ce76126f360046110c9565b610cf191906110c9565b610cfb91906110c9565b82610d08816127106110c9565b610d1291906110c9565b610d1c9190611071565b610d2b9064e8d4a510006110c9565b90506000610d3a8360646110c9565b610d4790620f42406110c9565b610d5083610faf565b610d5a919061111b565b90506000610d6b6126f360c86110c9565b610d7890620f42406110c9565b905080610d8583886110c9565b610d8f91906110e0565b9695505050505050565b60405163e6a4390560e01b81526001600160a01b037f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a811660048301527f00000000000000000000000070499adebb11efd915e3b69e700c331778628707811660248301526000917f000000000000000000000000ff0538782d122d3112f75dc7121f61562261c0f79091169063e6a4390590604401602060405180830381865afa158015610e4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7091906112f0565b905090565b600354600090610e9190603c9067ffffffffffffffff16611071565b421015610e9e5750600090565b6000610ea8610b49565b50905080600003610ebb57600091505090565b6000610ec682610cae565b905060008160005410610ed95781610edd565b6000545b9050670de0b6b3a76400008110610ef45780610ef7565b60005b935050505090565b610f07611019565b600260008051602061131a83398151915255565b600082600003610f2d57506000610fa9565b6000610f3b6126f3846110c9565b610f47612710866110c9565b610f519190611071565b610f5b8486611071565b610f6591906110c9565b90506000612710610f7686806110c9565b610f8091906110c9565b905061271081610f9084836110c9565b610f9a91906110e0565b610fa4919061111b565b925050505b92915050565b600081600003610fc157506000919050565b60006002610fd0846001611071565b610fda91906110e0565b90508291505b8181101561101357905080600281610ff881866110e0565b6110029190611071565b61100c91906110e0565b9050610fe0565b50919050565b6110346000600260008051602061131a833981519152611054565b1561105257604051633ee5aeb560e01b815260040160405180910390fd5b565b5414919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610fa957610fa961105b565b60008060006060848603121561109957600080fd5b505081359360208301359350604090920135919050565b6000602082840312156110c257600080fd5b5035919050565b8082028115828204841417610fa957610fa961105b565b6000826110fd57634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561111457600080fd5b5051919050565b81810381811115610fa957610fa961105b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60006080820186835260206080602085015281875180845260a08601915060208901935060005b818110156111a65784516001600160a01b031683529383019391830191600101611181565b50506001600160a01b039690961660408501525050506060015292915050565b600060208083850312156111d957600080fd5b825167ffffffffffffffff808211156111f157600080fd5b818501915085601f83011261120557600080fd5b8151818111156112175761121761112e565b8060051b604051601f19603f8301168101818110858211171561123c5761123c61112e565b60405291825284820192508381018501918883111561125a57600080fd5b938501935b828510156112785784518452938501939285019261125f565b98975050505050505050565b80516001600160701b038116811461129b57600080fd5b919050565b6000806000606084860312156112b557600080fd5b6112be84611284565b92506112cc60208501611284565b9150604084015163ffffffff811681146112e557600080fd5b809150509250925092565b60006020828403121561130257600080fd5b81516001600160a01b038116811461051757600080fdfe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a264697066735822122002bcd88d7ee9d40283ffb17c6c59d69fae25f48ba8d9494c768a18ea462c0ba164736f6c63430008180033