ETH Price: $2,547.51 (+0.27%)

Transaction Decoder

Block:
22334093 at Apr-23-2025 08:27:59 PM +UTC
Transaction Fee:
0.000026961952051466 ETH $0.07
Gas Used:
44,846 Gas / 0.601211971 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
0x0Ae8db15...B31Abcb9B
13.122112029348557245 Eth
Nonce: 23503
13.122085067396505779 Eth
Nonce: 23504
0.000026961952051466
(Titan Builder)
7.973172078341174266 Eth7.973172595628438228 Eth0.000000517287263962
0x80850712...61B8da827

Execution Trace

0xfa103c21ea2df71dfb92b0652f8b1d795e51cdef.1cff79cd( )
  • 0x3376d7d055f5d7b83b0f03c886011b1dbafef276.f5537ede( )
    • PENDLE.transfer( dst=0xA69babEF1cA67A37Ffaf7a485DfFF3382056e78C, amount=19280490000000000000000 ) => ( True )
      {"Address.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity \u003e=0.6.2 \u003c0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        // solhint-disable-next-line no-inline-assembly\n        assembly { size := extcodesize(account) }\n        return size \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity\u0027s `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n        (bool success, ) = recipient.call{ value: amount }(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain`call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n      return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length \u003e 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                // solhint-disable-next-line no-inline-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"},"IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity \u003e=0.6.0 \u003c0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller\u0027s account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller\u0027s tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender\u0027s allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller\u0027s\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"},"IPENDLE.sol":{"content":"// SPDX-License-Identifier: MIT\n/*\n * MIT License\n * ===========\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n */\n\npragma solidity 0.7.6;\n\nimport \"./IERC20.sol\";\n\ninterface IPENDLE is IERC20 {\n    function initiateConfigChanges(\n        uint256 _emissionRateMultiplierNumerator,\n        uint256 _terminalInflationRateNumerator,\n        address _liquidityIncentivesRecipient,\n        bool _isBurningAllowed\n    ) external;\n\n    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);\n\n    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);\n\n    function burn(uint256 amount) external returns (bool);\n\n    function applyConfigChanges() external;\n\n    function claimLiquidityEmissions() external returns (uint256 totalEmissions);\n\n    function isPendleToken() external view returns (bool);\n\n    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n    function startTime() external view returns (uint256);\n\n    function configChangesInitiated() external view returns (uint256);\n\n    function emissionRateMultiplierNumerator() external view returns (uint256);\n\n    function terminalInflationRateNumerator() external view returns (uint256);\n\n    function liquidityIncentivesRecipient() external view returns (address);\n\n    function isBurningAllowed() external view returns (bool);\n\n    function pendingEmissionRateMultiplierNumerator() external view returns (uint256);\n\n    function pendingTerminalInflationRateNumerator() external view returns (uint256);\n\n    function pendingLiquidityIncentivesRecipient() external view returns (address);\n\n    function pendingIsBurningAllowed() external view returns (bool);\n}\n"},"PENDLE.sol":{"content":"/* solhint-disable  const-name-snakecase*/\n// SPDX-License-Identifier: MIT\n/*\n * MIT License\n * ===========\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n */\npragma solidity 0.7.6;\npragma experimental ABIEncoderV2;\n\nimport \"./IPENDLE.sol\";\nimport \"./Permissions.sol\";\nimport \"./Withdrawable.sol\";\nimport \"./SafeMath.sol\";\n\n/**\n * @notice The mechanics for delegating votes to other accounts is adapted from Compound\n *   https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol\n ***/\ncontract PENDLE is IPENDLE, Permissions, Withdrawable {\n    using SafeMath for uint256;\n\n    /// @notice A checkpoint for marking number of votes from a given block\n    struct Checkpoint {\n        uint32 fromBlock;\n        uint256 votes;\n    }\n\n    bool public constant override isPendleToken = true;\n    string public constant name = \"Pendle\";\n    string public constant symbol = \"PENDLE\";\n    uint8 public constant decimals = 18;\n    uint256 public override totalSupply;\n\n    uint256 private constant TEAM_INVESTOR_ADVISOR_AMOUNT = 94917125 * 1e18;\n    uint256 private constant ECOSYSTEM_FUND_TOKEN_AMOUNT = 46 * 1_000_000 * 1e18;\n    uint256 private constant PUBLIC_SALES_TOKEN_AMOUNT = 16582875 * 1e18;\n    uint256 private constant INITIAL_LIQUIDITY_EMISSION = 1200000 * 1e18;\n    uint256 private constant CONFIG_DENOMINATOR = 1_000_000_000_000;\n    uint256 private constant CONFIG_CHANGES_TIME_LOCK = 7 days;\n    uint256 public override emissionRateMultiplierNumerator;\n    uint256 public override terminalInflationRateNumerator;\n    address public override liquidityIncentivesRecipient;\n    bool public override isBurningAllowed;\n    uint256 public override pendingEmissionRateMultiplierNumerator;\n    uint256 public override pendingTerminalInflationRateNumerator;\n    address public override pendingLiquidityIncentivesRecipient;\n    bool public override pendingIsBurningAllowed;\n    uint256 public override configChangesInitiated;\n    uint256 public override startTime;\n    uint256 public lastWeeklyEmission;\n    uint256 public lastWeekEmissionSent;\n\n    mapping(address =\u003e mapping(address =\u003e uint256)) internal allowances;\n    mapping(address =\u003e uint256) internal balances;\n    mapping(address =\u003e address) public delegates;\n\n    /// @notice A record of votes checkpoints for each account, by index\n    mapping(address =\u003e mapping(uint32 =\u003e Checkpoint)) public checkpoints;\n\n    /// @notice The number of checkpoints for each account\n    mapping(address =\u003e uint32) public numCheckpoints;\n\n    /// @notice The EIP-712 typehash for the contract\u0027s domain\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n    /// @notice The EIP-712 typehash for the delegation struct used by the contract\n    bytes32 public constant DELEGATION_TYPEHASH =\n        keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n    /// @notice A record of states for signing / validating signatures\n    mapping(address =\u003e uint256) public nonces;\n\n    /// @notice An event thats emitted when an account changes its delegate\n    event DelegateChanged(\n        address indexed delegator,\n        address indexed fromDelegate,\n        address indexed toDelegate\n    );\n\n    /// @notice An event thats emitted when a delegate account\u0027s vote balance changes\n    event DelegateVotesChanged(\n        address indexed delegate,\n        uint256 previousBalance,\n        uint256 newBalance\n    );\n\n    event PendingConfigChanges(\n        uint256 pendingEmissionRateMultiplierNumerator,\n        uint256 pendingTerminalInflationRateNumerator,\n        address pendingLiquidityIncentivesRecipient,\n        bool pendingIsBurningAllowed\n    );\n\n    event ConfigsChanged(\n        uint256 emissionRateMultiplierNumerator,\n        uint256 terminalInflationRateNumerator,\n        address liquidityIncentivesRecipient,\n        bool isBurningAllowed\n    );\n\n    /**\n     * @notice Construct a new PENDLE token\n     */\n    constructor(\n        address _governance,\n        address pendleTeamTokens,\n        address pendleEcosystemFund,\n        address salesMultisig,\n        address _liquidityIncentivesRecipient\n    ) Permissions(_governance) {\n        require(\n            pendleTeamTokens != address(0) \u0026\u0026\n                pendleEcosystemFund != address(0) \u0026\u0026\n                salesMultisig != address(0) \u0026\u0026\n                _liquidityIncentivesRecipient != address(0),\n            \"ZERO_ADDRESS\"\n        );\n        _mint(pendleTeamTokens, TEAM_INVESTOR_ADVISOR_AMOUNT);\n        _mint(pendleEcosystemFund, ECOSYSTEM_FUND_TOKEN_AMOUNT);\n        _mint(salesMultisig, PUBLIC_SALES_TOKEN_AMOUNT);\n        _mint(_liquidityIncentivesRecipient, INITIAL_LIQUIDITY_EMISSION * 26);\n        emissionRateMultiplierNumerator = (CONFIG_DENOMINATOR * 989) / 1000; // emission rate = 98.9% -\u003e 1.1% decay\n        terminalInflationRateNumerator = 379848538; // terminal inflation rate = 2% =\u003e weekly inflation = 0.0379848538%\n        liquidityIncentivesRecipient = _liquidityIncentivesRecipient;\n        startTime = block.timestamp;\n        lastWeeklyEmission = INITIAL_LIQUIDITY_EMISSION;\n        lastWeekEmissionSent = 26; // already done liquidity emissions for the first 26 weeks\n    }\n\n    /**\n     * @notice Approve `spender` to transfer up to `amount` from `src`\n     * @dev This will overwrite the approval amount for `spender`\n     *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n     * @param spender The address of the account which may transfer tokens\n     * @param amount The number of tokens that are approved\n     * @return Whether or not the approval succeeded\n     **/\n    function approve(address spender, uint256 amount) external override returns (bool) {\n        _approve(msg.sender, spender, amount);\n        return true;\n    }\n\n    /**\n     * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n     * @param dst The address of the destination account\n     * @param amount The number of tokens to transfer\n     * @return Whether or not the transfer succeeded\n     */\n    function transfer(address dst, uint256 amount) external override returns (bool) {\n        _transfer(msg.sender, dst, amount);\n        return true;\n    }\n\n    /**\n     * @notice Transfer `amount` tokens from `src` to `dst`\n     * @param src The address of the source account\n     * @param dst The address of the destination account\n     * @param amount The number of tokens to transfer\n     * @return Whether or not the transfer succeeded\n     */\n    function transferFrom(\n        address src,\n        address dst,\n        uint256 amount\n    ) external override returns (bool) {\n        _transfer(src, dst, amount);\n        _approve(\n            src,\n            msg.sender,\n            allowances[src][msg.sender].sub(amount, \"TRANSFER_EXCEED_ALLOWANCE\")\n        );\n        return true;\n    }\n\n    /**\n     * @dev Increases the allowance granted to spender by the caller.\n     * @param spender The address to increase the allowance from.\n     * @param addedValue The amount allowance to add.\n     * @return returns true if allowance has increased, otherwise false\n     **/\n    function increaseAllowance(address spender, uint256 addedValue)\n        public\n        override\n        returns (bool)\n    {\n        _approve(msg.sender, spender, allowances[msg.sender][spender].add(addedValue));\n        return true;\n    }\n\n    /**\n     * @dev Decreases the allowance granted to spender by the caller.\n     * @param spender The address to reduce the allowance from.\n     * @param subtractedValue The amount allowance to subtract.\n     * @return Returns true if allowance has decreased, otherwise false.\n     **/\n    function decreaseAllowance(address spender, uint256 subtractedValue)\n        public\n        override\n        returns (bool)\n    {\n        _approve(\n            msg.sender,\n            spender,\n            allowances[msg.sender][spender].sub(subtractedValue, \"NEGATIVE_ALLOWANCE\")\n        );\n        return true;\n    }\n\n    /**\n     * @dev Burns an amount of tokens from the msg.sender\n     * @param amount The amount to burn\n     * @return Returns true if the operation is successful\n     **/\n    function burn(uint256 amount) public override returns (bool) {\n        require(isBurningAllowed, \"BURNING_NOT_ALLOWED\");\n        _burn(msg.sender, amount);\n        return true;\n    }\n\n    /**\n     * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n     * @param account The address of the account holding the funds\n     * @param spender The address of the account spending the funds\n     * @return The number of tokens approved\n     **/\n    function allowance(address account, address spender) external view override returns (uint256) {\n        return allowances[account][spender];\n    }\n\n    /**\n     * @notice Get the number of tokens held by the `account`\n     * @param account The address of the account to get the balance of\n     * @return The number of tokens held\n     */\n    function balanceOf(address account) external view override returns (uint256) {\n        return balances[account];\n    }\n\n    /**\n     * @notice Gets the current votes balance for `account`\n     * @param account The address to get votes balance\n     * @return The number of current votes for `account`\n     */\n    function getCurrentVotes(address account) external view returns (uint256) {\n        uint32 nCheckpoints = numCheckpoints[account];\n        return nCheckpoints \u003e 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n    }\n\n    /**\n     * @notice Delegate votes from `msg.sender` to `delegatee`\n     * @param delegatee The address to delegate votes to\n     */\n    function delegate(address delegatee) public {\n        return _delegate(msg.sender, delegatee);\n    }\n\n    /**\n     * @notice Delegates votes from signatory to `delegatee`\n     * @param delegatee The address to delegate votes to\n     * @param nonce The contract state required to match the signature\n     * @param expiry The time at which to expire the signature\n     * @param v The recovery byte of the signature\n     * @param r Half of the ECDSA signature pair\n     * @param s Half of the ECDSA signature pair\n     */\n    function delegateBySig(\n        address delegatee,\n        uint256 nonce,\n        uint256 expiry,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public {\n        bytes32 domainSeparator =\n            keccak256(\n                abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))\n            );\n        bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n        bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n        address signatory = ecrecover(digest, v, r, s);\n        require(signatory != address(0), \"INVALID_SIGNATURE\");\n        require(nonce == nonces[signatory]++, \"INVALID_NONCE\");\n        require(block.timestamp \u003c= expiry, \"SIGNATURE_EXPIRED\");\n        return _delegate(signatory, delegatee);\n    }\n\n    /**\n     * @notice Determine the prior number of votes for an account as of a block number\n     * @dev Block number must be a finalized block or else\n                this function will revert to prevent misinformation\n     * @param account The address of the account to check\n     * @param blockNumber The block number to get the vote balance at\n     * @return The number of votes the account had as of the given block\n     */\n    function getPriorVotes(address account, uint256 blockNumber)\n        public\n        view\n        override\n        returns (uint256)\n    {\n        require(blockNumber \u003c block.number, \"NOT_YET_DETERMINED\");\n\n        uint32 nCheckpoints = numCheckpoints[account];\n        if (nCheckpoints == 0) {\n            return 0;\n        }\n\n        // First check most recent balance\n        if (checkpoints[account][nCheckpoints - 1].fromBlock \u003c= blockNumber) {\n            return checkpoints[account][nCheckpoints - 1].votes;\n        }\n\n        // Next check implicit zero balance\n        if (checkpoints[account][0].fromBlock \u003e blockNumber) {\n            return 0;\n        }\n\n        uint32 lower = 0;\n        uint32 upper = nCheckpoints - 1;\n        while (upper \u003e lower) {\n            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n            Checkpoint memory cp = checkpoints[account][center];\n            if (cp.fromBlock == blockNumber) {\n                return cp.votes;\n            } else if (cp.fromBlock \u003c blockNumber) {\n                lower = center;\n            } else {\n                upper = center - 1;\n            }\n        }\n        return checkpoints[account][lower].votes;\n    }\n\n    function _delegate(address delegator, address delegatee) internal {\n        address currentDelegate = delegates[delegator];\n        uint256 delegatorBalance = balances[delegator];\n        delegates[delegator] = delegatee;\n\n        emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n        _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n    }\n\n    function _transfer(\n        address src,\n        address dst,\n        uint256 amount\n    ) internal {\n        require(src != address(0), \"SENDER_ZERO_ADDR\");\n        require(dst != address(0), \"RECEIVER_ZERO_ADDR\");\n        require(dst != address(this), \"SEND_TO_TOKEN_CONTRACT\");\n\n        balances[src] = balances[src].sub(amount, \"TRANSFER_EXCEED_BALANCE\");\n        balances[dst] = balances[dst].add(amount);\n        emit Transfer(src, dst, amount);\n\n        _moveDelegates(delegates[src], delegates[dst], amount);\n    }\n\n    function _approve(\n        address src,\n        address dst,\n        uint256 amount\n    ) internal virtual {\n        require(src != address(0), \"OWNER_ZERO_ADDR\");\n        require(dst != address(0), \"SPENDER_ZERO_ADDR\");\n\n        allowances[src][dst] = amount;\n        emit Approval(src, dst, amount);\n    }\n\n    function _moveDelegates(\n        address srcRep,\n        address dstRep,\n        uint256 amount\n    ) internal {\n        if (srcRep != dstRep \u0026\u0026 amount \u003e 0) {\n            if (srcRep != address(0)) {\n                uint32 srcRepNum = numCheckpoints[srcRep];\n                uint256 srcRepOld = srcRepNum \u003e 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n                uint256 srcRepNew = srcRepOld.sub(amount);\n                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n            }\n\n            if (dstRep != address(0)) {\n                uint32 dstRepNum = numCheckpoints[dstRep];\n                uint256 dstRepOld = dstRepNum \u003e 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n                uint256 dstRepNew = dstRepOld.add(amount);\n                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n            }\n        }\n    }\n\n    function _writeCheckpoint(\n        address delegatee,\n        uint32 nCheckpoints,\n        uint256 oldVotes,\n        uint256 newVotes\n    ) internal {\n        uint32 blockNumber = safe32(block.number, \"BLOCK_NUM_EXCEED_32_BITS\");\n\n        if (\n            nCheckpoints \u003e 0 \u0026\u0026 checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber\n        ) {\n            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n        } else {\n            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n            numCheckpoints[delegatee] = nCheckpoints + 1;\n        }\n\n        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n    }\n\n    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n        require(n \u003c 2**32, errorMessage);\n        return uint32(n);\n    }\n\n    function getChainId() internal pure returns (uint256) {\n        uint256 chainId;\n        assembly {\n            chainId := chainid()\n        }\n        return chainId;\n    }\n\n    function initiateConfigChanges(\n        uint256 _emissionRateMultiplierNumerator,\n        uint256 _terminalInflationRateNumerator,\n        address _liquidityIncentivesRecipient,\n        bool _isBurningAllowed\n    ) external override onlyGovernance {\n        require(_liquidityIncentivesRecipient != address(0), \"ZERO_ADDRESS\");\n        pendingEmissionRateMultiplierNumerator = _emissionRateMultiplierNumerator;\n        pendingTerminalInflationRateNumerator = _terminalInflationRateNumerator;\n        pendingLiquidityIncentivesRecipient = _liquidityIncentivesRecipient;\n        pendingIsBurningAllowed = _isBurningAllowed;\n        emit PendingConfigChanges(\n            _emissionRateMultiplierNumerator,\n            _terminalInflationRateNumerator,\n            _liquidityIncentivesRecipient,\n            _isBurningAllowed\n        );\n        configChangesInitiated = block.timestamp;\n    }\n\n    function applyConfigChanges() external override {\n        require(configChangesInitiated != 0, \"UNINITIATED_CONFIG_CHANGES\");\n        require(\n            block.timestamp \u003e configChangesInitiated + CONFIG_CHANGES_TIME_LOCK,\n            \"TIMELOCK_IS_NOT_OVER\"\n        );\n\n        _mintLiquidityEmissions(); // We must settle the pending liquidity emissions first, to make sure the weeks in the past follow the old configs\n\n        emissionRateMultiplierNumerator = pendingEmissionRateMultiplierNumerator;\n        terminalInflationRateNumerator = pendingTerminalInflationRateNumerator;\n        liquidityIncentivesRecipient = pendingLiquidityIncentivesRecipient;\n        isBurningAllowed = pendingIsBurningAllowed;\n        configChangesInitiated = 0;\n        emit ConfigsChanged(\n            emissionRateMultiplierNumerator,\n            terminalInflationRateNumerator,\n            liquidityIncentivesRecipient,\n            isBurningAllowed\n        );\n    }\n\n    function claimLiquidityEmissions() external override returns (uint256 totalEmissions) {\n        require(msg.sender == liquidityIncentivesRecipient, \"NOT_INCENTIVES_RECIPIENT\");\n        totalEmissions = _mintLiquidityEmissions();\n    }\n\n    function _mintLiquidityEmissions() internal returns (uint256 totalEmissions) {\n        uint256 _currentWeek = _getCurrentWeek();\n        if (_currentWeek \u003c= lastWeekEmissionSent) {\n            return 0;\n        }\n        for (uint256 i = lastWeekEmissionSent + 1; i \u003c= _currentWeek; i++) {\n            if (i \u003c= 259) {\n                lastWeeklyEmission = lastWeeklyEmission.mul(emissionRateMultiplierNumerator).div(\n                    CONFIG_DENOMINATOR\n                );\n            } else {\n                lastWeeklyEmission = totalSupply.mul(terminalInflationRateNumerator).div(\n                    CONFIG_DENOMINATOR\n                );\n            }\n            _mint(liquidityIncentivesRecipient, lastWeeklyEmission);\n            totalEmissions = totalEmissions.add(lastWeeklyEmission);\n        }\n        lastWeekEmissionSent = _currentWeek;\n    }\n\n    // get current 1-indexed week id\n    function _getCurrentWeek() internal view returns (uint256 weekId) {\n        weekId = (block.timestamp - startTime) / (7 days) + 1;\n    }\n\n    function _mint(address account, uint256 amount) internal {\n        require(account != address(0), \"MINT_TO_ZERO_ADDR\");\n\n        totalSupply = totalSupply.add(amount);\n        balances[account] = balances[account].add(amount);\n        emit Transfer(address(0), account, amount);\n    }\n\n    function _burn(address account, uint256 amount) internal {\n        require(account != address(0), \"BURN_FROM_ZERO_ADDRESS\");\n\n        uint256 accountBalance = balances[account];\n        require(accountBalance \u003e= amount, \"BURN_EXCEED_BALANCE\");\n        balances[account] = accountBalance.sub(amount);\n        totalSupply = totalSupply.sub(amount);\n\n        emit Transfer(account, address(0), amount);\n    }\n}\n"},"Permissions.sol":{"content":"// SPDX-License-Identifier: MIT\n/*\n * MIT License\n * ===========\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n */\npragma solidity 0.7.6;\n\nimport \"./IERC20.sol\";\n\nabstract contract Permissions {\n    address public governance;\n    address public pendingGovernance;\n    address internal initializer;\n\n    event GovernanceClaimed(address newGovernance, address previousGovernance);\n\n    event TransferGovernancePending(address pendingGovernance);\n\n    constructor(address _governance) {\n        require(_governance != address(0), \"ZERO_ADDRESS\");\n        initializer = msg.sender;\n        governance = _governance;\n    }\n\n    modifier initialized() {\n        require(initializer == address(0), \"NOT_INITIALIZED\");\n        _;\n    }\n\n    modifier onlyGovernance() {\n        require(msg.sender == governance, \"ONLY_GOVERNANCE\");\n        _;\n    }\n\n    /**\n     * @dev Allows the pendingGovernance address to finalize the change governance process.\n     */\n    function claimGovernance() public {\n        require(pendingGovernance == msg.sender, \"WRONG_GOVERNANCE\");\n        emit GovernanceClaimed(pendingGovernance, governance);\n        governance = pendingGovernance;\n        pendingGovernance = address(0);\n    }\n\n    /**\n     * @dev Allows the current governance to set the pendingGovernance address.\n     * @param _governance The address to transfer ownership to.\n     */\n    function transferGovernance(address _governance) public onlyGovernance {\n        require(_governance != address(0), \"ZERO_ADDRESS\");\n        pendingGovernance = _governance;\n\n        emit TransferGovernancePending(pendingGovernance);\n    }\n}\n"},"SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity \u003e=0.6.0 \u003c0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./SafeMath.sol\";\nimport \"./Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using SafeMath for uint256;\n    using Address for address;\n\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // \u0027safeIncreaseAllowance\u0027 and \u0027safeDecreaseAllowance\u0027\n        // solhint-disable-next-line max-line-length\n        require((value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity\u0027s return data size checking mechanism, since\n        // we\u0027re implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length \u003e 0) { // Return data is optional\n            // solhint-disable-next-line max-line-length\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"},"SafeMath.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity \u003e=0.6.0 \u003c0.8.0;\n\n/**\n * @dev Wrappers over Solidity\u0027s arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it\u0027s recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        uint256 c = a + b;\n        if (c \u003c a) return (false, 0);\n        return (true, c);\n    }\n\n    /**\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b \u003e a) return (false, 0);\n        return (true, a - b);\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        // Gas optimization: this is cheaper than requiring \u0027a\u0027 not being zero, but the\n        // benefit is lost if \u0027b\u0027 is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) return (true, 0);\n        uint256 c = a * b;\n        if (c / a != b) return (false, 0);\n        return (true, c);\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b == 0) return (false, 0);\n        return (true, a / b);\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b == 0) return (false, 0);\n        return (true, a % b);\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity\u0027s `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c \u003e= a, \"SafeMath: addition overflow\");\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity\u0027s `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b \u003c= a, \"SafeMath: subtraction overflow\");\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity\u0027s `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (a == 0) return 0;\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b \u003e 0, \"SafeMath: division by zero\");\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b \u003e 0, \"SafeMath: modulo by zero\");\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity\u0027s `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b \u003c= a, errorMessage);\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\n     *\n     * Counterpart to Solidity\u0027s `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b \u003e 0, errorMessage);\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity\u0027s `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b \u003e 0, errorMessage);\n        return a % b;\n    }\n}\n"},"Withdrawable.sol":{"content":"// SPDX-License-Identifier: MIT\n/*\n * MIT License\n * ===========\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n */\npragma solidity 0.7.6;\n\nimport \"./IERC20.sol\";\nimport \"./SafeERC20.sol\";\nimport \"./Permissions.sol\";\n\nabstract contract Withdrawable is Permissions {\n    using SafeERC20 for IERC20;\n\n    event EtherWithdraw(uint256 amount, address sendTo);\n    event TokenWithdraw(IERC20 token, uint256 amount, address sendTo);\n\n    /**\n     * @dev Allows governance to withdraw Ether in a Pendle contract\n     *      in case of accidental ETH transfer into the contract.\n     * @param amount The amount of Ether to withdraw.\n     * @param sendTo The recipient address.\n     */\n    function withdrawEther(uint256 amount, address payable sendTo) external onlyGovernance {\n        (bool success, ) = sendTo.call{value: amount}(\"\");\n        require(success, \"WITHDRAW_FAILED\");\n        emit EtherWithdraw(amount, sendTo);\n    }\n\n    /**\n     * @dev Allows governance to withdraw all IERC20 compatible tokens in a Pendle\n     *      contract in case of accidental token transfer into the contract.\n     * @param token IERC20 The address of the token contract.\n     * @param amount The amount of IERC20 tokens to withdraw.\n     * @param sendTo The recipient address.\n     */\n    function withdrawToken(\n        IERC20 token,\n        uint256 amount,\n        address sendTo\n    ) external onlyGovernance {\n        token.safeTransfer(sendTo, amount);\n        emit TokenWithdraw(token, amount, sendTo);\n    }\n}\n"}}