Transaction Hash:
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:
573 |
PENDLE.Transfer( from=[Receiver] 0xfa103c21ea2df71dfb92b0652f8b1d795e51cdef, to=0xA69babEF1cA67A37Ffaf7a485DfFF3382056e78C, value=19280490000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x0Ae8db15...B31Abcb9B |
13.122112029348557245 Eth
Nonce: 23503
|
13.122085067396505779 Eth
Nonce: 23504
| 0.000026961952051466 | ||
0x4838B106...B0BAD5f97
Miner
| (Titan Builder) | 7.973172078341174266 Eth | 7.973172595628438228 Eth | 0.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"}}