Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PiteasRouter
- Optimization enabled
- false
- Compiler version
- v0.8.18+commit.87f61d96
- EVM Version
- default
- Verified at
- 2023-07-07T21:39:49.445468Z
Contract source code
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: @openzeppelin/contracts/utils/math/SafeMath.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
// File: @openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
// EIP-2612 is Final as of 2022-11-01. This file is deprecated.
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/interfaces/IDaiLikePermit.sol
pragma solidity ^0.8.0;
interface IDaiLikePermit {
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/interfaces/IPermit2.sol
pragma solidity ^0.8.0;
interface IPermit2 {
struct PermitDetails {
// ERC20 token address
address token;
// the maximum amount allowed to spend
uint160 amount;
// timestamp at which a spender's token allowances become invalid
uint48 expiration;
// an incrementing value indexed per owner,token,and spender for each signature
uint48 nonce;
}
/// @notice The permit message signed for a single token allownce
struct PermitSingle {
// the permit data for a single token alownce
PermitDetails details;
// address permissioned on the allowed tokens
address spender;
// deadline on the permit signature
uint256 sigDeadline;
}
/// @notice Packed allowance
struct PackedAllowance {
// amount allowed
uint160 amount;
// permission expiry
uint48 expiration;
// an incrementing value indexed per owner,token,and spender for each signature
uint48 nonce;
}
function transferFrom(address user, address spender, uint160 amount, address token) external;
function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;
function allowance(address user, address token, address spender) external view returns (PackedAllowance memory);
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/interfaces/IWETH.sol
pragma solidity ^0.8.0;
interface IWETH is IERC20 {
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);
function deposit() external payable;
function withdraw(uint256 amount) external;
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/libraries/RevertReasonForwarder.sol
pragma solidity ^0.8.0;
/// @title Revert reason forwarder.
library RevertReasonForwarder {
/// @dev Forwards latest externall call revert.
function reRevert() internal pure {
// bubble up revert reason from latest external call
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/libraries/SafeERC20.sol
pragma solidity ^0.8.0;
/**
* @title Implements efficient safe methods for ERC20 interface.
* @notice Compared to the standard ERC20, this implementation offers several enhancements:
* 1. more gas-efficient, providing significant savings in transaction costs.
* 2. support for different permit implementations
* 3. forceApprove functionality
* 4. support for WETH deposit and withdraw
*/
library SafeERC20 {
error SafeTransferFailed();
error SafeTransferFromFailed();
error ForceApproveFailed();
error SafeIncreaseAllowanceFailed();
error SafeDecreaseAllowanceFailed();
error SafePermitBadLength();
error Permit2TransferAmountTooHigh();
// Uniswap Permit2 address
address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector
uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
/**
* @notice Fetches the balance of a specific ERC20 token held by an account.
* Consumes less gas then regular `ERC20.balanceOf`.
* @param token The IERC20 token contract for which the balance will be fetched.
* @param account The address of the account whose token balance will be fetched.
* @return tokenBalance The balance of the specified ERC20 token held by the account.
*/
function safeBalanceOf(
IERC20 token,
address account
) internal view returns(uint256 tokenBalance) {
bytes4 selector = IERC20.balanceOf.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
mstore(0x00, selector)
mstore(0x04, account)
let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20)
tokenBalance := mload(0)
if or(iszero(success), lt(returndatasize(), 0x20)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}
/**
* @notice Attempts to safely transfer tokens from one address to another.
* @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom.
* Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
* @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom.
*/
function safeTransferFromUniversal(
IERC20 token,
address from,
address to,
uint256 amount,
bool permit2
) internal {
if (permit2) {
safeTransferFromPermit2(token, from, to, amount);
} else {
safeTransferFrom(token, from, to, amount);
}
}
/**
* @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
*/
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
bytes4 selector = token.transferFrom.selector;
bool success;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), from)
mstore(add(data, 0x24), to)
mstore(add(data, 0x44), amount)
success := call(gas(), token, 0, data, 100, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
if (!success) revert SafeTransferFromFailed();
}
/**
* @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
*/
function safeTransferFromPermit2(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh();
bytes4 selector = IPermit2.transferFrom.selector;
bool success;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), from)
mstore(add(data, 0x24), to)
mstore(add(data, 0x44), amount)
mstore(add(data, 0x64), token)
success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0)
if success {
success := gt(extcodesize(_PERMIT2), 0)
}
}
if (!success) revert SafeTransferFromFailed();
}
/**
* @notice Attempts to safely transfer tokens to another address.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param value The amount of tokens to transfer.
*/
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
if (!_makeCall(token, token.transfer.selector, to, value)) {
revert SafeTransferFailed();
}
}
/**
* @notice Attempts to approve a spender to spend a certain amount of tokens.
* @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call.
* @param token The IERC20 token contract on which the call will be made.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function forceApprove(
IERC20 token,
address spender,
uint256 value
) internal {
if (!_makeCall(token, token.approve.selector, spender, value)) {
if (
!_makeCall(token, token.approve.selector, spender, 0) ||
!_makeCall(token, token.approve.selector, spender, value)
) {
revert ForceApproveFailed();
}
}
}
/**
* @notice Safely increases the allowance of a spender.
* @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction.
* Then uses `forceApprove` to increase the allowance.
* @param token The IERC20 token contract on which the call will be made.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to increase the allowance by.
*/
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed();
forceApprove(token, spender, allowance + value);
}
/**
* @notice Safely decreases the allowance of a spender.
* @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction.
* Then uses `forceApprove` to increase the allowance.
* @param token The IERC20 token contract on which the call will be made.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to decrease the allowance by.
*/
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > allowance) revert SafeDecreaseAllowanceFailed();
forceApprove(token, spender, allowance - value);
}
/**
* @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.
* Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
* @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
* @param token The IERC20 token to execute the permit function on.
* @param permit The permit data to be used in the function call.
*/
function safePermit(IERC20 token, bytes calldata permit) internal {
if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert();
}
/**
* @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters.
* Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
* @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
* @param token The IERC20 token to execute the permit function on.
* @param owner The owner of the tokens for which the permit is made.
* @param spender The spender allowed to spend the tokens by the permit.
* @param permit The permit data to be used in the function call.
*/
function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal {
if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert();
}
/**
* @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.
* @dev Invokes `tryPermit` with sender as owner and contract as spender.
* @param token The IERC20 token to execute the permit function on.
* @param permit The permit data to be used in the function call.
* @return success Returns true if the permit function was successfully executed, false otherwise.
*/
function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) {
return tryPermit(token, msg.sender, address(this), permit);
}
/**
* @notice The function attempts to call the permit function on a given ERC20 token.
* @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2.
* It accommodates both Compact and Full formats of these permit types.
* Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter
* for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by
* gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and
* zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one
* before invocation for optimized performance.
* @param token The address of the ERC20 token on which to call the permit function.
* @param owner The owner of the tokens. This address should have signed the off-chain permit.
* @param spender The address which will be approved for transfer of tokens.
* @param permit The off-chain permit data, containing different fields depending on the type of permit function.
* @return success A boolean indicating whether the permit call was successful.
*/
function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) {
// load function selectors for different permit standards
bytes4 permitSelector = IERC20Permit.permit.selector;
bytes4 daiPermitSelector = IDaiLikePermit.permit.selector;
bytes4 permit2Selector = IPermit2.permit.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
// Switch case for different permit lengths, indicating different permit standards
switch permit.length
// Compact IERC20Permit
case 100 {
mstore(ptr, permitSelector) // store selector
mstore(add(ptr, 0x04), owner) // store owner
mstore(add(ptr, 0x24), spender) // store spender
// Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)
{ // stack too deep
let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23
let vs := calldataload(add(permit.offset, 0x44)) // loads permit.offset 0x44..0x63
calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // store value = copy permit.offset 0x00..0x19
mstore(add(ptr, 0x64), sub(deadline, 1)) // store deadline = deadline - 1
mstore(add(ptr, 0x84), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28)
calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r = copy permit.offset 0x24..0x43
mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) // store s = vs without most significant bit
}
// IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
}
// Compact IDaiLikePermit
case 72 {
mstore(ptr, daiPermitSelector) // store selector
mstore(add(ptr, 0x04), owner) // store owner
mstore(add(ptr, 0x24), spender) // store spender
// Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)
{ // stack too deep
let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07
let vs := calldataload(add(permit.offset, 0x28)) // loads permit.offset 0x28..0x47
mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce = copy permit.offset 0x00..0x03
mstore(add(ptr, 0x64), sub(expiry, 1)) // store expiry = expiry - 1
mstore(add(ptr, 0x84), true) // store allowed = true
mstore(add(ptr, 0xa4), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28)
calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // store r = copy permit.offset 0x08..0x27
mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) // store s = vs without most significant bit
}
// IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
success := call(gas(), token, 0, ptr, 0x104, 0, 0)
}
// IERC20Permit
case 224 {
mstore(ptr, permitSelector)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
}
// IDaiLikePermit
case 256 {
mstore(ptr, daiPermitSelector)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
success := call(gas(), token, 0, ptr, 0x104, 0, 0)
}
// Compact IPermit2
case 96 {
// Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)
mstore(ptr, permit2Selector) // store selector
mstore(add(ptr, 0x04), owner) // store owner
mstore(add(ptr, 0x24), token) // store token
calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff)
mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b
mstore(add(ptr, 0xa4), spender) // store spender
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff)
mstore(add(ptr, 0xe4), 0x100) // store offset = 256
mstore(add(ptr, 0x104), 0x40) // store length = 64
calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r = copy permit.offset 0x20..0x3f
calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs = copy permit.offset 0x40..0x5f
// IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
}
// IPermit2
case 352 {
mstore(ptr, permit2Selector)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
}
// Unknown
default {
mstore(ptr, _PERMIT_LENGTH_ERROR)
revert(ptr, 4)
}
}
}
/**
* @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns.
* @param token The IERC20 token contract on which the call will be made.
* @param selector The function signature that is to be called on the token contract.
* @param to The address to which the token amount will be transferred.
* @param amount The token amount to be transferred.
* @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure.
* In case of success but no returned data, validates that the contract code exists.
* In case of returned data, ensures that it's a boolean `true`.
*/
function _makeCall(
IERC20 token,
bytes4 selector,
address to,
uint256 amount
) private returns (bool success) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), to)
mstore(add(data, 0x24), amount)
success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
/**
* @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`.
* @param weth The IWETH token contract.
* @param amount The amount of Ether to deposit into the IWETH contract.
*/
function safeDeposit(IWETH weth, uint256 amount) internal {
if (amount > 0) {
bytes4 selector = IWETH.deposit.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
mstore(0, selector)
if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
/**
* @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`.
* @dev Uses inline assembly to interact with the IWETH contract.
* @param weth The IWETH token contract.
* @param amount The amount of wrapped Ether to withdraw from the IWETH contract.
*/
function safeWithdraw(IWETH weth, uint256 amount) internal {
bytes4 selector = IWETH.withdraw.selector;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
mstore(0, selector)
mstore(4, amount)
if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}
/**
* @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient.
* Consumes less gas then regular `IWETH.withdraw`.
* @param weth The IWETH token contract.
* @param amount The amount of wrapped Ether to withdraw from the IWETH contract.
* @param to The recipient of the withdrawn Ether.
*/
function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal {
safeWithdraw(weth, amount);
if (to != address(this)) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}
}
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/interfaces/ISwapManager.sol
pragma solidity ^0.8.18;
interface ISwapManager {
function swap(bytes calldata data) external payable returns (uint256);
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/libraries/StringUtil.sol
pragma solidity ^0.8.0;
/// @title Library with gas-efficient string operations
library StringUtil {
function toHex(uint256 value) internal pure returns (string memory) {
return toHex(abi.encodePacked(value));
}
function toHex(address value) internal pure returns (string memory) {
return toHex(abi.encodePacked(value));
}
/// @dev this is the assembly adaptation of highly optimized toHex16 code from Mikhail Vladimirov
/// https://stackoverflow.com/a/69266989
function toHex(bytes memory data) internal pure returns (string memory result) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
function _toHex16(input) -> output {
output := or(
and(input, 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000),
shr(64, and(input, 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000))
)
output := or(
and(output, 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000),
shr(32, and(output, 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000))
)
output := or(
and(output, 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000),
shr(16, and(output, 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000))
)
output := or(
and(output, 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000),
shr(8, and(output, 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000))
)
output := or(
shr(4, and(output, 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000)),
shr(8, and(output, 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00))
)
output := add(
add(0x3030303030303030303030303030303030303030303030303030303030303030, output),
mul(
and(
shr(4, add(output, 0x0606060606060606060606060606060606060606060606060606060606060606)),
0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
),
7 // Change 7 to 39 for lower case output
)
)
}
result := mload(0x40)
let length := mload(data)
let resultLength := shl(1, length)
let toPtr := add(result, 0x22) // 32 bytes for length + 2 bytes for '0x'
mstore(0x40, add(toPtr, resultLength)) // move free memory pointer
mstore(add(result, 2), 0x3078) // 0x3078 is right aligned so we write to `result + 2`
// to store the last 2 bytes in the beginning of the string
mstore(result, add(resultLength, 2)) // extra 2 bytes for '0x'
for {
let fromPtr := add(data, 0x20)
let endPtr := add(fromPtr, length)
} lt(fromPtr, endPtr) {
fromPtr := add(fromPtr, 0x20)
} {
let rawData := mload(fromPtr)
let hexData := _toHex16(rawData)
mstore(toPtr, hexData)
toPtr := add(toPtr, 0x20)
hexData := _toHex16(shl(128, rawData))
mstore(toPtr, hexData)
toPtr := add(toPtr, 0x20)
}
}
}
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/libraries/RevertReasonParser.sol
pragma solidity ^0.8.0;
/** @title Library that allows to parse unsuccessful arbitrary calls revert reasons.
* See https://solidity.readthedocs.io/en/latest/control-structures.html#revert for details.
* Note that we assume revert reason being abi-encoded as Error(string) so it may fail to parse reason
* if structured reverts appear in the future.
*
* All unsuccessful parsings get encoded as Unknown(data) string
*/
library RevertReasonParser {
using StringUtil for uint256;
using StringUtil for bytes;
error InvalidRevertReason();
bytes4 private constant _ERROR_SELECTOR = bytes4(keccak256("Error(string)"));
bytes4 private constant _PANIC_SELECTOR = bytes4(keccak256("Panic(uint256)"));
/// @dev Parses error `data` and returns actual with `prefix`.
function parse(bytes memory data, string memory prefix) internal pure returns (string memory) {
// https://solidity.readthedocs.io/en/latest/control-structures.html#revert
// We assume that revert reason is abi-encoded as Error(string)
bytes4 selector;
if (data.length >= 4) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
selector := mload(add(data, 0x20))
}
}
// 68 = 4-byte selector + 32 bytes offset + 32 bytes length
if (selector == _ERROR_SELECTOR && data.length >= 68) {
string memory reason;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
// 68 = 32 bytes data length + 4-byte selector + 32 bytes offset
reason := add(data, 68)
}
/*
revert reason is padded up to 32 bytes with ABI encoder: Error(string)
also sometimes there is extra 32 bytes of zeros padded in the end:
https://github.com/ethereum/solidity/issues/10170
because of that we can't check for equality and instead check
that string length + extra 68 bytes is equal or greater than overall data length
*/
if (data.length >= 68 + bytes(reason).length) {
return string.concat(prefix, "Error(", reason, ")");
}
}
// 36 = 4-byte selector + 32 bytes integer
else if (selector == _PANIC_SELECTOR && data.length == 36) {
uint256 code;
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
// 36 = 32 bytes data length + 4-byte selector
code := mload(add(data, 36))
}
return string.concat(prefix, "Panic(", code.toHex(), ")");
}
return string.concat(prefix, "Unknown(", data.toHex(), ")");
}
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/libraries/PitERC20.sol
pragma solidity ^0.8.18;
library PitERC20 {
using SafeERC20 for IERC20;
using SafeERC20 for IWETH;
error InsufficientBalance();
error ApproveCalledOnETH();
error NotEnoughValue();
error FromIsNotSender();
error ToIsNotThis();
error ETHTransferFailed();
error ExecutorError();
uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
uint256 private constant _MAX_APPROVE = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
IERC20 private constant _ZERO_ADDRESS = IERC20(address(0));
IWETH internal constant WETH = IWETH(0xA1077a294dDE1B09bB078844df40758a5D0f9a27);
/// @dev Returns true if `token` is ETH.
function isETH(IERC20 token) internal pure returns (bool) {
return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS);
}
/// @dev Returns `account` ERC20 `token` balance.
function pBalanceOf(IERC20 token, address account) internal view returns (uint256) {
if (isETH(token)) {
return account.balance;
} else {
return token.balanceOf(account);
}
}
/// @dev Reverts if `token` is ETH, otherwise performs ERC20 forceApprove.
function pApprove(
IERC20 token,
address to,
uint256 amount
) internal {
if (isETH(token)) revert ApproveCalledOnETH();
uint256 allowance = token.allowance(address(this), to);
if (allowance < amount) {
token.forceApprove(to, _MAX_APPROVE);
}
}
/// @dev Returns `account` ERC20 `token` balance.
function pAmountFixer(IERC20 token, uint256 amount) internal view returns (uint256 fixedAmount) {
address account = address(this);
if (amount <= 0) {
if (isETH(token)) {
fixedAmount = account.balance;
} else {
fixedAmount = token.balanceOf(account);
}
}
else {
fixedAmount = amount;
}
}
/// @dev `token` transfer `to` `amount`.
/// Note that this function does nothing in case of zero amount.
function pTransfer(
IERC20 token,
address payable to,
uint256 amount
) internal {
if (amount > 0) {
if (isETH(token)) {
if (address(this).balance < amount) revert InsufficientBalance();
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = to.call{value: amount, gas: _RAW_CALL_GAS_LIMIT}("");
if (!success) revert ETHTransferFailed();
} else {
token.safeTransfer(to, amount);
}
}
}
function pTransferFrom(
IERC20 token,
address payable from,
address to,
uint256 amount
) internal {
if (amount > 0) {
if (isETH(token)) {
if (msg.value < amount) revert NotEnoughValue();
if (from != msg.sender) revert FromIsNotSender();
if (to != address(this)) revert ToIsNotThis();
if (msg.value > amount) {
// Return remainder if exist
unchecked {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = from.call{value: msg.value - amount, gas: _RAW_CALL_GAS_LIMIT}("");
if (!success) revert ETHTransferFailed();
}
}
} else {
token.safeTransferFrom(from, to, amount);
}
}
}
/// @dev `token` transfer `from` `to` `amount`.
/// Note that this function does nothing in case of zero amount.
function execute(
IERC20 token,
address payable from,
address to,
uint256 amount,
bytes memory _data
) internal {
if (amount > 0) {
bool srcETH = isETH(token);
if (!srcETH) {
token.safeTransferFrom(from, to, amount);
}
(bool success, bytes memory result) = excessivelySafeCall(
to,
srcETH ? amount : 0,
abi.encodeWithSelector(
ISwapManager.swap.selector,
_data
)
);
if (!success) {
revert(RevertReasonParser.parse(result, "Error: "));
}
}
}
function excessivelySafeCall(
address _target,
uint256 _value,
bytes memory _calldata
) internal returns (bool _success, bytes memory _returnData) {
// set up for assembly call
uint256 _toCopy;
//bool _success;
// dispatch message to recipient
// by assembly calling "handle" function
// we call via assembly to avoid memcopying a very large returndata
// returned by a malicious contract
assembly {
_success := call(
gas(), // gas
_target, // recipient
_value, // ether value
add(_calldata, 0x20), // inloc
mload(_calldata), // inlen
0, // outloc
0 // outlen
)
// limit our copy to 256 bytes
_toCopy := returndatasize()
// Store the length of the copied bytes
mstore(_returnData, _toCopy)
// copy the bytes from returndata[0:_toCopy]
returndatacopy(add(_returnData, 0x20), 0, _toCopy)
}
return (_success, _returnData);
}
function pDeposit(uint256 amount) internal {
WETH.safeDeposit(amount);
}
function pWithdraw(uint256 amount) internal {
WETH.safeWithdraw(amount);
}
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/EthReceiver.sol
pragma solidity ^0.8.0;
abstract contract EthReceiver {
error EthDepositRejected();
receive() external payable {
//_receive();
}
function _receive() internal virtual {
// solhint-disable-next-line avoid-tx-origin
if (msg.sender == tx.origin) revert EthDepositRejected();
}
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/errors/Errors.sol
pragma solidity ^0.8.18;
contract Errors {
error ZeroData();
error ZeroAddress();
error ZeroSrcAmount();
error ZeroDestAmount();
error ReturnAmountIsNotEnough();
error ReturnAmountIsNotEqual();
error InvalidMsgValue();
error HasBeenStopped();
}
// File: verified-sources/0x6BF228eb7F8ad948d37deD07E595EfddfaAF88A6/sources/deployed-version-final/PiteasRouter.sol
pragma solidity ^0.8.18;
contract PiteasRouter is Ownable, EthReceiver {
using PitERC20 for IERC20;
using SafeMath for uint256;
bool private status = true;
address private swapManager;
struct Detail {
IERC20 srcToken;
IERC20 destToken;
address payable destAccount;
uint256 srcAmount;
uint256 destMinAmount;
}
event ChangedStatus(bool indexed status);
event ChangedSwapManager(address indexed manager);
event SwapEvent(
address swapManager,
IERC20 srcToken,
IERC20 destToken,
address indexed sender,
address destReceiver,
uint256 srcAmount,
uint256 destAmount
);
modifier checkStatus() {
if (status == false) {
revert Errors.HasBeenStopped();
}
_;
}
function swap(Detail memory detail, bytes calldata data) public payable checkStatus returns (uint256 returnAmount) {
if (detail.srcAmount == 0) revert Errors.ZeroSrcAmount();
if (detail.destMinAmount == 0) revert Errors.ZeroDestAmount();
if (data.length == 0) revert Errors.ZeroData();
IERC20 srcToken = detail.srcToken;
IERC20 destToken = detail.destToken;
bool srcETH = srcToken.isETH();
if (msg.value < (srcETH ? detail.srcAmount : 0)) revert Errors.InvalidMsgValue();
uint256 beginBalance = destToken.pBalanceOf(address(this));
srcToken.execute(payable(msg.sender), swapManager, detail.srcAmount, data);
returnAmount = destToken.pBalanceOf(address(this)).sub(beginBalance,"Error");
address payable destReceiver = (detail.destAccount == address(0)) ? payable(msg.sender) : detail.destAccount;
if (returnAmount >= detail.destMinAmount) {
destToken.pTransfer(destReceiver, returnAmount);
}else{
revert Errors.ReturnAmountIsNotEnough();
}
emit SwapEvent(address(swapManager), srcToken, destToken, msg.sender, destReceiver, detail.srcAmount, returnAmount);
}
function changeStatus(bool _status) external onlyOwner {
status = _status;
emit ChangedStatus(_status);
}
function changeSwapManager(address _manager) external onlyOwner {
if (_manager == address(0)) {
revert Errors.ZeroAddress();
}
swapManager = _manager;
emit ChangedSwapManager(_manager);
}
function withdrawFunds(IERC20 token, uint256 amount) external onlyOwner {
token.pTransfer(payable(msg.sender), amount);
}
}
Contract ABI
[{"type":"error","name":"ETHTransferFailed","inputs":[]},{"type":"error","name":"EthDepositRejected","inputs":[]},{"type":"error","name":"HasBeenStopped","inputs":[]},{"type":"error","name":"InsufficientBalance","inputs":[]},{"type":"error","name":"InvalidMsgValue","inputs":[]},{"type":"error","name":"ReturnAmountIsNotEnough","inputs":[]},{"type":"error","name":"SafeTransferFailed","inputs":[]},{"type":"error","name":"SafeTransferFromFailed","inputs":[]},{"type":"error","name":"ZeroAddress","inputs":[]},{"type":"error","name":"ZeroData","inputs":[]},{"type":"error","name":"ZeroDestAmount","inputs":[]},{"type":"error","name":"ZeroSrcAmount","inputs":[]},{"type":"event","name":"ChangedStatus","inputs":[{"type":"bool","name":"status","internalType":"bool","indexed":true}],"anonymous":false},{"type":"event","name":"ChangedSwapManager","inputs":[{"type":"address","name":"manager","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SwapEvent","inputs":[{"type":"address","name":"swapManager","internalType":"address","indexed":false},{"type":"address","name":"srcToken","internalType":"contract IERC20","indexed":false},{"type":"address","name":"destToken","internalType":"contract IERC20","indexed":false},{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"address","name":"destReceiver","internalType":"address","indexed":false},{"type":"uint256","name":"srcAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"destAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeStatus","inputs":[{"type":"bool","name":"_status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeSwapManager","inputs":[{"type":"address","name":"_manager","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"returnAmount","internalType":"uint256"}],"name":"swap","inputs":[{"type":"tuple","name":"detail","internalType":"struct PiteasRouter.Detail","components":[{"type":"address","name":"srcToken","internalType":"contract IERC20"},{"type":"address","name":"destToken","internalType":"contract IERC20"},{"type":"address","name":"destAccount","internalType":"address payable"},{"type":"uint256","name":"srcAmount","internalType":"uint256"},{"type":"uint256","name":"destMinAmount","internalType":"uint256"}]},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFunds","inputs":[{"type":"address","name":"token","internalType":"contract IERC20"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x60806040526001600060146101000a81548160ff02191690831515021790555034801561002b57600080fd5b5061004861003d61004d60201b60201c565b61005560201b60201c565b610119565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611d1a806101286000396000f3fe6080604052600436106100745760003560e01c80638da5cb5b1161004e5780638da5cb5b146100f05780639b3de49b1461011b578063c107532914610144578063f2fde38b1461016d5761007b565b8063065a79ad14610080578063715018a6146100a95780638218b58f146100c05761007b565b3661007b57005b600080fd5b34801561008c57600080fd5b506100a760048036038101906100a29190611372565b610196565b005b3480156100b557600080fd5b506100be61028b565b005b6100da60048036038101906100d591906115d3565b61029f565b6040516100e79190611642565b60405180910390f35b3480156100fc57600080fd5b5061010561069e565b604051610112919061166c565b60405180910390f35b34801561012757600080fd5b50610142600480360381019061013d91906116bf565b6106c7565b005b34801561015057600080fd5b5061016b600480360381019061016691906116ec565b61071b565b005b34801561017957600080fd5b50610194600480360381019061018f9190611372565b610752565b005b61019e6107d5565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610204576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f9749619bcf6d1b4c60f22db410005b9501d48c42a749c4564585466fff64f34d60405160405180910390a250565b6102936107d5565b61029d6000610853565b565b6000801515600060149054906101000a900460ff161515036102ed576040517f4e43cc4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084606001510361032b576040517fe5ae137000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000846080015103610369576040517f175b9e6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083839050036103a6576040517fc922446b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008460000151905060008560200151905060006103d98373ffffffffffffffffffffffffffffffffffffffff16610917565b9050806103e75760006103ed565b86606001515b341015610426576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610451308473ffffffffffffffffffffffffffffffffffffffff1661099990919063ffffffff16565b90506104ec33600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a606001518a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508873ffffffffffffffffffffffffffffffffffffffff16610a4b90949392919063ffffffff16565b61055e816040518060400160405280600581526020017f4572726f7200000000000000000000000000000000000000000000000000000081525061054f308773ffffffffffffffffffffffffffffffffffffffff1661099990919063ffffffff16565b610bb39092919063ffffffff16565b945060008073ffffffffffffffffffffffffffffffffffffffff16896040015173ffffffffffffffffffffffffffffffffffffffff16146105a35788604001516105a5565b335b9050886080015186106105e2576105dd81878673ffffffffffffffffffffffffffffffffffffffff16610c089092919063ffffffff16565b610614565b6040517ff32bec2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167faee0813f6f9fe55be44dd4c96b16d8b03085d3eb669fe21b51be0f4dc391622c600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168787858e606001518c60405161068a969594939291906117ac565b60405180910390a250505050509392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6106cf6107d5565b80600060146101000a81548160ff0219169083151502179055508015157f030d1ae93bd878ad07bee72827dba91738e3b03307b607a679916911ea552b9960405160405180910390a250565b6107236107d5565b61074e33828473ffffffffffffffffffffffffffffffffffffffff16610c089092919063ffffffff16565b5050565b61075a6107d5565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036107c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107c090611890565b60405180910390fd5b6107d281610853565b50565b6107dd610d39565b73ffffffffffffffffffffffffffffffffffffffff166107fb61069e565b73ffffffffffffffffffffffffffffffffffffffff1614610851576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610848906118fc565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610992575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b60006109a483610917565b156109c8578173ffffffffffffffffffffffffffffffffffffffff16319050610a45565b8273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401610a01919061166c565b602060405180830381865afa158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a429190611931565b90505b92915050565b6000821115610bac576000610a5f86610917565b905080610a9457610a938585858973ffffffffffffffffffffffffffffffffffffffff16610d41909392919063ffffffff16565b5b600080610b248684610aa7576000610aa9565b865b63627dd56a60e01b87604051602401610ac291906119dd565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610de0565b9150915081610ba857610b6c816040518060400160405280600781526020017f4572726f723a2000000000000000000000000000000000000000000000000000815250610e0c565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9f9190611a43565b60405180910390fd5b5050505b5050505050565b6000838311158290610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf29190611a43565b60405180910390fd5b5082840390509392505050565b6000811115610d3457610c1a83610917565b15610d075780471015610c59576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168261138890604051610c8390611a96565b600060405180830381858888f193505050503d8060008114610cc1576040519150601f19603f3d011682016040523d82523d6000602084013e610cc6565b606091505b5050905080610d01576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610d33565b610d3282828573ffffffffffffffffffffffffffffffffffffffff16610fc79092919063ffffffff16565b5b5b505050565b600033905090565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af191508115610da0573d60008114610d9657600160005114601f3d11169250610d9e565b6000883b1192505b505b5080610dd8576040517ff405907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b600060606000806000855160208701888a5af192503d9050808252806000602084013e50935093915050565b606060006004845110610e2157602084015190505b7f08c379a0afcc32b1a39302f7cb8073359698411ab5fd6e3edb2c02c0b5fba8aa7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148015610e9057506044845110155b15610ee357606060448501905080516044610eab9190611ada565b855110610edd578381604051602001610ec5929190611b96565b60405160208183030381529060405292505050610fc1565b50610f93565b7f4e487b71539e0164c9d29506cc725e49342bcac15e0927282bf30fedfe1c72687bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148015610f51575060248451145b15610f925760006024850151905083610f6982611015565b604051602001610f7a929190611bfe565b60405160208183030381529060405292505050610fc1565b5b82610f9d85611046565b604051602001610fae929190611c66565b6040516020818303038152906040529150505b92915050565b610fda8363a9059cbb60e01b84846112aa565b611010576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b606061103f8260405160200161102b9190611cc9565b604051602081830303815290604052611046565b9050919050565b6060611235565b600077ffffffffffffffff00000000000000000000000000000000821660401c7fffffffffffffffff00000000000000000000000000000000000000000000000083161790507bffffffff000000000000000000000000ffffffff0000000000000000811660201c7fffffffff000000000000000000000000ffffffff00000000000000000000000082161790507dffff000000000000ffff000000000000ffff000000000000ffff00000000811660101c7fffff000000000000ffff000000000000ffff000000000000ffff00000000000082161790507eff000000ff000000ff000000ff000000ff000000ff000000ff000000ff0000811660081c7fff000000ff000000ff000000ff000000ff000000ff000000ff000000ff00000082161790507f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00811660081c7ff000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000821660041c17905060077f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f0606060606060606060606060606060606060606060606060606060606060606830160041c1602817f303030303030303030303030303030303030303030303030303030303030303001019050919050565b604051905081518060011b602283018181016040526130786002850152600282018452602085018381015b808210156112a05781516112738161104d565b8085526020850194506112888260801b61104d565b90508085526020850194505050602082019150611260565b5050505050919050565b60006040518481528360048201528260248201526020600060448360008a5af1915081156112f7573d600081146112ed57600160005114601f3d111692506112f5565b6000873b1192505b505b50949350505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061133f82611314565b9050919050565b61134f81611334565b811461135a57600080fd5b50565b60008135905061136c81611346565b92915050565b6000602082840312156113885761138761130a565b5b60006113968482850161135d565b91505092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6113ed826113a4565b810181811067ffffffffffffffff8211171561140c5761140b6113b5565b5b80604052505050565b600061141f611300565b905061142b82826113e4565b919050565b600061143b82611334565b9050919050565b61144b81611430565b811461145657600080fd5b50565b60008135905061146881611442565b92915050565b600061147982611314565b9050919050565b6114898161146e565b811461149457600080fd5b50565b6000813590506114a681611480565b92915050565b6000819050919050565b6114bf816114ac565b81146114ca57600080fd5b50565b6000813590506114dc816114b6565b92915050565b600060a082840312156114f8576114f761139f565b5b61150260a0611415565b9050600061151284828501611459565b600083015250602061152684828501611459565b602083015250604061153a84828501611497565b604083015250606061154e848285016114cd565b6060830152506080611562848285016114cd565b60808301525092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126115935761159261156e565b5b8235905067ffffffffffffffff8111156115b0576115af611573565b5b6020830191508360018202830111156115cc576115cb611578565b5b9250929050565b600080600060c084860312156115ec576115eb61130a565b5b60006115fa868287016114e2565b93505060a084013567ffffffffffffffff81111561161b5761161a61130f565b5b6116278682870161157d565b92509250509250925092565b61163c816114ac565b82525050565b60006020820190506116576000830184611633565b92915050565b61166681611334565b82525050565b6000602082019050611681600083018461165d565b92915050565b60008115159050919050565b61169c81611687565b81146116a757600080fd5b50565b6000813590506116b981611693565b92915050565b6000602082840312156116d5576116d461130a565b5b60006116e3848285016116aa565b91505092915050565b600080604083850312156117035761170261130a565b5b600061171185828601611459565b9250506020611722858286016114cd565b9150509250929050565b6000819050919050565b600061175161174c61174784611314565b61172c565b611314565b9050919050565b600061176382611736565b9050919050565b600061177582611758565b9050919050565b6117858161176a565b82525050565b600061179682611758565b9050919050565b6117a68161178b565b82525050565b600060c0820190506117c1600083018961165d565b6117ce602083018861177c565b6117db604083018761177c565b6117e8606083018661179d565b6117f56080830185611633565b61180260a0830184611633565b979650505050505050565b600082825260208201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061187a60268361180d565b91506118858261181e565b604082019050919050565b600060208201905081810360008301526118a98161186d565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006118e660208361180d565b91506118f1826118b0565b602082019050919050565b60006020820190508181036000830152611915816118d9565b9050919050565b60008151905061192b816114b6565b92915050565b6000602082840312156119475761194661130a565b5b60006119558482850161191c565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561199857808201518184015260208101905061197d565b60008484015250505050565b60006119af8261195e565b6119b98185611969565b93506119c981856020860161197a565b6119d2816113a4565b840191505092915050565b600060208201905081810360008301526119f781846119a4565b905092915050565b600081519050919050565b6000611a15826119ff565b611a1f818561180d565b9350611a2f81856020860161197a565b611a38816113a4565b840191505092915050565b60006020820190508181036000830152611a5d8184611a0a565b905092915050565b600081905092915050565b50565b6000611a80600083611a65565b9150611a8b82611a70565b600082019050919050565b6000611aa182611a73565b9150819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611ae5826114ac565b9150611af0836114ac565b9250828201905080821115611b0857611b07611aab565b5b92915050565b600081905092915050565b6000611b24826119ff565b611b2e8185611b0e565b9350611b3e81856020860161197a565b80840191505092915050565b7f4572726f72280000000000000000000000000000000000000000000000000000815250565b7f2900000000000000000000000000000000000000000000000000000000000000815250565b6000611ba28285611b19565b9150611bad82611b4a565b600682019150611bbd8284611b19565b9150611bc882611b70565b6001820191508190509392505050565b7f50616e6963280000000000000000000000000000000000000000000000000000815250565b6000611c0a8285611b19565b9150611c1582611bd8565b600682019150611c258284611b19565b9150611c3082611b70565b6001820191508190509392505050565b7f556e6b6e6f776e28000000000000000000000000000000000000000000000000815250565b6000611c728285611b19565b9150611c7d82611c40565b600882019150611c8d8284611b19565b9150611c9882611b70565b6001820191508190509392505050565b6000819050919050565b611cc3611cbe826114ac565b611ca8565b82525050565b6000611cd58284611cb2565b6020820191508190509291505056fea264697066735822122028d1f65241f6c7f042eb2e5f9f950d2294ceb5fafb20f3229d7ec9561ad3de2164736f6c63430008120033
Deployed ByteCode
0x6080604052600436106100745760003560e01c80638da5cb5b1161004e5780638da5cb5b146100f05780639b3de49b1461011b578063c107532914610144578063f2fde38b1461016d5761007b565b8063065a79ad14610080578063715018a6146100a95780638218b58f146100c05761007b565b3661007b57005b600080fd5b34801561008c57600080fd5b506100a760048036038101906100a29190611372565b610196565b005b3480156100b557600080fd5b506100be61028b565b005b6100da60048036038101906100d591906115d3565b61029f565b6040516100e79190611642565b60405180910390f35b3480156100fc57600080fd5b5061010561069e565b604051610112919061166c565b60405180910390f35b34801561012757600080fd5b50610142600480360381019061013d91906116bf565b6106c7565b005b34801561015057600080fd5b5061016b600480360381019061016691906116ec565b61071b565b005b34801561017957600080fd5b50610194600480360381019061018f9190611372565b610752565b005b61019e6107d5565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610204576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f9749619bcf6d1b4c60f22db410005b9501d48c42a749c4564585466fff64f34d60405160405180910390a250565b6102936107d5565b61029d6000610853565b565b6000801515600060149054906101000a900460ff161515036102ed576040517f4e43cc4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084606001510361032b576040517fe5ae137000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000846080015103610369576040517f175b9e6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083839050036103a6576040517fc922446b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008460000151905060008560200151905060006103d98373ffffffffffffffffffffffffffffffffffffffff16610917565b9050806103e75760006103ed565b86606001515b341015610426576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610451308473ffffffffffffffffffffffffffffffffffffffff1661099990919063ffffffff16565b90506104ec33600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a606001518a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508873ffffffffffffffffffffffffffffffffffffffff16610a4b90949392919063ffffffff16565b61055e816040518060400160405280600581526020017f4572726f7200000000000000000000000000000000000000000000000000000081525061054f308773ffffffffffffffffffffffffffffffffffffffff1661099990919063ffffffff16565b610bb39092919063ffffffff16565b945060008073ffffffffffffffffffffffffffffffffffffffff16896040015173ffffffffffffffffffffffffffffffffffffffff16146105a35788604001516105a5565b335b9050886080015186106105e2576105dd81878673ffffffffffffffffffffffffffffffffffffffff16610c089092919063ffffffff16565b610614565b6040517ff32bec2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167faee0813f6f9fe55be44dd4c96b16d8b03085d3eb669fe21b51be0f4dc391622c600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168787858e606001518c60405161068a969594939291906117ac565b60405180910390a250505050509392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6106cf6107d5565b80600060146101000a81548160ff0219169083151502179055508015157f030d1ae93bd878ad07bee72827dba91738e3b03307b607a679916911ea552b9960405160405180910390a250565b6107236107d5565b61074e33828473ffffffffffffffffffffffffffffffffffffffff16610c089092919063ffffffff16565b5050565b61075a6107d5565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036107c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107c090611890565b60405180910390fd5b6107d281610853565b50565b6107dd610d39565b73ffffffffffffffffffffffffffffffffffffffff166107fb61069e565b73ffffffffffffffffffffffffffffffffffffffff1614610851576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610848906118fc565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610992575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b60006109a483610917565b156109c8578173ffffffffffffffffffffffffffffffffffffffff16319050610a45565b8273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401610a01919061166c565b602060405180830381865afa158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a429190611931565b90505b92915050565b6000821115610bac576000610a5f86610917565b905080610a9457610a938585858973ffffffffffffffffffffffffffffffffffffffff16610d41909392919063ffffffff16565b5b600080610b248684610aa7576000610aa9565b865b63627dd56a60e01b87604051602401610ac291906119dd565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610de0565b9150915081610ba857610b6c816040518060400160405280600781526020017f4572726f723a2000000000000000000000000000000000000000000000000000815250610e0c565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9f9190611a43565b60405180910390fd5b5050505b5050505050565b6000838311158290610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf29190611a43565b60405180910390fd5b5082840390509392505050565b6000811115610d3457610c1a83610917565b15610d075780471015610c59576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168261138890604051610c8390611a96565b600060405180830381858888f193505050503d8060008114610cc1576040519150601f19603f3d011682016040523d82523d6000602084013e610cc6565b606091505b5050905080610d01576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610d33565b610d3282828573ffffffffffffffffffffffffffffffffffffffff16610fc79092919063ffffffff16565b5b5b505050565b600033905090565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af191508115610da0573d60008114610d9657600160005114601f3d11169250610d9e565b6000883b1192505b505b5080610dd8576040517ff405907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b600060606000806000855160208701888a5af192503d9050808252806000602084013e50935093915050565b606060006004845110610e2157602084015190505b7f08c379a0afcc32b1a39302f7cb8073359698411ab5fd6e3edb2c02c0b5fba8aa7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148015610e9057506044845110155b15610ee357606060448501905080516044610eab9190611ada565b855110610edd578381604051602001610ec5929190611b96565b60405160208183030381529060405292505050610fc1565b50610f93565b7f4e487b71539e0164c9d29506cc725e49342bcac15e0927282bf30fedfe1c72687bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148015610f51575060248451145b15610f925760006024850151905083610f6982611015565b604051602001610f7a929190611bfe565b60405160208183030381529060405292505050610fc1565b5b82610f9d85611046565b604051602001610fae929190611c66565b6040516020818303038152906040529150505b92915050565b610fda8363a9059cbb60e01b84846112aa565b611010576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b606061103f8260405160200161102b9190611cc9565b604051602081830303815290604052611046565b9050919050565b6060611235565b600077ffffffffffffffff00000000000000000000000000000000821660401c7fffffffffffffffff00000000000000000000000000000000000000000000000083161790507bffffffff000000000000000000000000ffffffff0000000000000000811660201c7fffffffff000000000000000000000000ffffffff00000000000000000000000082161790507dffff000000000000ffff000000000000ffff000000000000ffff00000000811660101c7fffff000000000000ffff000000000000ffff000000000000ffff00000000000082161790507eff000000ff000000ff000000ff000000ff000000ff000000ff000000ff0000811660081c7fff000000ff000000ff000000ff000000ff000000ff000000ff000000ff00000082161790507f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00811660081c7ff000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000821660041c17905060077f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f0606060606060606060606060606060606060606060606060606060606060606830160041c1602817f303030303030303030303030303030303030303030303030303030303030303001019050919050565b604051905081518060011b602283018181016040526130786002850152600282018452602085018381015b808210156112a05781516112738161104d565b8085526020850194506112888260801b61104d565b90508085526020850194505050602082019150611260565b5050505050919050565b60006040518481528360048201528260248201526020600060448360008a5af1915081156112f7573d600081146112ed57600160005114601f3d111692506112f5565b6000873b1192505b505b50949350505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061133f82611314565b9050919050565b61134f81611334565b811461135a57600080fd5b50565b60008135905061136c81611346565b92915050565b6000602082840312156113885761138761130a565b5b60006113968482850161135d565b91505092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6113ed826113a4565b810181811067ffffffffffffffff8211171561140c5761140b6113b5565b5b80604052505050565b600061141f611300565b905061142b82826113e4565b919050565b600061143b82611334565b9050919050565b61144b81611430565b811461145657600080fd5b50565b60008135905061146881611442565b92915050565b600061147982611314565b9050919050565b6114898161146e565b811461149457600080fd5b50565b6000813590506114a681611480565b92915050565b6000819050919050565b6114bf816114ac565b81146114ca57600080fd5b50565b6000813590506114dc816114b6565b92915050565b600060a082840312156114f8576114f761139f565b5b61150260a0611415565b9050600061151284828501611459565b600083015250602061152684828501611459565b602083015250604061153a84828501611497565b604083015250606061154e848285016114cd565b6060830152506080611562848285016114cd565b60808301525092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126115935761159261156e565b5b8235905067ffffffffffffffff8111156115b0576115af611573565b5b6020830191508360018202830111156115cc576115cb611578565b5b9250929050565b600080600060c084860312156115ec576115eb61130a565b5b60006115fa868287016114e2565b93505060a084013567ffffffffffffffff81111561161b5761161a61130f565b5b6116278682870161157d565b92509250509250925092565b61163c816114ac565b82525050565b60006020820190506116576000830184611633565b92915050565b61166681611334565b82525050565b6000602082019050611681600083018461165d565b92915050565b60008115159050919050565b61169c81611687565b81146116a757600080fd5b50565b6000813590506116b981611693565b92915050565b6000602082840312156116d5576116d461130a565b5b60006116e3848285016116aa565b91505092915050565b600080604083850312156117035761170261130a565b5b600061171185828601611459565b9250506020611722858286016114cd565b9150509250929050565b6000819050919050565b600061175161174c61174784611314565b61172c565b611314565b9050919050565b600061176382611736565b9050919050565b600061177582611758565b9050919050565b6117858161176a565b82525050565b600061179682611758565b9050919050565b6117a68161178b565b82525050565b600060c0820190506117c1600083018961165d565b6117ce602083018861177c565b6117db604083018761177c565b6117e8606083018661179d565b6117f56080830185611633565b61180260a0830184611633565b979650505050505050565b600082825260208201905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061187a60268361180d565b91506118858261181e565b604082019050919050565b600060208201905081810360008301526118a98161186d565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006118e660208361180d565b91506118f1826118b0565b602082019050919050565b60006020820190508181036000830152611915816118d9565b9050919050565b60008151905061192b816114b6565b92915050565b6000602082840312156119475761194661130a565b5b60006119558482850161191c565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561199857808201518184015260208101905061197d565b60008484015250505050565b60006119af8261195e565b6119b98185611969565b93506119c981856020860161197a565b6119d2816113a4565b840191505092915050565b600060208201905081810360008301526119f781846119a4565b905092915050565b600081519050919050565b6000611a15826119ff565b611a1f818561180d565b9350611a2f81856020860161197a565b611a38816113a4565b840191505092915050565b60006020820190508181036000830152611a5d8184611a0a565b905092915050565b600081905092915050565b50565b6000611a80600083611a65565b9150611a8b82611a70565b600082019050919050565b6000611aa182611a73565b9150819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611ae5826114ac565b9150611af0836114ac565b9250828201905080821115611b0857611b07611aab565b5b92915050565b600081905092915050565b6000611b24826119ff565b611b2e8185611b0e565b9350611b3e81856020860161197a565b80840191505092915050565b7f4572726f72280000000000000000000000000000000000000000000000000000815250565b7f2900000000000000000000000000000000000000000000000000000000000000815250565b6000611ba28285611b19565b9150611bad82611b4a565b600682019150611bbd8284611b19565b9150611bc882611b70565b6001820191508190509392505050565b7f50616e6963280000000000000000000000000000000000000000000000000000815250565b6000611c0a8285611b19565b9150611c1582611bd8565b600682019150611c258284611b19565b9150611c3082611b70565b6001820191508190509392505050565b7f556e6b6e6f776e28000000000000000000000000000000000000000000000000815250565b6000611c728285611b19565b9150611c7d82611c40565b600882019150611c8d8284611b19565b9150611c9882611b70565b6001820191508190509392505050565b6000819050919050565b611cc3611cbe826114ac565b611ca8565b82525050565b6000611cd58284611cb2565b6020820191508190509291505056fea264697066735822122028d1f65241f6c7f042eb2e5f9f950d2294ceb5fafb20f3229d7ec9561ad3de2164736f6c63430008120033