{"file_path":"PegKeeperV2.vy","creation_status":"success","source_code":"# @version 0.3.10\n\"\"\"\n@title Peg Keeper V2\n@license MIT\n@author Curve.Fi\n@notice Peg Keeper\n@dev Version 2\n\"\"\"\n\ninterface Regulator:\n    def stablecoin() -> address: view\n    def provide_allowed(_pk: address=msg.sender) -> uint256: view\n    def withdraw_allowed(_pk: address=msg.sender) -> uint256: view\n    def fee_receiver() -> address: view\n\ninterface CurvePool:\n    def balances(i_coin: uint256) -> uint256: view\n    def coins(i: uint256) -> address: view\n    def get_virtual_price() -> uint256: view\n    def balanceOf(arg0: address) -> uint256: view\n    def transfer(_to: address, _value: uint256) -> bool: nonpayable\n\ninterface CurvePoolOld:\n    def calc_token_amount(_amounts: uint256[2], _is_deposit: bool) -> uint256: view\n    def add_liquidity(_amounts: uint256[2], _min_mint_amount: uint256) -> uint256: nonpayable\n    def remove_liquidity_imbalance(_amounts: uint256[2], _max_burn_amount: uint256) -> uint256: nonpayable\n\ninterface CurvePoolNG:\n    def calc_token_amount(_amounts: DynArray[uint256, 8], _is_deposit: bool) -> uint256: view\n    def add_liquidity(_amounts: DynArray[uint256, 8], _min_mint_amount: uint256) -> uint256: nonpayable\n    def remove_liquidity_imbalance(_amounts: DynArray[uint256, 8], _max_burn_amount: uint256) -> uint256: nonpayable\n\ninterface ERC20:\n    def approve(_spender: address, _amount: uint256): nonpayable\n    def balanceOf(_owner: address) -> uint256: view\n    def decimals() -> uint256: view\n\n\nevent Provide:\n    amount: uint256\n\nevent Withdraw:\n    amount: uint256\n\nevent Profit:\n    lp_amount: uint256\n\nevent CommitNewAdmin:\n    admin: address\n\nevent ApplyNewAdmin:\n    admin: address\n\nevent SetNewActionDelay:\n    action_delay: uint256\n\nevent SetNewCallerShare:\n    caller_share: uint256\n\nevent SetNewRegulator:\n    regulator: address\n\n\n# Time between providing/withdrawing coins\naction_delay: uint256\nADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400\n\nPRECISION: constant(uint256) = 10 ** 18\n\nPOOL: immutable(CurvePool)\nI: immutable(uint256)  # index of pegged in pool\nPEGGED: immutable(ERC20)\nIS_INVERSE: public(immutable(bool))\nIS_NG: public(immutable(bool))  # Interface for CurveStableSwapNG\nPEG_MUL: immutable(uint256)\n\nregulator: public(Regulator)\n\nlast_change: public(uint256)\ndebt: public(uint256)\n\nSHARE_PRECISION: constant(uint256) = 10 ** 5\ncaller_share: public(uint256)\n\nadmin: public(address)\nfuture_admin: public(address)\nnew_admin_deadline: public(uint256)\n\n\n@external\ndef __init__(\n    _pool: CurvePool, _caller_share: uint256, _regulator: Regulator, _admin: address\n):\n    \"\"\"\n    @notice Contract constructor\n    @param _pool Contract pool address\n    @param _caller_share Caller's share of profit\n    @param _regulator Peg Keeper Regulator\n    @param _admin Admin account\n    \"\"\"\n    POOL = _pool\n    pegged: ERC20 = ERC20(_regulator.stablecoin())\n    PEGGED = pegged\n    pegged.approve(_pool.address, max_value(uint256))\n\n    coins: ERC20[2] = [ERC20(_pool.coins(0)), ERC20(_pool.coins(1))]\n    for i in range(2):\n        if coins[i] == pegged:\n            I = i\n            IS_INVERSE = (i == 0)\n        else:\n            PEG_MUL = 10 ** (18 - coins[i].decimals())\n\n    IS_NG = raw_call(\n        _pool.address, _abi_encode(convert(0, uint256), method_id=method_id(\"price_oracle(uint256)\")),\n        revert_on_failure=False\n    )\n\n    self.admin = _admin\n    log ApplyNewAdmin(msg.sender)\n\n    self.regulator = _regulator\n    log SetNewRegulator(_regulator.address)\n\n    assert _caller_share <= SHARE_PRECISION  # dev: bad part value\n    self.caller_share = _caller_share\n    log SetNewCallerShare(_caller_share)\n\n    self.action_delay = 12  # 1 block\n    log SetNewActionDelay(12)\n\n@pure\n@external\ndef pegged() -> address:\n    \"\"\"\n    @return Address of stablecoin being pegged\n    \"\"\"\n    return PEGGED.address\n\n\n@pure\n@external\ndef pool() -> CurvePool:\n    \"\"\"\n    @return StableSwap pool being used\n    \"\"\"\n    return POOL\n\n\n@internal\ndef _provide(_amount: uint256):\n    \"\"\"\n    @notice Implementation of provide\n    @dev Coins should be already in the contract\n    \"\"\"\n    if _amount == 0:\n        return\n\n    amount: uint256 = min(_amount, PEGGED.balanceOf(self))\n\n    if IS_NG:\n        amounts: DynArray[uint256, 2] = [0, 0]\n        amounts[I] = amount\n        CurvePoolNG(POOL.address).add_liquidity(amounts, 0)\n    else:\n        amounts: uint256[2] = empty(uint256[2])\n        amounts[I] = amount\n        CurvePoolOld(POOL.address).add_liquidity(amounts, 0)\n\n    self.last_change = block.timestamp\n    self.debt += amount\n    log Provide(amount)\n\n\n@internal\ndef _withdraw(_amount: uint256):\n    \"\"\"\n    @notice Implementation of withdraw\n    \"\"\"\n    if _amount == 0:\n        return\n\n    debt: uint256 = self.debt\n    amount: uint256 = min(_amount, debt)\n\n    if IS_NG:\n        amounts: DynArray[uint256, 2] = [0, 0]\n        amounts[I] = amount\n        CurvePoolNG(POOL.address).remove_liquidity_imbalance(amounts, max_value(uint256))\n    else:\n        amounts: uint256[2] = empty(uint256[2])\n        amounts[I] = amount\n        CurvePoolOld(POOL.address).remove_liquidity_imbalance(amounts, max_value(uint256))\n\n    self.last_change = block.timestamp\n    self.debt = debt - amount\n\n    log Withdraw(amount)\n\n\n@internal\n@pure\ndef _calc_profit_from(lp_balance: uint256, virtual_price: uint256, debt: uint256) -> uint256:\n    \"\"\"\n    @notice PegKeeper's profit calculation formula\n    \"\"\"\n    lp_debt: uint256 = debt * PRECISION / virtual_price\n\n    if lp_balance <= lp_debt:\n        return 0\n    else:\n        return lp_balance - lp_debt\n\n\n@internal\n@view\ndef _calc_profit() -> uint256:\n    \"\"\"\n    @notice Calculate PegKeeper's profit using current values\n    \"\"\"\n    return self._calc_profit_from(POOL.balanceOf(self), POOL.get_virtual_price(), self.debt)\n\n\n@internal\n@view\ndef _calc_call_profit(_amount: uint256, _is_deposit: bool) -> uint256:\n    \"\"\"\n    @notice Calculate overall profit from calling update()\n    \"\"\"\n    lp_balance: uint256 = POOL.balanceOf(self)\n    virtual_price: uint256 = POOL.get_virtual_price()\n    debt: uint256 = self.debt\n    initial_profit: uint256 = self._calc_profit_from(lp_balance, virtual_price, debt)\n\n    amount: uint256 = _amount\n    if _is_deposit:\n        amount = min(_amount, PEGGED.balanceOf(self))\n    else:\n        amount = min(_amount, debt)\n\n    lp_balance_diff: uint256 = 0\n    if IS_NG:\n        amounts: DynArray[uint256, 2] = [0, 0]\n        amounts[I] = amount\n        lp_balance_diff = CurvePoolNG(POOL.address).calc_token_amount(amounts, _is_deposit)\n    else:\n        amounts: uint256[2] = empty(uint256[2])\n        amounts[I] = amount\n        lp_balance_diff = CurvePoolOld(POOL.address).calc_token_amount(amounts, _is_deposit)\n\n    if _is_deposit:\n        lp_balance += lp_balance_diff\n        debt += amount\n    else:\n        lp_balance -= lp_balance_diff\n        debt -= amount\n\n    new_profit: uint256 = self._calc_profit_from(lp_balance, virtual_price, debt)\n    if new_profit <= initial_profit:\n        return 0\n    return new_profit - initial_profit\n\n\n@external\n@view\ndef calc_profit() -> uint256:\n    \"\"\"\n    @notice Calculate generated profit in LP tokens. Does NOT include already withdrawn profit\n    @return Amount of generated profit\n    \"\"\"\n    return self._calc_profit()\n\n\n@external\n@view\ndef estimate_caller_profit() -> uint256:\n    \"\"\"\n    @notice Estimate profit from calling update()\n    @dev This method is not precise, real profit is always more because of increasing virtual price\n    @return Expected amount of profit going to beneficiary\n    \"\"\"\n    if self.last_change + self.action_delay > block.timestamp:\n        return 0\n\n    balance_pegged: uint256 = POOL.balances(I)\n    balance_peg: uint256 = POOL.balances(1 - I) * PEG_MUL\n\n    call_profit: uint256 = 0\n    if balance_peg > balance_pegged:\n        allowed: uint256 = self.regulator.provide_allowed()\n        call_profit = self._calc_call_profit(min((balance_peg - balance_pegged) / 5, allowed), True)  # this dumps stablecoin\n\n    else:\n        allowed: uint256 = self.regulator.withdraw_allowed()\n        call_profit = self._calc_call_profit(min((balance_pegged - balance_peg) / 5, allowed), False)  # this pumps stablecoin\n\n    return call_profit * self.caller_share / SHARE_PRECISION\n\n\n@external\n@nonpayable\ndef update(_beneficiary: address = msg.sender) -> uint256:\n    \"\"\"\n    @notice Provide or withdraw coins from the pool to stabilize it\n    @param _beneficiary Beneficiary address\n    @return Amount of profit received by beneficiary\n    \"\"\"\n    if self.last_change + self.action_delay > block.timestamp:\n        return 0\n\n    balance_pegged: uint256 = POOL.balances(I)\n    balance_peg: uint256 = POOL.balances(1 - I) * PEG_MUL\n\n    initial_profit: uint256 = self._calc_profit()\n\n    if balance_peg > balance_pegged:\n        allowed: uint256 = self.regulator.provide_allowed()\n        assert allowed > 0, \"Regulator ban\"\n        self._provide(min(unsafe_sub(balance_peg, balance_pegged) / 5, allowed))  # this dumps stablecoin\n\n    else:\n        allowed: uint256 = self.regulator.withdraw_allowed()\n        assert allowed > 0, \"Regulator ban\"\n        self._withdraw(min(unsafe_sub(balance_pegged, balance_peg) / 5, allowed))  # this pumps stablecoin\n\n    # Send generated profit\n    new_profit: uint256 = self._calc_profit()\n    assert new_profit > initial_profit, \"peg unprofitable\"\n    lp_amount: uint256 = new_profit - initial_profit\n    caller_profit: uint256 = lp_amount * self.caller_share / SHARE_PRECISION\n    if caller_profit > 0:\n        POOL.transfer(_beneficiary, caller_profit)\n\n    return caller_profit\n\n\n@external\n@nonpayable\ndef withdraw_profit() -> uint256:\n    \"\"\"\n    @notice Withdraw profit generated by Peg Keeper\n    @return Amount of LP Token received\n    \"\"\"\n    lp_amount: uint256 = self._calc_profit()\n    POOL.transfer(self.regulator.fee_receiver(), lp_amount)\n\n    log Profit(lp_amount)\n\n    return lp_amount\n\n\n# ------------------------------- Admin methods --------------------------------\n\n\n@external\n@nonpayable\ndef set_new_action_delay(_new_action_delay: uint256):\n    \"\"\"\n    @notice Set new action delay\n    @param _new_action_delay Action delay in seconds\n    \"\"\"\n    assert msg.sender == self.admin  # dev: only admin\n\n    self.action_delay = _new_action_delay\n\n    log SetNewActionDelay(_new_action_delay)\n\n\n@external\n@nonpayable\ndef set_new_caller_share(_new_caller_share: uint256):\n    \"\"\"\n    @notice Set new update caller's part\n    @param _new_caller_share Part with SHARE_PRECISION\n    \"\"\"\n    assert msg.sender == self.admin  # dev: only admin\n    assert _new_caller_share <= SHARE_PRECISION  # dev: bad part value\n\n    self.caller_share = _new_caller_share\n\n    log SetNewCallerShare(_new_caller_share)\n\n\n@external\n@nonpayable\ndef set_new_regulator(_new_regulator: Regulator):\n    \"\"\"\n    @notice Set new peg keeper regulator\n    \"\"\"\n    assert msg.sender == self.admin  # dev: only admin\n    assert _new_regulator.address != empty(address)  # dev: bad regulator\n\n    self.regulator = _new_regulator\n    log SetNewRegulator(_new_regulator.address)\n\n\n@external\n@nonpayable\ndef commit_new_admin(_new_admin: address):\n    \"\"\"\n    @notice Commit new admin of the Peg Keeper\n    @dev In order to revert, commit_new_admin(current_admin) may be called\n    @param _new_admin Address of the new admin\n    \"\"\"\n    assert msg.sender == self.admin  # dev: only admin\n    assert _new_admin != empty(address)  # dev: bad admin\n\n    self.new_admin_deadline = block.timestamp + ADMIN_ACTIONS_DELAY\n    self.future_admin = _new_admin\n\n    log CommitNewAdmin(_new_admin)\n\n\n@external\n@nonpayable\ndef apply_new_admin():\n    \"\"\"\n    @notice Apply new admin of the Peg Keeper\n    @dev Should be executed from new admin\n    \"\"\"\n    new_admin: address = self.future_admin\n    new_admin_deadline: uint256 = self.new_admin_deadline\n    assert msg.sender == new_admin  # dev: only new admin\n    assert block.timestamp >= new_admin_deadline  # dev: insufficient time\n    assert new_admin_deadline != 0  # dev: no active action\n\n    self.admin = new_admin\n    self.new_admin_deadline = 0\n\n    log ApplyNewAdmin(new_admin)","deployed_bytecode":"0x5f3560e01c60026013820660011b61130801601e395f51565b63f96b9f188118610af1573461130457602061138e60403960206040f3610af1565b631f13be728118610af157346113045760206113ae60403960206040f3610af1565b63dd8fee14811861007857346113045760015460405260206040f35b63553b549c8118610af157346113045760075460405260206040f3610af1565b63394b146d8118610af157346113045760025460405260206040f3610af1565b630dca59c18118610af157346113045760035460405260206040f3610af1565b63df81cd3f8118610af157346113045760045460405260206040f3610af1565b63f851a4408118610af157346113045760055460405260206040f3610af1565b6317f7182a811861013457346113045760065460405260206040f35b63c9e0cafe8118610af157602436103417611304576005543318611304576004355f557f91839293e1732d7f8bc72854c63f1867f41b010c3cb38b315fc5845366e5491460043560405260206040a100610af1565b630907861381186101a7573461130457602061136e60403960206040f35b639f5ef86f8118610af15760243610341761130457600554331861130457620186a060043511611304576004356004557f43abfd568a12e5f6ea230e56ba11b83e29e9921019211df9cc2e216ba9f225dc60043560405260206040a100610af1565b6316f0115b8118610af1573461130457602061132e60403960206040f3610af1565b63322f15d9811861024d5734611304576020610248610160610f1d565b610160f35b63c336fbd58118610af157346113045760065460405260075460605260405133186113045760605142106113045760605115611304576040516005555f6007557fc0a6e80c08b9d10c650a9f3e8ff16d7ee0f62bbd5c8ac3b5eba62dae04ec995a60405160805260206080a100610af1565b63d0d184918118610af1573461130457426002545f54808201828110611304579050905011156102f8575f6102e05260206102e06104f5565b602061132e5f395f51634903b0d161030052602061134e610320396020610300602461031c845afa61032c573d5f5f3e3d5ffd5b60203d10611304576103009050516102e052602061132e5f395f51634903b0d161032052602061134e5f395f518060010360018111611304579050610340526020610320602461033c845afa610384573d5f5f3e3d5ffd5b60203d106113045761032090505160206113ce5f395f518082028115838383041417156113045790509050610300525f610320526102e051610300511161044857600154633278d11f610360526020610360600461037c845afa6103ea573d5f5f3e3d5ffd5b60203d1061130457610360905051610340526102e051610300518082038281116113045790509050600581049050610340518082811882841002189050905060c0525f60e05261043b610360610faf565b61036051610320526104c8565b6001546324039e72610360526020610360600461037c845afa61046d573d5f5f3e3d5ffd5b60203d106113045761036090505161034052610300516102e0518082038281116113045790509050600581049050610340518082811882841002189050905060c052600160e0526104bf610360610faf565b61036051610320525b610320516004548082028115838383041417156113045790509050620186a0810490506103405260206103405bf3610af1565b63a2e620458118610af1573461130457336101c05261053e56610af1565b631c1b87728118610af157602436103417611304576004358060a01c611304576101c0525b426002545f5480820182811061130457905090501115610567575f6101e05260206101e0610913565b602061132e5f395f51634903b0d161020052602061134e610220396020610200602461021c845afa61059b573d5f5f3e3d5ffd5b60203d10611304576102009050516101e052602061132e5f395f51634903b0d161022052602061134e5f395f518060010360018111611304579050610240526020610220602461023c845afa6105f3573d5f5f3e3d5ffd5b60203d106113045761022090505160206113ce5f395f5180820281158383830414171561130457905090506102005261062d610240610f1d565b61024051610220526101e051610200511161071557600154633278d11f610260526020610260600461027c845afa610667573d5f5f3e3d5ffd5b60203d106113045761026090505161024052610240516106e657600d610260527f526567756c61746f722062616e000000000000000000000000000000000000006102805261026050610260518061028001601f825f031636823750506308c379a061022052602061024052601f19601f61026051011660440161023cfd5b610200516101e0510360058104905061024051808281188284100218905090506040526107e4610ccb566107e4565b6001546324039e72610260526020610260600461027c845afa61073a573d5f5f3e3d5ffd5b60203d106113045761026090505161024052610240516107b957600d610260527f526567756c61746f722062616e000000000000000000000000000000000000006102805261026050610260518061028001601f825f031636823750506308c379a061022052602061024052601f19601f61026051011660440161023cfd5b6101e051610200510360058104905061024051808281188284100218905090506040526107e4610af5565b6107ef610260610f1d565b6102605161024052610220516102405111610869576010610260527f70656720756e70726f66697461626c65000000000000000000000000000000006102805261026050610260518061028001601f825f031636823750506308c379a061022052602061024052601f19601f61026051011660440161023cfd5b6102405161022051808203828111611304579050905061026052610260516004548082028115838383041417156113045790509050620186a08104905061028052610280511561090d57602061132e5f395f5163a9059cbb6102a0526101c0516102c052610280516102e05260206102a060446102bc5f855af16108ef573d5f5f3e3d5ffd5b60203d10611304576102a0518060011c611304576103005261030050505b60206102805bf3610af1565b632c9f7f928118610a0a573461130457610934610180610f1d565b6101805161016052602061132e5f395f5163a9059cbb6101e05260015463cab4d3db610180526020610180600461019c845afa610973573d5f5f3e3d5ffd5b60203d1061130457610180518060a01c611304576101c0526101c090505161020052610160516102205260206101e060446101fc5f855af16109b7573d5f5f3e3d5ffd5b60203d10611304576101e0518060011c611304576102405261024050507f357d905f1831209797df4d55d79c5c5bf1d9f7311c976afd05e13d881eab9bc861016051610180526020610180a16020610160f35b63bde956768118610af157602436103417611304576004358060a01c6113045760405260055433186113045760405115611304576040516001557f12399a48b466e8608fee30e1b0cd0fc481380efa8a100e6dd566f6d8d20c24ec60405160605260206060a100610af1565b63f636b05f8118610af157602436103417611304576004358060a01c611304576040526005543318611304576040511561130457426203f48081018181106113045790506007556040516006557f0305c49816a5a9a099d81e90d76421c9a4a529e0640cd15297b6fc8f1c9ac6ff60405160605260206060a1005b5f5ffd5b604051610b0157610cc9565b604051602061136e5f395f516370a082316080523060a052602060806024609c845afa610b30573d5f5f3e3d5ffd5b60203d106113045760809050518082811882841002189050905060605260206113ae5f395f51610bc757604036608037606051602061134e5f395f51600181116113045760051b60800152602061132e5f395f51630b4c7e4d60c05260805160e05260a051610100525f61012052602060c0606460dc5f855af1610bb6573d5f5f3e3d5ffd5b60203d106113045760c05050610c81565b60403660a0376002608052606051602061134e5f395f516080518110156113045760051b60a00152602061132e5f395f5163b72df5de60e0526040806101005280610100015f6080518083528060051b5f8260028111611304578015610c4657905b8060051b60a001518160051b602088010152600101818118610c29575b505082016020019150509050810190505f6101205250602060e060a460fc5f855af1610c74573d5f5f3e3d5ffd5b60203d106113045760e050505b4260025560035460605180820182811061130457905090506003557f8d685bd3f45d861c759ed7a46ea3d30eb5cc6ce9fe06c526931f94c963bca7d260605160805260206080a15b565b604051610cd757610eb4565b6003546060526040516060518082811882841002189050905060805260206113ae5f395f51610d8e5760403660a037608051602061134e5f395f51600181116113045760051b60a00152602061132e5f395f5163e310327360e05260a0516101005260c051610120527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61014052602060e0606460fc5f855af1610d7d573d5f5f3e3d5ffd5b60203d106113045760e05050610e6c565b60403660c037600260a052608051602061134e5f395f5160a0518110156113045760051b60c00152602061132e5f395f51637706db75610100526040806101205280610120015f60a0518083528060051b5f8260028111611304578015610e0e57905b8060051b60c001518160051b602088010152600101818118610df1575b505082016020019150509050810190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101405250602061010060a461011c5f855af1610e5e573d5f5f3e3d5ffd5b60203d106113045761010050505b4260025560605160805180820382811161130457905090506003557f5b6b431d4476a211bb7d41c20d1aab9ae2321deee0d20be3d9fc9b1093fa6e3d60805160a052602060a0a15b565b608051670de0b6b3a7640000810281670de0b6b3a76400008204186113045790506060518015611304578082049050905060a05260a0516040511115610f165760405160a0518082038281116113045790509050815250610f1b56610f1b565b5f8152505b565b602061132e5f395f516370a0823160c0523060e052602060c0602460dc845afa610f49573d5f5f3e3d5ffd5b60203d106113045760c0905051604052602061132e5f395f5163bb7b8b80610100526020610100600461011c845afa610f84573d5f5f3e3d5ffd5b60203d1061130457610100905051606052600354608052610fa6610140610eb6565b61014051815250565b602061132e5f395f516370a082316101205230610140526020610120602461013c845afa610fdf573d5f5f3e3d5ffd5b60203d106113045761012090505161010052602061132e5f395f5163bb7b8b80610140526020610140600461015c845afa61101c573d5f5f3e3d5ffd5b60203d10611304576101409050516101205260035461014052610100516040526101205160605261014051608052611055610180610eb6565b610180516101605260c0516101805260e0516110885760c0516101405180828118828410021890509050610180526110db565b60c051602061136e5f395f516370a082316101a052306101c05260206101a060246101bc845afa6110bb573d5f5f3e3d5ffd5b60203d10611304576101a090505180828118828410021890509050610180525b5f6101a05260206113ae5f395f5161116a576040366101c03761018051602061134e5f395f51600181116113045760051b6101c00152602061132e5f395f5163ed8e84f3610200526101c051610220526101e0516102405260e051610260526020610200606461021c845afa611153573d5f5f3e3d5ffd5b60203d10611304576102009050516101a052611235565b6040366101e03760026101c05261018051602061134e5f395f516101c0518110156113045760051b6101e00152602061132e5f395f51633db06dd8610220526040806102405280610240015f6101c0518083528060051b5f82600281116113045780156111f157905b8060051b6101e001518160051b6020880101526001018181186111d3575b5050820160200191505090508101905060e0516102605250602061022060a461023c845afa611222573d5f5f3e3d5ffd5b60203d10611304576102209050516101a0525b60e05161127557610100516101a05180820382811161130457905090506101005261014051610180518082038281116113045790509050610140526112aa565b610100516101a05180820182811061130457905090506101005261014051610180518082018281106113045790509050610140525b6101005160405261012051606052610140516080526112ca6101e0610eb6565b6101e0516101c052610160516101c051116112e8575f815250611302565b6101c0516101605180820382811161130457905090508152505b565b5f80fd04fb01180209022b0a7600b80af10519003a001800d80af101890af100f802bf005c0919009800000000000000000000000097ba10115da528c113462ede9c20d7adc806d93f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b1c2db5d6ca03fce73dbd304d320bf76c55ae1b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000e8d4a51000","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"outputSelection":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]},"search_paths":["."]},"optimization_runs":null,"sourcify_repo_url":null,"decoded_constructor_args":[["0x97BA10115da528c113462EDE9C20D7adc806D93f",{"name":"_pool","type":"address"}],["20000",{"name":"_caller_share","type":"uint256"}],["0x887706612730B7A227f3bFFD8c9A6E6c3Cb3F19E",{"name":"_regulator","type":"address"}],["0x461B62CB3A7e9Df8f800aE058AE92F855F2c27Ca",{"name":"_admin","type":"address"}]],"compiler_version":"v0.3.10+commit.91361694","is_verified_via_verifier_alliance":false,"verified_at":"2026-04-27T19:38:06.722098Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6113ce51503461035757602061169f5f395f518060a01c6103575760405260206116df5f395f518060a01c6103575760605260206116ff5f395f518060a01c6103575760805260405161132e5260605163e9cbd82260c052602060c0600460dc845afa61006e573d5f5f3e3d5ffd5b60203d106103575760c0518060a01c610357576101005261010090505160a05260a05161136e5260a05163095ea7b360c05260405160e0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010052803b15610357575f60c0604460dc5f855af16100e9573d5f5f3e3d5ffd5b5060405163c6610657610100525f610120526020610100602461011c845afa610114573d5f5f3e3d5ffd5b60203d1061035757610100518060a01c610357576101405261014090505160c05260405163c6610657610160526001610180526020610160602461017c845afa610160573d5f5f3e3d5ffd5b60203d1061035757610160518060a01c610357576101a0526101a090505160e0525f6002905b806101005260a05161010051600181116103575760051b60c00151186101bc576101005161134e52610100511561138e52610220565b61010051600181116103575760051b60c0015163313ce567610120526020610120600461013c845afa6101f1573d5f5f3e3d5ffd5b60203d10610357576101209050518060120360128111610357579050604d81116103575780600a0a90506113ce525b6001018181186101865750506040515a63687276536101045260045f6101245260200161010052610100505f5f610100516101205f8686f1905090506113ae526080516005557fc0a6e80c08b9d10c650a9f3e8ff16d7ee0f62bbd5c8ac3b5eba62dae04ec995a33610100526020610100a16060516001557f12399a48b466e8608fee30e1b0cd0fc481380efa8a100e6dd566f6d8d20c24ec606051610100526020610100a1620186a060206116bf5f395f51116103575760206116bf5f395f516004557f43abfd568a12e5f6ea230e56ba11b83e29e9921019211df9cc2e216ba9f225dc60206116bf610100396020610100a1600c5f557f91839293e1732d7f8bc72854c63f1867f41b010c3cb38b315fc5845366e54914600c610100526020610100a161132e61035b610000396113ee610000f35b5f80fd5f3560e01c60026013820660011b61130801601e395f51565b63f96b9f188118610af1573461130457602061138e60403960206040f3610af1565b631f13be728118610af157346113045760206113ae60403960206040f3610af1565b63dd8fee14811861007857346113045760015460405260206040f35b63553b549c8118610af157346113045760075460405260206040f3610af1565b63394b146d8118610af157346113045760025460405260206040f3610af1565b630dca59c18118610af157346113045760035460405260206040f3610af1565b63df81cd3f8118610af157346113045760045460405260206040f3610af1565b63f851a4408118610af157346113045760055460405260206040f3610af1565b6317f7182a811861013457346113045760065460405260206040f35b63c9e0cafe8118610af157602436103417611304576005543318611304576004355f557f91839293e1732d7f8bc72854c63f1867f41b010c3cb38b315fc5845366e5491460043560405260206040a100610af1565b630907861381186101a7573461130457602061136e60403960206040f35b639f5ef86f8118610af15760243610341761130457600554331861130457620186a060043511611304576004356004557f43abfd568a12e5f6ea230e56ba11b83e29e9921019211df9cc2e216ba9f225dc60043560405260206040a100610af1565b6316f0115b8118610af1573461130457602061132e60403960206040f3610af1565b63322f15d9811861024d5734611304576020610248610160610f1d565b610160f35b63c336fbd58118610af157346113045760065460405260075460605260405133186113045760605142106113045760605115611304576040516005555f6007557fc0a6e80c08b9d10c650a9f3e8ff16d7ee0f62bbd5c8ac3b5eba62dae04ec995a60405160805260206080a100610af1565b63d0d184918118610af1573461130457426002545f54808201828110611304579050905011156102f8575f6102e05260206102e06104f5565b602061132e5f395f51634903b0d161030052602061134e610320396020610300602461031c845afa61032c573d5f5f3e3d5ffd5b60203d10611304576103009050516102e052602061132e5f395f51634903b0d161032052602061134e5f395f518060010360018111611304579050610340526020610320602461033c845afa610384573d5f5f3e3d5ffd5b60203d106113045761032090505160206113ce5f395f518082028115838383041417156113045790509050610300525f610320526102e051610300511161044857600154633278d11f610360526020610360600461037c845afa6103ea573d5f5f3e3d5ffd5b60203d1061130457610360905051610340526102e051610300518082038281116113045790509050600581049050610340518082811882841002189050905060c0525f60e05261043b610360610faf565b61036051610320526104c8565b6001546324039e72610360526020610360600461037c845afa61046d573d5f5f3e3d5ffd5b60203d106113045761036090505161034052610300516102e0518082038281116113045790509050600581049050610340518082811882841002189050905060c052600160e0526104bf610360610faf565b61036051610320525b610320516004548082028115838383041417156113045790509050620186a0810490506103405260206103405bf3610af1565b63a2e620458118610af1573461130457336101c05261053e56610af1565b631c1b87728118610af157602436103417611304576004358060a01c611304576101c0525b426002545f5480820182811061130457905090501115610567575f6101e05260206101e0610913565b602061132e5f395f51634903b0d161020052602061134e610220396020610200602461021c845afa61059b573d5f5f3e3d5ffd5b60203d10611304576102009050516101e052602061132e5f395f51634903b0d161022052602061134e5f395f518060010360018111611304579050610240526020610220602461023c845afa6105f3573d5f5f3e3d5ffd5b60203d106113045761022090505160206113ce5f395f5180820281158383830414171561130457905090506102005261062d610240610f1d565b61024051610220526101e051610200511161071557600154633278d11f610260526020610260600461027c845afa610667573d5f5f3e3d5ffd5b60203d106113045761026090505161024052610240516106e657600d610260527f526567756c61746f722062616e000000000000000000000000000000000000006102805261026050610260518061028001601f825f031636823750506308c379a061022052602061024052601f19601f61026051011660440161023cfd5b610200516101e0510360058104905061024051808281188284100218905090506040526107e4610ccb566107e4565b6001546324039e72610260526020610260600461027c845afa61073a573d5f5f3e3d5ffd5b60203d106113045761026090505161024052610240516107b957600d610260527f526567756c61746f722062616e000000000000000000000000000000000000006102805261026050610260518061028001601f825f031636823750506308c379a061022052602061024052601f19601f61026051011660440161023cfd5b6101e051610200510360058104905061024051808281188284100218905090506040526107e4610af5565b6107ef610260610f1d565b6102605161024052610220516102405111610869576010610260527f70656720756e70726f66697461626c65000000000000000000000000000000006102805261026050610260518061028001601f825f031636823750506308c379a061022052602061024052601f19601f61026051011660440161023cfd5b6102405161022051808203828111611304579050905061026052610260516004548082028115838383041417156113045790509050620186a08104905061028052610280511561090d57602061132e5f395f5163a9059cbb6102a0526101c0516102c052610280516102e05260206102a060446102bc5f855af16108ef573d5f5f3e3d5ffd5b60203d10611304576102a0518060011c611304576103005261030050505b60206102805bf3610af1565b632c9f7f928118610a0a573461130457610934610180610f1d565b6101805161016052602061132e5f395f5163a9059cbb6101e05260015463cab4d3db610180526020610180600461019c845afa610973573d5f5f3e3d5ffd5b60203d1061130457610180518060a01c611304576101c0526101c090505161020052610160516102205260206101e060446101fc5f855af16109b7573d5f5f3e3d5ffd5b60203d10611304576101e0518060011c611304576102405261024050507f357d905f1831209797df4d55d79c5c5bf1d9f7311c976afd05e13d881eab9bc861016051610180526020610180a16020610160f35b63bde956768118610af157602436103417611304576004358060a01c6113045760405260055433186113045760405115611304576040516001557f12399a48b466e8608fee30e1b0cd0fc481380efa8a100e6dd566f6d8d20c24ec60405160605260206060a100610af1565b63f636b05f8118610af157602436103417611304576004358060a01c611304576040526005543318611304576040511561130457426203f48081018181106113045790506007556040516006557f0305c49816a5a9a099d81e90d76421c9a4a529e0640cd15297b6fc8f1c9ac6ff60405160605260206060a1005b5f5ffd5b604051610b0157610cc9565b604051602061136e5f395f516370a082316080523060a052602060806024609c845afa610b30573d5f5f3e3d5ffd5b60203d106113045760809050518082811882841002189050905060605260206113ae5f395f51610bc757604036608037606051602061134e5f395f51600181116113045760051b60800152602061132e5f395f51630b4c7e4d60c05260805160e05260a051610100525f61012052602060c0606460dc5f855af1610bb6573d5f5f3e3d5ffd5b60203d106113045760c05050610c81565b60403660a0376002608052606051602061134e5f395f516080518110156113045760051b60a00152602061132e5f395f5163b72df5de60e0526040806101005280610100015f6080518083528060051b5f8260028111611304578015610c4657905b8060051b60a001518160051b602088010152600101818118610c29575b505082016020019150509050810190505f6101205250602060e060a460fc5f855af1610c74573d5f5f3e3d5ffd5b60203d106113045760e050505b4260025560035460605180820182811061130457905090506003557f8d685bd3f45d861c759ed7a46ea3d30eb5cc6ce9fe06c526931f94c963bca7d260605160805260206080a15b565b604051610cd757610eb4565b6003546060526040516060518082811882841002189050905060805260206113ae5f395f51610d8e5760403660a037608051602061134e5f395f51600181116113045760051b60a00152602061132e5f395f5163e310327360e05260a0516101005260c051610120527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61014052602060e0606460fc5f855af1610d7d573d5f5f3e3d5ffd5b60203d106113045760e05050610e6c565b60403660c037600260a052608051602061134e5f395f5160a0518110156113045760051b60c00152602061132e5f395f51637706db75610100526040806101205280610120015f60a0518083528060051b5f8260028111611304578015610e0e57905b8060051b60c001518160051b602088010152600101818118610df1575b505082016020019150509050810190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101405250602061010060a461011c5f855af1610e5e573d5f5f3e3d5ffd5b60203d106113045761010050505b4260025560605160805180820382811161130457905090506003557f5b6b431d4476a211bb7d41c20d1aab9ae2321deee0d20be3d9fc9b1093fa6e3d60805160a052602060a0a15b565b608051670de0b6b3a7640000810281670de0b6b3a76400008204186113045790506060518015611304578082049050905060a05260a0516040511115610f165760405160a0518082038281116113045790509050815250610f1b56610f1b565b5f8152505b565b602061132e5f395f516370a0823160c0523060e052602060c0602460dc845afa610f49573d5f5f3e3d5ffd5b60203d106113045760c0905051604052602061132e5f395f5163bb7b8b80610100526020610100600461011c845afa610f84573d5f5f3e3d5ffd5b60203d1061130457610100905051606052600354608052610fa6610140610eb6565b61014051815250565b602061132e5f395f516370a082316101205230610140526020610120602461013c845afa610fdf573d5f5f3e3d5ffd5b60203d106113045761012090505161010052602061132e5f395f5163bb7b8b80610140526020610140600461015c845afa61101c573d5f5f3e3d5ffd5b60203d10611304576101409050516101205260035461014052610100516040526101205160605261014051608052611055610180610eb6565b610180516101605260c0516101805260e0516110885760c0516101405180828118828410021890509050610180526110db565b60c051602061136e5f395f516370a082316101a052306101c05260206101a060246101bc845afa6110bb573d5f5f3e3d5ffd5b60203d10611304576101a090505180828118828410021890509050610180525b5f6101a05260206113ae5f395f5161116a576040366101c03761018051602061134e5f395f51600181116113045760051b6101c00152602061132e5f395f5163ed8e84f3610200526101c051610220526101e0516102405260e051610260526020610200606461021c845afa611153573d5f5f3e3d5ffd5b60203d10611304576102009050516101a052611235565b6040366101e03760026101c05261018051602061134e5f395f516101c0518110156113045760051b6101e00152602061132e5f395f51633db06dd8610220526040806102405280610240015f6101c0518083528060051b5f82600281116113045780156111f157905b8060051b6101e001518160051b6020880101526001018181186111d3575b5050820160200191505090508101905060e0516102605250602061022060a461023c845afa611222573d5f5f3e3d5ffd5b60203d10611304576102209050516101a0525b60e05161127557610100516101a05180820382811161130457905090506101005261014051610180518082038281116113045790509050610140526112aa565b610100516101a05180820182811061130457905090506101005261014051610180518082018281106113045790509050610140525b6101005160405261012051606052610140516080526112ca6101e0610eb6565b6101e0516101c052610160516101c051116112e8575f815250611302565b6101c0516101605180820382811161130457905090508152505b565b5f80fd04fb01180209022b0a7600b80af10519003a001800d80af101890af100f802bf005c091900988419132e81182618c0a16576797065728300030a001600000000000000000000000097ba10115da528c113462ede9c20d7adc806d93f0000000000000000000000000000000000000000000000000000000000004e20000000000000000000000000887706612730b7a227f3bffd8c9a6e6c3cb3f19e000000000000000000000000461b62cb3a7e9df8f800ae058ae92f855f2c27ca","name":"PegKeeperV2","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":false,"language":"vyper","evm_version":null,"can_be_visualized_via_sol2uml":false,"is_verified_via_sourcify":false,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Provide","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lp_amount","type":"uint256"}],"name":"Profit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"admin","type":"address"}],"name":"CommitNewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"admin","type":"address"}],"name":"ApplyNewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"action_delay","type":"uint256"}],"name":"SetNewActionDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"caller_share","type":"uint256"}],"name":"SetNewCallerShare","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"regulator","type":"address"}],"name":"SetNewRegulator","type":"event"},{"inputs":[{"name":"_pool","type":"address"},{"name":"_caller_share","type":"uint256"},{"name":"_regulator","type":"address"},{"name":"_admin","type":"address"}],"outputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"pegged","outputs":[{"name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pool","outputs":[{"name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"calc_profit","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"estimate_caller_profit","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"update","outputs":[{"name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_beneficiary","type":"address"}],"name":"update","outputs":[{"name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw_profit","outputs":[{"name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_new_action_delay","type":"uint256"}],"name":"set_new_action_delay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_new_caller_share","type":"uint256"}],"name":"set_new_caller_share","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_new_regulator","type":"address"}],"name":"set_new_regulator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_new_admin","type":"address"}],"name":"commit_new_admin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"apply_new_admin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"IS_INVERSE","outputs":[{"name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IS_NG","outputs":[{"name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"regulator","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"last_change","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debt","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"caller_share","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"future_admin","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"new_admin_deadline","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0x00000000000000000000000097ba10115da528c113462ede9c20d7adc806d93f0000000000000000000000000000000000000000000000000000000000004e20000000000000000000000000887706612730b7a227f3bffd8c9a6e6c3cb3f19e000000000000000000000000461b62cb3a7e9df8f800ae058ae92f855f2c27ca"}