Source Code
Latest 25 from a total of 307 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Zap | 24550508 | 5 hrs ago | IN | 0 ETH | 0.00045254 | ||||
| Zap | 24550125 | 6 hrs ago | IN | 0 ETH | 0.00011765 | ||||
| Zap | 24550087 | 6 hrs ago | IN | 0 ETH | 0.00016238 | ||||
| Zap | 24548196 | 13 hrs ago | IN | 0 ETH | 0.00017914 | ||||
| Zap | 24543951 | 27 hrs ago | IN | 0 ETH | 0.00005197 | ||||
| Zap | 24538265 | 46 hrs ago | IN | 0 ETH | 0.00006009 | ||||
| Zap | 24536891 | 2 days ago | IN | 0 ETH | 0.00001037 | ||||
| Zap | 24536460 | 2 days ago | IN | 0 ETH | 0.00024682 | ||||
| Zap | 24527012 | 3 days ago | IN | 0 ETH | 0.00138277 | ||||
| Zap | 24522236 | 4 days ago | IN | 0 ETH | 0.0000561 | ||||
| Zap | 24513902 | 5 days ago | IN | 0 ETH | 0.00008879 | ||||
| Zap | 24513891 | 5 days ago | IN | 0 ETH | 0.00009732 | ||||
| Zap | 24507733 | 6 days ago | IN | 0 ETH | 0.00776358 | ||||
| Zap | 24505041 | 6 days ago | IN | 0 ETH | 0.00317132 | ||||
| Zap | 24502157 | 6 days ago | IN | 0.00360022 ETH | 0.00007436 | ||||
| Zap | 24499165 | 7 days ago | IN | 0 ETH | 0.00104673 | ||||
| Zap | 24494067 | 8 days ago | IN | 0 ETH | 0.00010728 | ||||
| Zap | 24493763 | 8 days ago | IN | 0 ETH | 0.00003188 | ||||
| Zap | 24493467 | 8 days ago | IN | 0 ETH | 0.00003099 | ||||
| Zap | 24492031 | 8 days ago | IN | 0 ETH | 0.00027966 | ||||
| Zap | 24491993 | 8 days ago | IN | 0 ETH | 0.0001787 | ||||
| Zap | 24490459 | 8 days ago | IN | 0 ETH | 0.0000261 | ||||
| Zap | 24489620 | 8 days ago | IN | 0 ETH | 0.00009467 | ||||
| Zap | 24477530 | 10 days ago | IN | 0 ETH | 0.00008104 | ||||
| Zap | 24471916 | 11 days ago | IN | 0 ETH | 0.00009028 |
Latest 20 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0xf012a2b6 | 24502157 | 6 days ago | 0.00360022 ETH | ||||
| 0xf012a2b6 | 24320714 | 32 days ago | 0.00150721 ETH | ||||
| 0xf012a2b6 | 24285216 | 37 days ago | 0.0011 ETH | ||||
| 0xf012a2b6 | 24285193 | 37 days ago | 0.0011 ETH | ||||
| 0xf012a2b6 | 24263798 | 40 days ago | 0.00425704 ETH | ||||
| 0xf012a2b6 | 24240298 | 43 days ago | 0.0527175 ETH | ||||
| 0xf012a2b6 | 24226705 | 45 days ago | 0.09 ETH | ||||
| 0xf012a2b6 | 24211834 | 47 days ago | 0.026 ETH | ||||
| 0xf012a2b6 | 24192038 | 50 days ago | 0.00227047 ETH | ||||
| 0xf012a2b6 | 24192033 | 50 days ago | 0.00227047 ETH | ||||
| 0xf012a2b6 | 24191704 | 50 days ago | 0.00013614 ETH | ||||
| 0xf012a2b6 | 24191262 | 50 days ago | 0.00049994 ETH | ||||
| 0xf012a2b6 | 24154313 | 55 days ago | 0.14 ETH | ||||
| 0xf012a2b6 | 24128526 | 59 days ago | 0.00461465 ETH | ||||
| 0xf012a2b6 | 24127795 | 59 days ago | 0.0015 ETH | ||||
| 0xf012a2b6 | 24074919 | 66 days ago | 1 ETH | ||||
| 0xf012a2b6 | 24074892 | 66 days ago | 1 ETH | ||||
| 0xf012a2b6 | 24056202 | 69 days ago | 0.015 ETH | ||||
| 0xf012a2b6 | 23955017 | 83 days ago | 0.2 ETH | ||||
| 0xf012a2b6 | 23949129 | 84 days ago | 0.00008836 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
KSZapRouterPositionPermit
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {IKSZapRouterPositionPermit} from 'contracts/interfaces/IKSZapRouterPositionPermit.sol';
import {IZapDexEnum} from 'contracts/interfaces/zap/common/IZapDexEnum.sol';
import {IKSZapExecutorActions} from 'contracts/interfaces/zap/executors/IKSZapExecutorActions.sol';
import {
IKSZapValidatorActions
} from 'contracts/interfaces/zap/validators/IKSZapValidatorActions.sol';
import {KSRescueV2} from 'ks-growth-utils-sc/contracts/KSRescueV2.sol';
import {ReentrancyGuard} from 'openzeppelin/contracts/security/ReentrancyGuard.sol';
import {IERC1155} from 'openzeppelin/contracts/token/ERC1155/IERC1155.sol';
import {IERC721} from 'openzeppelin/contracts/token/ERC721/IERC721.sol';
import {IAllowanceTransfer} from 'ks-common-sc/src/interfaces/IAllowanceTransfer.sol';
import {PermitHelper} from 'ks-common-sc/src/libraries/token/PermitHelper.sol';
import {TokenHelper} from 'ks-common-sc/src/libraries/token/TokenHelper.sol';
/// @notice Main KyberSwap Zap Router to allow users zapping into any dexes
/// It uses Validator to validate the zap result with flexibility, to enable adding more dexes
contract KSZapRouterPositionPermit is
IKSZapRouterPositionPermit,
IZapDexEnum,
KSRescueV2,
ReentrancyGuard
{
using TokenHelper for address;
using PermitHelper for address;
address private constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
IAllowanceTransfer immutable permit2;
mapping(address => bool) public whitelistedExecutor;
mapping(address => bool) public whitelistedValidator;
modifier checkDeadline(uint32 _deadline) {
require(block.timestamp <= _deadline, 'ZapRouter: expired');
_;
}
constructor(address _permit2) {
permit2 = IAllowanceTransfer(_permit2);
}
/// @notice Whitelist executors by the owner, can grant or revoke
function whitelistExecutors(address[] calldata _executors, bool _grantOrRevoke)
external
onlyOwner
{
for (uint256 i = 0; i < _executors.length; i++) {
whitelistedExecutor[_executors[i]] = _grantOrRevoke;
emit ExecutorWhitelisted(_executors[i], _grantOrRevoke);
}
}
/// @notice Whitelist validators by the owner, can grant or revoke
function whitelistValidators(address[] calldata _validators, bool _grantOrRevoke)
external
onlyOwner
{
for (uint256 i = 0; i < _validators.length; i++) {
whitelistedValidator[_validators[i]] = _grantOrRevoke;
emit ValidatorWhitelisted(_validators[i], _grantOrRevoke);
}
}
/// @inheritdoc IKSZapRouterPositionPermit
function zap(ZapDescription calldata _desc, ZapExecutionData calldata _exe)
external
payable
override
whenNotPaused
nonReentrant
checkDeadline(_exe.deadline)
returns (bytes memory zapResults)
{
require(whitelistedExecutor[_exe.executor], 'ZapRouter: non whitelisted executor');
// handle src token collection
_handleCollectERC20Tokens(_desc.erc20SrcInfo, _exe.executor);
_handleCollectERC721Tokens(_desc.erc721SrcInfo, _exe.executor);
// prepare validation data
bytes memory initialData;
if (_exe.validator != address(0)) {
require(whitelistedValidator[_exe.validator], 'ZapRouter: non whitelisted validator');
initialData = IKSZapValidatorActions(_exe.validator).prepareValidationData(0, _desc.zapInfo);
}
// calling executor to execute the zap logic
zapResults =
IKSZapExecutorActions(_exe.executor).executeZap{value: msg.value}(_exe.executorData);
// validate data after zapping if needed
if (_exe.validator != address(0)) {
bool isValid = IKSZapValidatorActions(_exe.validator)
.validateData(0, _desc.extraData, initialData, zapResults);
require(isValid, 'ZapRouter: validation failed');
}
emit ZapExecuted(
_exe.validator, _exe.executor, _desc.zapInfo, _desc.extraData, initialData, zapResults
);
emit ClientData(_exe.clientData);
}
/// @notice Handle collecting ERC20 tokens and transfer to executor
function _handleCollectERC20Tokens(ERC20SrcInfo calldata src, address _executor) internal {
require(
src.tokens.length == src.amounts.length && src.tokens.length == src.permitData.length,
'ZapRouter: invalid data'
);
uint256 msgValue = msg.value;
address msgSender = msg.sender;
IAllowanceTransfer.AllowanceTransferDetails[] memory details =
new IAllowanceTransfer.AllowanceTransferDetails[](src.tokens.length);
uint256 detailsLength = 0;
for (uint256 i = 0; i < src.tokens.length;) {
if (src.tokens[i] == ETH_ADDRESS) {
// native token, should appear only once with correct msg.value
require(msgValue > 0 && msgValue == src.amounts[i], 'ZapRouter: invalid msg value');
msgValue = 0;
} else if (
src.tokens[i].erc20Permit(msgSender, src.permitData[i]) || src.permitData[i].length == 0
) {
src.tokens[i].safeTransferFrom(msgSender, _executor, src.amounts[i]);
} else {
details[detailsLength++] = IAllowanceTransfer.AllowanceTransferDetails({
from: msgSender, to: _executor, amount: uint160(src.amounts[i]), token: src.tokens[i]
});
}
emit ERC20Collected(src.tokens[i], src.amounts[i]);
unchecked {
++i;
}
}
require(msgValue == 0, 'ZapRouter: invalid msg value');
if (detailsLength > 0) {
if (src.permit2Data.length > 0) {
(bool success,) = address(permit2)
.call(abi.encodePacked(IAllowanceTransfer.permit.selector, src.permit2Data));
if (!success) {
revert('ZapRouter: permit2 permit failed');
}
}
assembly ('memory-safe') {
mstore(details, detailsLength)
}
permit2.transferFrom(details);
}
}
/// @notice Handle collecting ERC721 token and transfer to executor
function _handleCollectERC721Tokens(ERC721SrcInfo calldata src, address _executor) internal {
require(
src.tokens.length == src.ids.length && src.tokens.length == src.permitData.length,
'ZapRouter: invalid data'
);
for (uint256 i = 0; i < src.tokens.length;) {
src.tokens[i].erc721Permit(src.ids[i], src.permitData[i]);
IERC721(src.tokens[i]).safeTransferFrom(msg.sender, _executor, src.ids[i]);
emit ERC721Collected(src.tokens[i], src.ids[i]);
unchecked {
++i;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
interface IKSZapRouterPositionPermit {
event ClientData(bytes _clientData);
event ZapExecuted(
address _validator,
address _executor,
bytes _zapInfo,
bytes _extraData,
bytes _initialData,
bytes _zapResults
);
event ExecutorWhitelisted(address indexed _executor, bool indexed _grantOrRevoke);
event ValidatorWhitelisted(address indexed _validator, bool indexed _grantOrRevoke);
event ERC20Collected(address indexed _token, uint256 indexed _amount);
event ERC721Collected(address indexed _token, uint256 indexed _id);
/// @dev Contains general data for zapping and validation
/// @param srcInfo src position info
/// @param zapInfo extra info, depends on each dex type
/// @param extraData extra data to be used for validation
struct ZapDescription {
ERC20SrcInfo erc20SrcInfo;
ERC721SrcInfo erc721SrcInfo;
bytes zapInfo;
bytes extraData;
}
/// @dev Contains execution data for zapping
/// @param validator validator address, must be whitelisted one
/// @param executor zap executor address, must be whitelisted one
/// @param deadline make sure the request is not expired yet
/// @param executorData data for zap execution
/// @param clientData for events and tracking purposes
struct ZapExecutionData {
address validator;
address executor;
uint32 deadline;
bytes executorData;
bytes clientData;
}
/// @dev Contains address and function for the delegatecall
/// @param helper helper address
/// @param funcSelector helper function
struct DelegatecallData {
address helper;
bytes4 funcSelector;
}
struct ERC20SrcInfo {
address[] tokens;
uint256[] amounts;
bytes[] permitData;
bytes permit2Data;
}
struct ERC721SrcInfo {
address[] tokens;
uint256[] ids;
bytes[] permitData;
}
/// @notice collect token, execute and validate zap
function zap(ZapDescription calldata _desc, ZapExecutionData calldata _exe)
external
payable
returns (bytes memory zapResults);
function whitelistExecutors(address[] calldata _executors, bool _grantOrRevoke) external;
function whitelistValidators(address[] calldata _validators, bool _grantOrRevoke) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IZapDexEnum {
// There must be a slot for EMPTY
enum DexType {
UniswapV2,
UniswapV3,
EMPTY,
Curve,
Balancer,
AlgebraV19,
AlgebraV19DirFee,
RamsesV2,
AerodromeV1,
RingV2,
KoiV2,
SolidlyV3,
AerodromeCL,
AlgebraIntegralV12BasePluginV2,
Gamma,
PancakeV3Staking,
ArrakisV1,
ArrakisV2,
GyroECLP,
AlgebraIntegralV10BasePluginV1,
FluidVaultT4,
SyncswapV2,
ZKSwapV3Staking,
GammaSwap,
RamsesV3,
ShadowLegacy,
ZKSwapV2,
UniswapV4,
PancakeV4CL,
Steer,
BunniV2,
SquadswapV3Staking,
BalancerV3,
DodoV2,
CamelotV2,
ZapForwarder,
KatanaV2,
KatanaV3,
Maverick,
Generic,
Arbera,
SeamlessLT,
AlgebraIntegralV12BasePluginV1
}
enum SrcType {
ERC20Token,
ERC721Token,
ERC1155Token
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
interface IKSZapExecutorActions {
// @notice Function execute zap
/// @param _executorData bytes data and will be decoded into corresponding data depends on dex type
/// @return zapResults result of the zap, depend on dex type
function executeZap(bytes calldata _executorData)
external
payable
returns (bytes memory zapResults);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
interface IKSZapValidatorActions {
function prepareValidationData(uint8 dstType, bytes calldata _zapInfo)
external
view
returns (bytes memory _validationData);
function validateData(
uint8 dstType,
bytes calldata _extraData,
bytes calldata _validationData,
bytes calldata _zapResults
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {KSRescue} from '@src/KSRescue.sol';
import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import {IERC1155} from '@openzeppelin/contracts/token/ERC1155/IERC1155.sol';
abstract contract KSRescueV2 is KSRescue {
function rescueBatchERC721(
address token,
uint256[] calldata _ids,
address recipient
) external onlyOwner {
require(recipient != address(0), 'KSRescue: invalid recipient');
for (uint256 i = 0; i < _ids.length; i++) {
IERC721(token).transferFrom(address(this), recipient, _ids[i]);
}
}
function rescueBatchERC1155(
address token,
uint256[] calldata ids,
uint256[] memory amounts,
bytes calldata data,
address recipient
) external onlyOwner {
require(recipient != address(0), 'KSRescue: invalid recipient');
require(ids.length == amounts.length, 'KSRescue: invalid array length');
for (uint256 i = 0; i < ids.length; ++i) {
if (amounts[i] == 0) amounts[i] = IERC1155(token).balanceOf(address(this), ids[i]);
}
IERC1155(token).safeBatchTransferFrom(address(this), recipient, ids, amounts, data);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title AllowanceTransfer
/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts
/// @dev Requires user's token approval on the Permit2 contract
interface IAllowanceTransfer {
/// @notice The permit data for a token
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 multiple token allowances
struct PermitBatch {
// the permit data for multiple token allowances
PermitDetails[] details;
// address permissioned on the allowed tokens
address spender;
// deadline on the permit signature
uint256 sigDeadline;
}
/// @notice A token spender pair.
struct TokenSpenderPair {
// the token the spender is approved
address token;
// the spender address
address spender;
}
/// @notice Details for a token transfer.
struct AllowanceTransferDetails {
// the owner of the token
address from;
// the recipient of the token
address to;
// the amount of the token
uint160 amount;
// the token to be transferred
address token;
}
/// @notice Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature
/// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce
/// @param owner The owner of the tokens being approved
/// @param permitBatch Data signed over by the owner specifying the terms of approval
/// @param signature The owner's signature over the permit data
function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external;
/// @notice Transfer approved tokens in a batch
/// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers
/// @dev Requires the from addresses to have approved at least the desired amount
/// of tokens to msg.sender.
function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IDaiLikePermit} from '../../interfaces/IDaiLikePermit.sol';
import {IERC721Permit_v3} from '../../interfaces/IERC721Permit_v3.sol';
import {IERC721Permit_v4} from '../../interfaces/IERC721Permit_v4.sol';
import {CustomRevert} from '../CustomRevert.sol';
import {CalldataDecoder} from '../calldata/CalldataDecoder.sol';
import {IERC20Permit} from
'openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol';
library PermitHelper {
using CalldataDecoder for bytes;
/// @notice Additional context for ERC-7751 wrapped error when permit fails
error ERC20PermitFailed();
error ERC721PermitFailed();
function erc20Permit(address token, address owner, bytes calldata permitData)
internal
returns (bool success)
{
if (permitData.length == 32 * 5) {
success = _callErc20Permit(token, owner, IERC20Permit.permit.selector, permitData);
} else if (permitData.length == 32 * 6) {
success = _callErc20Permit(token, owner, IDaiLikePermit.permit.selector, permitData);
} else {
return false;
}
}
function erc721Permit(address token, uint256 tokenId, bytes calldata permitData)
internal
returns (bool success)
{
if (permitData.length == 32 * 4) {
success = _callErc721Permit(token, tokenId, IERC721Permit_v3.permit.selector, permitData, 0);
} else if (permitData.length == 32 * 7) {
success =
_callErc721Permit(token, tokenId, IERC721Permit_v4.permit.selector, permitData, 0xa0);
} else {
return false;
}
}
function _callErc721Permit(
address token,
uint256 tokenId,
bytes4 selector,
bytes calldata permitData,
uint256 overrideSigOffset
) internal returns (bool success) {
bytes memory data = new bytes(4 + 32 * 2 + permitData.length);
assembly ("memory-safe") {
mstore(add(data, 0x20), selector)
mstore(add(data, 0x24), address())
mstore(add(data, 0x44), tokenId)
calldatacopy(add(data, 0x64), permitData.offset, permitData.length)
// override the signature offset in case dynamic bytes (65 bytes length)
if overrideSigOffset { mstore(add(data, add(overrideSigOffset, 4)), overrideSigOffset) }
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0)
}
if (!success) {
CustomRevert.bubbleUpAndRevertWith(token, selector, ERC721PermitFailed.selector);
}
}
function _callErc20Permit(
address token,
address owner,
bytes4 selector,
bytes calldata permitData
) internal returns (bool success) {
bytes memory data = new bytes(4 + 32 * 2 + permitData.length);
assembly ("memory-safe") {
mstore(add(data, 0x20), selector)
mstore(add(data, 0x24), owner)
mstore(add(data, 0x44), address())
calldatacopy(add(data, 0x64), permitData.offset, permitData.length)
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0)
}
if (!success) {
CustomRevert.bubbleUpAndRevertWith(token, selector, ERC20PermitFailed.selector);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {CustomRevert} from '../CustomRevert.sol';
import {IERC20} from 'openzeppelin-contracts/contracts/interfaces/IERC20.sol';
/// @title Library for transferring, approving and holding native tokens and ERC20 tokens
/// @dev This library is based on CurrencyLibrary.sol from Uniswap/v4-core and SafeTransferLib.sol from transmissions11/solmate
library TokenHelper {
/// @notice Additional context for ERC-7751 wrapped error when a native transfer fails
error NativeTransferFailed();
/// @notice Additional context for ERC-7751 wrapped error when an ERC20 transfer fails
error ERC20TransferFailed();
/// @notice Additional context for ERC-7751 wrapped error when an ERC20 approve fails
error ERC20ApproveFailed();
address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function isNative(address token) internal pure returns (bool) {
return token == NATIVE_ADDRESS;
}
function safeTransferNative(address to, uint256 amount) internal {
if (amount == 0) return;
bool success;
assembly ("memory-safe") {
// Transfer the ETH and revert if it fails.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
// revert with NativeTransferFailed, containing the bubbled up error as an argument
if (!success) {
CustomRevert.bubbleUpAndRevertWith(to, bytes4(0), NativeTransferFailed.selector);
}
}
function safeTransferERC20(address token, address to, uint256 amount) internal {
if (amount == 0) return;
bool success;
assembly ("memory-safe") {
// Get a pointer to some free memory.
let fmp := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success :=
and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, fmp, 68, 0, 32)
)
// Now clean the memory we used
mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here
mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here
mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here
}
// revert with ERC20TransferFailed, containing the bubbled up error as an argument
if (!success) {
CustomRevert.bubbleUpAndRevertWith(
token, IERC20.transfer.selector, ERC20TransferFailed.selector
);
}
}
function safeTransfer(address token, address to, uint256 amount) internal {
if (isNative(token)) {
safeTransferNative(to, amount);
} else {
safeTransferERC20(token, to, amount);
}
}
function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
if (amount == 0) return;
bool success;
assembly ("memory-safe") {
// Get a pointer to some free memory.
let fmp := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(fmp, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(fmp, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
mstore(add(fmp, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(fmp, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success :=
and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, fmp, 100, 0, 32)
)
// Now clean the memory we used
mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `from` were stored here
mstore(add(fmp, 0x20), 0) // 4 bytes of `from` and 28 bytes of `to` were stored here
mstore(add(fmp, 0x40), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here
mstore(add(fmp, 0x60), 0) // 4 bytes of `amount` were stored here
}
// revert with ERC20TransferFailed, containing the bubbled up error as an argument
if (!success) {
CustomRevert.bubbleUpAndRevertWith(
token, IERC20.transferFrom.selector, ERC20TransferFailed.selector
);
}
}
function trySafeApprove(address token, address spender, uint256 amount)
internal
returns (bool success)
{
assembly ("memory-safe") {
// Get a pointer to some free memory.
let fmp := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(fmp, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(fmp, 4), and(spender, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "spender" argument.
mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success :=
and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, fmp, 68, 0, 32)
)
// Now clean the memory we used
mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here
mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here
mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here
}
}
function safeApprove(address token, address spender, uint256 amount) internal {
// revert with ERC20ApproveFailed, containing the bubbled up error as an argument
if (!trySafeApprove(token, spender, amount)) {
CustomRevert.bubbleUpAndRevertWith(
token, IERC20.approve.selector, ERC20ApproveFailed.selector
);
}
}
function forceApprove(address token, address spender, uint256 amount) internal {
// meant to be used with tokens that require the approval to be set to zero before setting it to a non-zero value, such as USDT
if (!trySafeApprove(token, spender, amount)) {
safeApprove(token, spender, 0);
safeApprove(token, spender, amount);
}
}
function balanceOf(address token, address account) internal view returns (uint256) {
if (isNative(token)) {
return account.balance;
} else {
return IERC20(token).balanceOf(account);
}
}
function selfBalance(address token) internal view returns (uint256) {
if (isNative(token)) {
return address(this).balance;
} else {
return IERC20(token).balanceOf(address(this));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {KyberSwapRole} from '@src/KyberSwapRole.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
abstract contract KSRescue is KyberSwapRole {
using SafeERC20 for IERC20;
address private constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
function rescueFunds(address token, uint256 amount, address recipient) external onlyOwner {
require(recipient != address(0), 'KSRescue: invalid recipient');
if (amount == 0) amount = _getAvailableAmount(token);
if (amount > 0) {
if (_isETH(token)) {
(bool success,) = recipient.call{value: amount}('');
require(success, 'KSRescue: ETH_TRANSFER_FAILED');
} else {
IERC20(token).safeTransfer(recipient, amount);
}
}
}
function _getAvailableAmount(address token) internal view virtual returns (uint256 amount) {
if (_isETH(token)) {
amount = address(this).balance;
} else {
amount = IERC20(token).balanceOf(address(this));
}
if (amount > 0) --amount;
}
function _isETH(address token) internal pure returns (bool) {
return (token == ETH_ADDRESS);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Interface for DAI-style permits
interface IDaiLikePermit {
/// @notice Permit a spender to a given amount of the holder's token via the holder's EIP-712 signature
/// @dev May fail if the holder's nonce was invalidated in-flight by invalidateNonce
/// @param holder The holder of the tokens being approved
/// @param spender The address permissioned on the allowed tokens
/// @param nonce The nonce of the holder
/// @param expiry The expiry of the permit
/// @param allowed Whether the permit is allowed
/// @param v The v component of the signature
/// @param r The r component of the signature
/// @param s The s component of the signature
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
/// @title ERC721 with permit
/// @notice Extension to ERC721 that includes a permit function for signature based approvals
interface IERC721Permit_v3 {
/// @notice The permit typehash used in the permit signature
/// @return The typehash for the permit
function PERMIT_TYPEHASH() external pure returns (bytes32);
/// @notice The domain separator used in the permit signature
/// @return The domain seperator used in encoding of permit signature
function DOMAIN_SEPARATOR() external view returns (bytes32);
/// @notice Approve of a specific token ID for spending by spender via signature
/// @param spender The account that is being approved
/// @param tokenId The ID of the token that is being approved for spending
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external
payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title IERC721Permit_v4
/// @notice Interface for the ERC721Permit_v4 contract
interface IERC721Permit_v4 {
error SignatureDeadlineExpired();
error NoSelfPermit();
error Unauthorized();
/// @notice Approve of a specific token ID for spending by spender via signature
/// @param spender The account that is being approved
/// @param tokenId The ID of the token that is being approved for spending
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
/// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word
/// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v)
/// @dev payable so it can be multicalled with NATIVE related actions
function permit(
address spender,
uint256 tokenId,
uint256 deadline,
uint256 nonce,
bytes calldata signature
) external payable;
/// @notice Set an operator with full permission to an owner's tokens via signature
/// @param owner The address that is setting the operator
/// @param operator The address that will be set as an operator for the owner
/// @param approved The permission to set on the operator
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
/// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word
/// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v)
/// @dev payable so it can be multicalled with NATIVE related actions
function permitForAll(
address owner,
address operator,
bool approved,
uint256 deadline,
uint256 nonce,
bytes calldata signature
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Library for reverting with custom errors efficiently
/// @notice Contains functions for reverting with custom errors with different argument types efficiently
/// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with
/// `CustomError.selector.revertWith()`
/// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately
library CustomRevert {
/// @dev ERC-7751 error for wrapping bubbled up reverts
error WrappedError(address target, bytes4 selector, bytes reason, bytes details);
/// @dev Reverts with the selector of a custom error in the scratch space
function revertWith(bytes4 selector) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
revert(0, 0x04)
}
}
/// @dev Reverts with a custom error with an address argument in the scratch space
function revertWith(bytes4 selector, address addr) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
revert(0, 0x24)
}
}
/// @dev Reverts with a custom error with an int24 argument in the scratch space
function revertWith(bytes4 selector, int24 value) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, signextend(2, value))
revert(0, 0x24)
}
}
/// @dev Reverts with a custom error with a uint160 argument in the scratch space
function revertWith(bytes4 selector, uint160 value) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff))
revert(0, 0x24)
}
}
/// @dev Reverts with a custom error with two int24 arguments
function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure {
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, selector)
mstore(add(fmp, 0x04), signextend(2, value1))
mstore(add(fmp, 0x24), signextend(2, value2))
revert(fmp, 0x44)
}
}
/// @dev Reverts with a custom error with two uint160 arguments
function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure {
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, selector)
mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))
revert(fmp, 0x44)
}
}
/// @dev Reverts with a custom error with two address arguments
function revertWith(bytes4 selector, address value1, address value2) internal pure {
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, selector)
mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))
revert(fmp, 0x44)
}
}
/// @notice bubble up the revert message returned by a call and revert with a wrapped ERC-7751 error
/// @dev this method can be vulnerable to revert data bombs
function bubbleUpAndRevertWith(
address revertingContract,
bytes4 revertingFunctionSelector,
bytes4 additionalContext
) internal pure {
bytes4 wrappedErrorSelector = WrappedError.selector;
assembly ("memory-safe") {
// Ensure the size of the revert data is a multiple of 32 bytes
let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32)
let fmp := mload(0x40)
// Encode wrapped error selector, address, function selector, offset, additional context, size, revert reason
mstore(fmp, wrappedErrorSelector)
mstore(add(fmp, 0x04), and(revertingContract, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(
add(fmp, 0x24),
and(
revertingFunctionSelector,
0xffffffff00000000000000000000000000000000000000000000000000000000
)
)
// offset revert reason
mstore(add(fmp, 0x44), 0x80)
// offset additional context
mstore(add(fmp, 0x64), add(0xa0, encodedDataSize))
// size revert reason
mstore(add(fmp, 0x84), returndatasize())
// revert reason
returndatacopy(add(fmp, 0xa4), 0, returndatasize())
// size additional context
mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04)
// additional context
mstore(
add(fmp, add(0xc4, encodedDataSize)),
and(additionalContext, 0xffffffff00000000000000000000000000000000000000000000000000000000)
)
revert(fmp, add(0xe4, encodedDataSize))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Library for abi decoding in calldata
library CalldataDecoder {
error SliceOutOfBounds();
/// @notice mask used for offsets and lengths to ensure no overflow
/// @dev no sane abi encoding will pass in an offset or length greater than type(uint32).max
/// (note that this does deviate from standard solidity behavior and offsets/lengths will
/// be interpreted as mod type(uint32).max which will only impact malicious/buggy callers)
uint256 constant OFFSET_OR_LENGTH_MASK = 0xffffffff;
uint256 constant OFFSET_OR_LENGTH_MASK_AND_WORD_ALIGN = 0xffffffe0;
/// @notice equivalent to SliceOutOfBounds.selector, stored in least-significant bits
uint256 constant SLICE_ERROR_SELECTOR = 0x3b99b53d;
function decodeAddress(bytes calldata data) internal pure returns (address value) {
assembly ("memory-safe") {
value := calldataload(data.offset)
}
}
function decodeUint256(bytes calldata data) internal pure returns (uint256 value) {
assembly ("memory-safe") {
value := calldataload(data.offset)
}
}
function decodeBool(bytes calldata data) internal pure returns (bool value) {
assembly ("memory-safe") {
value := calldataload(data.offset)
}
}
function decodeBytes32(bytes calldata data) internal pure returns (bytes32 value) {
assembly ("memory-safe") {
value := calldataload(data.offset)
}
}
/// @notice Decode the `_arg`-th element in `_bytes` as a dynamic array
/// @dev The decoding of `length` and `offset` is universal,
/// whereas the type declaration of `res` instructs the compiler how to read it.
/// @param _bytes The input bytes string to slice
/// @param _arg The index of the argument to extract
/// @return length Length of the array
/// @return offset Pointer to the data part of the array
function decodeLengthOffset(bytes calldata _bytes, uint256 _arg)
internal
pure
returns (uint256 length, uint256 offset)
{
assembly ("memory-safe") {
// The offset of the `_arg`-th element is `32 * arg`, which stores the offset of the length pointer.
// shl(5, x) is equivalent to mul(32, x)
let lengthPtr := add(_bytes.offset, calldataload(add(_bytes.offset, shl(5, _arg))))
length := calldataload(lengthPtr)
offset := add(lengthPtr, 0x20)
// if the provided bytes string isnt as long as the encoding says, revert
if lt(add(_bytes.length, _bytes.offset), add(length, offset)) {
mstore(0, SLICE_ERROR_SELECTOR)
revert(0x1c, 4)
}
}
}
/// @notice Decode the `_arg`-th element in `_bytes` as `bytes`
/// @param _bytes The input bytes string to extract a bytes string from
/// @param _arg The index of the argument to extract
function decodeBytes(bytes calldata _bytes, uint256 _arg)
internal
pure
returns (bytes calldata res)
{
(uint256 length, uint256 offset) = decodeLengthOffset(_bytes, _arg);
assembly ("memory-safe") {
res.length := length
res.offset := offset
}
}
/// @notice Decode the `_arg`-th element in `_bytes` as `uint256[]`
/// @param _bytes The input bytes string to extract a uint256 array from
/// @param _arg The index of the argument to extract
function decodeUint256Array(bytes calldata _bytes, uint256 _arg)
internal
pure
returns (uint256[] calldata res)
{
(uint256 length, uint256 offset) = decodeLengthOffset(_bytes, _arg);
assembly ("memory-safe") {
res.length := length
res.offset := offset
}
}
/// @notice Decode the `_arg`-th element in `_bytes` as `address[]`
/// @param _bytes The input bytes string to extract an address array from
/// @param _arg The index of the argument to extract
function decodeAddressArray(bytes calldata _bytes, uint256 _arg)
internal
pure
returns (address[] calldata res)
{
(uint256 length, uint256 offset) = decodeLengthOffset(_bytes, _arg);
assembly ("memory-safe") {
res.length := length
res.offset := offset
}
}
/// @notice Decode the `_arg`-th element in `_bytes` as `bytes32[]`
/// @param _bytes The input bytes string to extract a bytes32 array from
/// @param _arg The index of the argument to extract
function decodeBytes32Array(bytes calldata _bytes, uint256 _arg)
internal
pure
returns (bytes32[] calldata res)
{
(uint256 length, uint256 offset) = decodeLengthOffset(_bytes, _arg);
assembly ("memory-safe") {
res.length := length
res.offset := offset
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
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].
*
* CAUTION: See Security Considerations above.
*/
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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {Pausable} from '@openzeppelin/contracts/security/Pausable.sol';
abstract contract KyberSwapRole is Ownable, Pausable {
mapping(address => bool) public operators;
mapping(address => bool) public guardians;
/**
* @dev Emitted when the an user was grant or revoke operator role.
*/
event UpdateOperator(address user, bool grantOrRevoke);
/**
* @dev Emitted when the an user was grant or revoke guardian role.
*/
event UpdateGuardian(address user, bool grantOrRevoke);
/**
* @dev Modifier to make a function callable only when caller is operator.
*
* Requirements:
*
* - Caller must have operator role.
*/
modifier onlyOperator() {
require(operators[msg.sender], 'KyberSwapRole: not operator');
_;
}
/**
* @dev Modifier to make a function callable only when caller is guardian.
*
* Requirements:
*
* - Caller must have guardian role.
*/
modifier onlyGuardian() {
require(guardians[msg.sender], 'KyberSwapRole: not guardian');
_;
}
/**
* @dev Update Operator role for user.
* Can only be called by the current owner.
*/
function updateOperator(address user, bool grantOrRevoke) external onlyOwner {
operators[user] = grantOrRevoke;
emit UpdateOperator(user, grantOrRevoke);
}
/**
* @dev Update Guardian role for user.
* Can only be called by the current owner.
*/
function updateGuardian(address user, bool grantOrRevoke) external onlyOwner {
guardians[user] = grantOrRevoke;
emit UpdateGuardian(user, grantOrRevoke);
}
/**
* @dev Enable logic for contract.
* Can only be called by the current owner.
*/
function enableLogic() external onlyOwner {
_unpause();
}
/**
* @dev Disable logic for contract.
* Can only be called by the guardians.
*/
function disableLogic() external onlyGuardian {
_pause();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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 value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @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() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(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");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
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;
}
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"openzeppelin/=lib/openzeppelin-contracts/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"ks-growth-utils-sc/=lib/ks-growth-utils-sc/",
"ks-common-sc/=lib/ks-common-sc/",
"openzeppelin-contracts/=lib/ks-common-sc/lib/openzeppelin-contracts/",
"@openzeppelin/=lib/ks-growth-utils-sc/lib/openzeppelin-contracts/",
"@src/=lib/ks-growth-utils-sc/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-zksync-std/=lib/forge-zksync-std/src/",
"halmos-cheatcodes/=lib/ks-common-sc/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_permit2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"_clientData","type":"bytes"}],"name":"ClientData","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"ERC20Collected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"uint256","name":"_id","type":"uint256"}],"name":"ERC721Collected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_executor","type":"address"},{"indexed":true,"internalType":"bool","name":"_grantOrRevoke","type":"bool"}],"name":"ExecutorWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"grantOrRevoke","type":"bool"}],"name":"UpdateGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"grantOrRevoke","type":"bool"}],"name":"UpdateOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_validator","type":"address"},{"indexed":true,"internalType":"bool","name":"_grantOrRevoke","type":"bool"}],"name":"ValidatorWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_validator","type":"address"},{"indexed":false,"internalType":"address","name":"_executor","type":"address"},{"indexed":false,"internalType":"bytes","name":"_zapInfo","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_extraData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_initialData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_zapResults","type":"bytes"}],"name":"ZapExecuted","type":"event"},{"inputs":[],"name":"disableLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"guardians","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueBatchERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueBatchERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"grantOrRevoke","type":"bool"}],"name":"updateGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"grantOrRevoke","type":"bool"}],"name":"updateOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_executors","type":"address[]"},{"internalType":"bool","name":"_grantOrRevoke","type":"bool"}],"name":"whitelistExecutors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_validators","type":"address[]"},{"internalType":"bool","name":"_grantOrRevoke","type":"bool"}],"name":"whitelistValidators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedExecutor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes[]","name":"permitData","type":"bytes[]"},{"internalType":"bytes","name":"permit2Data","type":"bytes"}],"internalType":"struct IKSZapRouterPositionPermit.ERC20SrcInfo","name":"erc20SrcInfo","type":"tuple"},{"components":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"bytes[]","name":"permitData","type":"bytes[]"}],"internalType":"struct IKSZapRouterPositionPermit.ERC721SrcInfo","name":"erc721SrcInfo","type":"tuple"},{"internalType":"bytes","name":"zapInfo","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct IKSZapRouterPositionPermit.ZapDescription","name":"_desc","type":"tuple"},{"components":[{"internalType":"address","name":"validator","type":"address"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bytes","name":"executorData","type":"bytes"},{"internalType":"bytes","name":"clientData","type":"bytes"}],"internalType":"struct IKSZapRouterPositionPermit.ZapExecutionData","name":"_exe","type":"tuple"}],"name":"zap","outputs":[{"internalType":"bytes","name":"zapResults","type":"bytes"}],"stateMutability":"payable","type":"function"}]Contract Creation Code
60a060405234801561000f575f80fd5b50604051612bc6380380612bc683398101604081905261002e916100a8565b61003733610059565b5f805460ff60a01b1916905560016003556001600160a01b03166080526100d5565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100b8575f80fd5b81516001600160a01b03811681146100ce575f80fd5b9392505050565b608051612ad26100f45f395f8181611723015261182f0152612ad25ff3fe608060405260043610610105575f3560e01c8063a5644e2e11610092578063cc15009711610062578063cc150097146102df578063dff3ca7d146102fe578063e83aa3a81461031d578063f2fde38b1461033c578063f9338d181461035b575f80fd5b8063a5644e2e14610253578063a827db4614610273578063c2eb5282146102a1578063c5389017146102c0575f80fd5b8063715018a6116100d8578063715018a6146101b857806388f4950f146101cc5780638da5cb5b146101eb5780639abf6f1f146102115780639dd392391461023f575f80fd5b80630633b14a1461010957806313e7c9d81461014c5780635c975abb1461017a5780636d44a3b214610197575b5f80fd5b348015610114575f80fd5b506101376101233660046121d0565b60026020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b348015610157575f80fd5b506101376101663660046121d0565b60016020525f908152604090205460ff1681565b348015610185575f80fd5b505f54600160a01b900460ff16610137565b3480156101a2575f80fd5b506101b66101b13660046121f6565b61036f565b005b3480156101c3575f80fd5b506101b6610404565b3480156101d7575f80fd5b506101b66101e63660046121f6565b610438565b3480156101f6575f80fd5b505f546040516001600160a01b039091168152602001610143565b34801561021c575f80fd5b5061013761022b3660046121d0565b60056020525f908152604090205460ff1681565b34801561024a575f80fd5b506101b66104bc565b61026661026136600461222b565b610522565b60405161014391906122bb565b34801561027e575f80fd5b5061013761028d3660046121d0565b60046020525f908152604090205460ff1681565b3480156102ac575f80fd5b506101b66102bb366004612314565b610a21565b3480156102cb575f80fd5b506101b66102da366004612366565b610b13565b3480156102ea575f80fd5b506101b66102f9366004612447565b610c0c565b348015610309575f80fd5b506101b6610318366004612314565b610e00565b348015610328575f80fd5b506101b6610337366004612570565b610eec565b348015610347575f80fd5b506101b66103563660046121d0565b611030565b348015610366575f80fd5b506101b66110ca565b5f546001600160a01b031633146103a15760405162461bcd60e51b8152600401610398906125a9565b60405180910390fd5b6001600160a01b0382165f81815260016020908152604091829020805460ff19168515159081179091558251938452908301527f2ee52be9d342458b3d25e07faada7ff9bc06723b4aa24edb6321ac1316b8a9dd91015b60405180910390a15050565b5f546001600160a01b0316331461042d5760405162461bcd60e51b8152600401610398906125a9565b6104365f6110fb565b565b5f546001600160a01b031633146104615760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b0382165f81815260026020908152604091829020805460ff19168515159081179091558251938452908301527f25d7ce8d7e0b3990938766275ee2d54fbe81347d287bfbf0429838409a889fdc91016103f8565b335f9081526002602052604090205460ff1661051a5760405162461bcd60e51b815260206004820152601b60248201527f4b7962657253776170526f6c653a206e6f7420677561726469616e00000000006044820152606401610398565b61043661114a565b5f54606090600160a01b900460ff16156105715760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610398565b6105796111ed565b61058960608301604084016125de565b8063ffffffff164211156105d45760405162461bcd60e51b815260206004820152601260248201527116985c149bdd5d195c8e88195e1c1a5c995960721b6044820152606401610398565b60045f6105e760408601602087016121d0565b6001600160a01b0316815260208101919091526040015f205460ff1661065b5760405162461bcd60e51b815260206004820152602360248201527f5a6170526f757465723a206e6f6e2077686974656c69737465642065786563756044820152623a37b960e91b6064820152608401610398565b61067d6106688580612601565b61067860408601602087016121d0565b611246565b6106a261068d602086018661261f565b61069d60408601602087016121d0565b61189a565b60605f6106b260208601866121d0565b6001600160a01b0316146107cf5760055f6106d060208701876121d0565b6001600160a01b0316815260208101919091526040015f205460ff166107445760405162461bcd60e51b8152602060048201526024808201527f5a6170526f757465723a206e6f6e2077686974656c69737465642076616c696460448201526330ba37b960e11b6064820152608401610398565b61075160208501856121d0565b6001600160a01b031663c6256bef5f61076d6040890189612633565b6040518463ffffffff1660e01b815260040161078b9392919061269d565b5f60405180830381865afa1580156107a5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107cc91908101906126c2565b90505b6107df60408501602086016121d0565b6001600160a01b031663f012a2b6346107fb6060880188612633565b6040518463ffffffff1660e01b8152600401610818929190612754565b5f6040518083038185885af1158015610833573d5f803e3d5ffd5b50505050506040513d5f823e601f3d908101601f1916820160405261085b91908101906126c2565b92505f61086b60208601866121d0565b6001600160a01b031614610955575f61088760208601866121d0565b6001600160a01b031663af0a35575f6108a360608a018a612633565b86896040518663ffffffff1660e01b81526004016108c5959493929190612767565b602060405180830381865afa1580156108e0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090491906127b5565b9050806109535760405162461bcd60e51b815260206004820152601c60248201527f5a6170526f757465723a2076616c69646174696f6e206661696c6564000000006044820152606401610398565b505b7f664f14ee7c88b7407107e4cfdc6fc831e19ac4fbdb28c1906a79c0d03cf19a3061098360208601866121d0565b61099360408701602088016121d0565b6109a06040890189612633565b6109ad60608b018b612633565b878a6040516109c39897969594939291906127d0565b60405180910390a17f095e66fa4dd6a6f7b43fb8444a7bd0edb870508c7abf639bc216efb0bcff97796109f96080860186612633565b604051610a07929190612754565b60405180910390a15050610a1b6001600355565b92915050565b5f546001600160a01b03163314610a4a5760405162461bcd60e51b8152600401610398906125a9565b5f5b82811015610b0d578160045f868685818110610a6a57610a6a612846565b9050602002016020810190610a7f91906121d0565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055811515848483818110610abb57610abb612846565b9050602002016020810190610ad091906121d0565b6001600160a01b03167f19f4c310cf148369e5605e8f3538cee4d3495da0612c9a45c0b89105ed6fee4d60405160405180910390a3600101610a4c565b50505050565b5f546001600160a01b03163314610b3c5760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b038116610b625760405162461bcd60e51b81526004016103989061285a565b5f5b82811015610c0557846001600160a01b03166323b872dd3084878786818110610b8f57610b8f612846565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152506020909102013560448201526064015f604051808303815f87803b158015610be3575f80fd5b505af1158015610bf5573d5f803e3d5ffd5b505060019092019150610b649050565b5050505050565b5f546001600160a01b03163314610c355760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b038116610c5b5760405162461bcd60e51b81526004016103989061285a565b83518514610cab5760405162461bcd60e51b815260206004820152601e60248201527f4b535265736375653a20696e76616c6964206172726179206c656e67746800006044820152606401610398565b5f5b85811015610d9157848181518110610cc757610cc7612846565b60200260200101515f03610d8957876001600160a01b031662fdd58e30898985818110610cf657610cf6612846565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401602060405180830381865afa158015610d46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d6a9190612891565b858281518110610d7c57610d7c612846565b6020026020010181815250505b600101610cad565b50604051631759616b60e11b81526001600160a01b03881690632eb2c2d690610dca90309085908b908b908b908b908b906004016128a8565b5f604051808303815f87803b158015610de1575f80fd5b505af1158015610df3573d5f803e3d5ffd5b5050505050505050505050565b5f546001600160a01b03163314610e295760405162461bcd60e51b8152600401610398906125a9565b5f5b82811015610b0d578160055f868685818110610e4957610e49612846565b9050602002016020810190610e5e91906121d0565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055811515848483818110610e9a57610e9a612846565b9050602002016020810190610eaf91906121d0565b6001600160a01b03167f43572750395348a3948322f95d3b0bf4773311c6c19ec9a575cde194e5bac21160405160405180910390a3600101610e2b565b5f546001600160a01b03163314610f155760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b038116610f3b5760405162461bcd60e51b81526004016103989061285a565b815f03610f4e57610f4b83611b29565b91505b811561102b5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03841603611017575f816001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610fc1576040519150601f19603f3d011682016040523d82523d5f602084013e610fc6565b606091505b5050905080610b0d5760405162461bcd60e51b815260206004820152601d60248201527f4b535265736375653a204554485f5452414e534645525f4641494c45440000006044820152606401610398565b61102b6001600160a01b0384168284611bd5565b505050565b5f546001600160a01b031633146110595760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b0381166110be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610398565b6110c7816110fb565b50565b5f546001600160a01b031633146110f35760405162461bcd60e51b8152600401610398906125a9565b610436611c27565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f54600160a01b900460ff16156111965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610398565b5f805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111d03390565b6040516001600160a01b03909116815260200160405180910390a1565b60026003540361123f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610398565b6002600355565b6112536020830183612953565b905061125f8380612953565b905014801561128657506112766040830183612953565b90506112828380612953565b9050145b6112cc5760405162461bcd60e51b81526020600482015260176024820152765a6170526f757465723a20696e76616c6964206461746160481b6044820152606401610398565b34335f6112d98580612953565b90506001600160401b038111156112f2576112f26123c6565b60405190808252806020026020018201604052801561134257816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f199092019101816113105790505b5090505f805b6113528780612953565b90508110156116ad5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee61137a8880612953565b8381811061138a5761138a612846565b905060200201602081019061139f91906121d0565b6001600160a01b031603611432575f851180156113de57506113c46020880188612953565b828181106113d4576113d4612846565b9050602002013585145b61142a5760405162461bcd60e51b815260206004820152601c60248201527f5a6170526f757465723a20696e76616c6964206d73672076616c7565000000006044820152606401610398565b5f945061161a565b6114a58461144360408a018a612953565b8481811061145357611453612846565b90506020028101906114659190612633565b61146f8b80612953565b8681811061147f5761147f612846565b905060200201602081019061149491906121d0565b6001600160a01b0316929190611ca9565b806114de57506114b86040880188612953565b828181106114c8576114c8612846565b90506020028101906114da9190612633565b1590505b156115545761154f84876114f560208b018b612953565b8581811061150557611505612846565b602002919091013590506115198b80612953565b8681811061152957611529612846565b905060200201602081019061153e91906121d0565b6001600160a01b0316929190611cf6565b61161a565b6040518060800160405280856001600160a01b03168152602001876001600160a01b0316815260200188806020019061158d9190612953565b8481811061159d5761159d612846565b905060200201356001600160a01b0316815260200188805f01906115c19190612953565b848181106115d1576115d1612846565b90506020020160208101906115e691906121d0565b6001600160a01b0316905283836115fc816129ac565b94508151811061160e5761160e612846565b60200260200101819052505b6116276020880188612953565b8281811061163757611637612846565b6020029190910135905061164b8880612953565b8381811061165b5761165b612846565b905060200201602081019061167091906121d0565b6001600160a01b03167f542ffabdd5320a08598fbaa483210c5e34df4cfbd7f2541470a88d43c640311460405160405180910390a3600101611348565b5083156116fc5760405162461bcd60e51b815260206004820152601c60248201527f5a6170526f757465723a20696e76616c6964206d73672076616c7565000000006044820152606401610398565b8015611892575f6117106060880188612633565b90501115611815575f6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016632a2d80d160e01b61175860608a018a612633565b60405160200161176a939291906129c4565b60408051601f1981840301815290829052611784916129e7565b5f604051808303815f865af19150503d805f81146117bd576040519150601f19603f3d011682016040523d82523d5f602084013e6117c2565b606091505b50509050806118135760405162461bcd60e51b815260206004820181905260248201527f5a6170526f757465723a207065726d697432207065726d6974206661696c65646044820152606401610398565b505b808252604051630d58b1db60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630d58b1db906118649085906004016129fd565b5f604051808303815f87803b15801561187b575f80fd5b505af115801561188d573d5f803e3d5ffd5b505050505b505050505050565b6118a76020830183612953565b90506118b38380612953565b90501480156118da57506118ca6040830183612953565b90506118d68380612953565b9050145b6119205760405162461bcd60e51b81526020600482015260176024820152765a6170526f757465723a20696e76616c6964206461746160481b6044820152606401610398565b5f5b61192c8380612953565b905081101561102b576119ce6119456020850185612953565b8381811061195557611955612846565b9050602002013584806040019061196c9190612953565b8481811061197c5761197c612846565b905060200281019061198e9190612633565b6119988780612953565b868181106119a8576119a8612846565b90506020020160208101906119bd91906121d0565b6001600160a01b0316929190611d7c565b506119d98380612953565b828181106119e9576119e9612846565b90506020020160208101906119fe91906121d0565b6001600160a01b03166342842e0e3384611a1b6020880188612953565b86818110611a2b57611a2b612846565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152506020909102013560448201526064015f604051808303815f87803b158015611a7f575f80fd5b505af1158015611a91573d5f803e3d5ffd5b50611aa3925050506020840184612953565b82818110611ab357611ab3612846565b60200291909101359050611ac78480612953565b83818110611ad757611ad7612846565b9050602002016020810190611aec91906121d0565b6001600160a01b03167fa6fb63d713a5a606436dc801f04dfdfd00d8e5211c54bc1332aeb047992c06f760405160405180910390a3600101611922565b5f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03831603611b55575047611bbe565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611b97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bbb9190612891565b90505b8015611bd057611bcd81612a74565b90505b919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261102b908490611dba565b5f54600160a01b900460ff16611c765760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610398565b5f805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336111d0565b5f60a0829003611cce57611cc7858563d505accf60e01b8686611e8b565b9050611cee565b60c0829003611ceb57611cc785856323f2ebc360e21b8686611e8b565b505f5b949350505050565b8015610b0d575f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af13d15601f3d1160015f511416171691505f81525f60208201525f60408201525f60608201525080610c0557610c05856323b872dd60e01b633c9fd93960e21b611f24565b5f6080829003611d9b57611cc78585637ac2ff7b60e01b86865f611f9c565b60e0829003611ceb57611cc78585630f5730f160e01b868660a0611f9c565b5f611e0e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120459092919063ffffffff16565b80519091501561102b5780806020019051810190611e2c91906127b5565b61102b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610398565b5f80611e98836044612a89565b6001600160401b03811115611eaf57611eaf6123c6565b6040519080825280601f01601f191660200182016040528015611ed9576020820181803683370190505b509050846020820152856024820152306044820152828460648301375f808251602084015f8b5af1915081611f1a57611f1a878663203aa5b560e11b611f24565b5095945050505050565b6040516390bfb86560e01b8082526001600160a01b03851660048301526001600160e01b031984166024830152608060448301526020601f3d018190040260a0810160648401523d608484015290913d5f60a483013e60048260a4018201526001600160e01b031984168260c4018201528160e40181fd5b5f80611fa9846044612a89565b6001600160401b03811115611fc057611fc06123c6565b6040519080825280601f01601f191660200182016040528015611fea576020820181803683370190505b5090508560208201523060248201528660448201528385606483013782156120155782600484018201525b5f808251602084015f8c5af191508161203a5761203a8887630efd078d60e11b611f24565b509695505050505050565b606061205384845f8561205d565b90505b9392505050565b6060824710156120be5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610398565b843b61210c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610398565b5f80866001600160a01b0316858760405161212791906129e7565b5f6040518083038185875af1925050503d805f8114612161576040519150601f19603f3d011682016040523d82523d5f602084013e612166565b606091505b5091509150612176828286612181565b979650505050505050565b60608315612190575081612056565b8251156121a05782518084602001fd5b8160405162461bcd60e51b815260040161039891906122bb565b80356001600160a01b0381168114611bd0575f80fd5b5f602082840312156121e0575f80fd5b612056826121ba565b80151581146110c7575f80fd5b5f8060408385031215612207575f80fd5b612210836121ba565b91506020830135612220816121e9565b809150509250929050565b5f806040838503121561223c575f80fd5b82356001600160401b03811115612251575f80fd5b830160808186031215612262575f80fd5b915060208301356001600160401b0381111561227c575f80fd5b830160a08186031215612220575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f612056602083018461228d565b5f8083601f8401126122dd575f80fd5b5081356001600160401b038111156122f3575f80fd5b6020830191508360208260051b850101111561230d575f80fd5b9250929050565b5f805f60408486031215612326575f80fd5b83356001600160401b0381111561233b575f80fd5b612347868287016122cd565b909450925050602084013561235b816121e9565b809150509250925092565b5f805f8060608587031215612379575f80fd5b612382856121ba565b935060208501356001600160401b0381111561239c575f80fd5b6123a8878288016122cd565b90945092506123bb9050604086016121ba565b905092959194509250565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612402576124026123c6565b604052919050565b5f8083601f84011261241a575f80fd5b5081356001600160401b03811115612430575f80fd5b60208301915083602082850101111561230d575f80fd5b5f805f805f805f60a0888a03121561245d575f80fd5b612466886121ba565b965060208801356001600160401b03811115612480575f80fd5b61248c8a828b016122cd565b90975095505060408801356001600160401b038111156124aa575f80fd5b8801601f81018a136124ba575f80fd5b80356001600160401b038111156124d3576124d36123c6565b8060051b6124e3602082016123da565b9182526020818401810192908101908d8411156124fe575f80fd5b6020850194505b8385101561252457843580835260209586019590935090910190612505565b9750505050606089013590506001600160401b03811115612543575f80fd5b61254f8a828b0161240a565b90945092506125629050608089016121ba565b905092959891949750929550565b5f805f60608486031215612582575f80fd5b61258b846121ba565b9250602084013591506125a0604085016121ba565b90509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b5f602082840312156125ee575f80fd5b813563ffffffff81168114612056575f80fd5b5f8235607e19833603018112612615575f80fd5b9190910192915050565b5f8235605e19833603018112612615575f80fd5b5f808335601e19843603018112612648575f80fd5b8301803591506001600160401b03821115612661575f80fd5b60200191503681900382131561230d575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60ff84168152604060208201525f6126b9604083018486612675565b95945050505050565b5f602082840312156126d2575f80fd5b81516001600160401b038111156126e7575f80fd5b8201601f810184136126f7575f80fd5b80516001600160401b03811115612710576127106123c6565b612723601f8201601f19166020016123da565b818152856020838501011115612737575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b602081525f612053602083018486612675565b60ff86168152608060208201525f612783608083018688612675565b8281036040840152612795818661228d565b905082810360608401526127a9818561228d565b98975050505050505050565b5f602082840312156127c5575f80fd5b8151612056816121e9565b6001600160a01b0389811682528816602082015260c0604082018190525f906127fc908301888a612675565b828103606084015261280f818789612675565b90508281036080840152612823818661228d565b905082810360a0840152612837818561228d565b9b9a5050505050505050505050565b634e487b7160e01b5f52603260045260245ffd5b6020808252601b908201527f4b535265736375653a20696e76616c696420726563697069656e740000000000604082015260600190565b5f602082840312156128a1575f80fd5b5051919050565b6001600160a01b0388811682528716602082015260a06040820181905281018590525f6001600160fb1b038611156128de575f80fd5b8560051b808860c085013760c090830183810382016060850152865191810182905260208701915f9160e001905b8083101561292f578351825260208201915060208401935060018301925061290c565b508481036080860152612943818789612675565b9c9b505050505050505050505050565b5f808335601e19843603018112612968575f80fd5b8301803591506001600160401b03821115612981575f80fd5b6020019150600581901b360382131561230d575f80fd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016129bd576129bd612998565b5060010190565b6001600160e01b031984168152818360048301375f910160040190815292915050565b5f82518060208501845e5f920191825250919050565b602080825282518282018190525f918401906040840190835b81811015612a6957835180516001600160a01b0390811685526020808301518216818701526040808401518316908701526060928301519091169185019190915290930192608090920191600101612a16565b509095945050505050565b5f81612a8257612a82612998565b505f190190565b80820180821115610a1b57610a1b61299856fea264697066735822122073164cba18e7287230affb12454056d4d2ff647cb680dffc4d6373f03ca1371f64736f6c634300081a0033000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Deployed Bytecode
0x608060405260043610610105575f3560e01c8063a5644e2e11610092578063cc15009711610062578063cc150097146102df578063dff3ca7d146102fe578063e83aa3a81461031d578063f2fde38b1461033c578063f9338d181461035b575f80fd5b8063a5644e2e14610253578063a827db4614610273578063c2eb5282146102a1578063c5389017146102c0575f80fd5b8063715018a6116100d8578063715018a6146101b857806388f4950f146101cc5780638da5cb5b146101eb5780639abf6f1f146102115780639dd392391461023f575f80fd5b80630633b14a1461010957806313e7c9d81461014c5780635c975abb1461017a5780636d44a3b214610197575b5f80fd5b348015610114575f80fd5b506101376101233660046121d0565b60026020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b348015610157575f80fd5b506101376101663660046121d0565b60016020525f908152604090205460ff1681565b348015610185575f80fd5b505f54600160a01b900460ff16610137565b3480156101a2575f80fd5b506101b66101b13660046121f6565b61036f565b005b3480156101c3575f80fd5b506101b6610404565b3480156101d7575f80fd5b506101b66101e63660046121f6565b610438565b3480156101f6575f80fd5b505f546040516001600160a01b039091168152602001610143565b34801561021c575f80fd5b5061013761022b3660046121d0565b60056020525f908152604090205460ff1681565b34801561024a575f80fd5b506101b66104bc565b61026661026136600461222b565b610522565b60405161014391906122bb565b34801561027e575f80fd5b5061013761028d3660046121d0565b60046020525f908152604090205460ff1681565b3480156102ac575f80fd5b506101b66102bb366004612314565b610a21565b3480156102cb575f80fd5b506101b66102da366004612366565b610b13565b3480156102ea575f80fd5b506101b66102f9366004612447565b610c0c565b348015610309575f80fd5b506101b6610318366004612314565b610e00565b348015610328575f80fd5b506101b6610337366004612570565b610eec565b348015610347575f80fd5b506101b66103563660046121d0565b611030565b348015610366575f80fd5b506101b66110ca565b5f546001600160a01b031633146103a15760405162461bcd60e51b8152600401610398906125a9565b60405180910390fd5b6001600160a01b0382165f81815260016020908152604091829020805460ff19168515159081179091558251938452908301527f2ee52be9d342458b3d25e07faada7ff9bc06723b4aa24edb6321ac1316b8a9dd91015b60405180910390a15050565b5f546001600160a01b0316331461042d5760405162461bcd60e51b8152600401610398906125a9565b6104365f6110fb565b565b5f546001600160a01b031633146104615760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b0382165f81815260026020908152604091829020805460ff19168515159081179091558251938452908301527f25d7ce8d7e0b3990938766275ee2d54fbe81347d287bfbf0429838409a889fdc91016103f8565b335f9081526002602052604090205460ff1661051a5760405162461bcd60e51b815260206004820152601b60248201527f4b7962657253776170526f6c653a206e6f7420677561726469616e00000000006044820152606401610398565b61043661114a565b5f54606090600160a01b900460ff16156105715760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610398565b6105796111ed565b61058960608301604084016125de565b8063ffffffff164211156105d45760405162461bcd60e51b815260206004820152601260248201527116985c149bdd5d195c8e88195e1c1a5c995960721b6044820152606401610398565b60045f6105e760408601602087016121d0565b6001600160a01b0316815260208101919091526040015f205460ff1661065b5760405162461bcd60e51b815260206004820152602360248201527f5a6170526f757465723a206e6f6e2077686974656c69737465642065786563756044820152623a37b960e91b6064820152608401610398565b61067d6106688580612601565b61067860408601602087016121d0565b611246565b6106a261068d602086018661261f565b61069d60408601602087016121d0565b61189a565b60605f6106b260208601866121d0565b6001600160a01b0316146107cf5760055f6106d060208701876121d0565b6001600160a01b0316815260208101919091526040015f205460ff166107445760405162461bcd60e51b8152602060048201526024808201527f5a6170526f757465723a206e6f6e2077686974656c69737465642076616c696460448201526330ba37b960e11b6064820152608401610398565b61075160208501856121d0565b6001600160a01b031663c6256bef5f61076d6040890189612633565b6040518463ffffffff1660e01b815260040161078b9392919061269d565b5f60405180830381865afa1580156107a5573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107cc91908101906126c2565b90505b6107df60408501602086016121d0565b6001600160a01b031663f012a2b6346107fb6060880188612633565b6040518463ffffffff1660e01b8152600401610818929190612754565b5f6040518083038185885af1158015610833573d5f803e3d5ffd5b50505050506040513d5f823e601f3d908101601f1916820160405261085b91908101906126c2565b92505f61086b60208601866121d0565b6001600160a01b031614610955575f61088760208601866121d0565b6001600160a01b031663af0a35575f6108a360608a018a612633565b86896040518663ffffffff1660e01b81526004016108c5959493929190612767565b602060405180830381865afa1580156108e0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090491906127b5565b9050806109535760405162461bcd60e51b815260206004820152601c60248201527f5a6170526f757465723a2076616c69646174696f6e206661696c6564000000006044820152606401610398565b505b7f664f14ee7c88b7407107e4cfdc6fc831e19ac4fbdb28c1906a79c0d03cf19a3061098360208601866121d0565b61099360408701602088016121d0565b6109a06040890189612633565b6109ad60608b018b612633565b878a6040516109c39897969594939291906127d0565b60405180910390a17f095e66fa4dd6a6f7b43fb8444a7bd0edb870508c7abf639bc216efb0bcff97796109f96080860186612633565b604051610a07929190612754565b60405180910390a15050610a1b6001600355565b92915050565b5f546001600160a01b03163314610a4a5760405162461bcd60e51b8152600401610398906125a9565b5f5b82811015610b0d578160045f868685818110610a6a57610a6a612846565b9050602002016020810190610a7f91906121d0565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055811515848483818110610abb57610abb612846565b9050602002016020810190610ad091906121d0565b6001600160a01b03167f19f4c310cf148369e5605e8f3538cee4d3495da0612c9a45c0b89105ed6fee4d60405160405180910390a3600101610a4c565b50505050565b5f546001600160a01b03163314610b3c5760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b038116610b625760405162461bcd60e51b81526004016103989061285a565b5f5b82811015610c0557846001600160a01b03166323b872dd3084878786818110610b8f57610b8f612846565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152506020909102013560448201526064015f604051808303815f87803b158015610be3575f80fd5b505af1158015610bf5573d5f803e3d5ffd5b505060019092019150610b649050565b5050505050565b5f546001600160a01b03163314610c355760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b038116610c5b5760405162461bcd60e51b81526004016103989061285a565b83518514610cab5760405162461bcd60e51b815260206004820152601e60248201527f4b535265736375653a20696e76616c6964206172726179206c656e67746800006044820152606401610398565b5f5b85811015610d9157848181518110610cc757610cc7612846565b60200260200101515f03610d8957876001600160a01b031662fdd58e30898985818110610cf657610cf6612846565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401602060405180830381865afa158015610d46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d6a9190612891565b858281518110610d7c57610d7c612846565b6020026020010181815250505b600101610cad565b50604051631759616b60e11b81526001600160a01b03881690632eb2c2d690610dca90309085908b908b908b908b908b906004016128a8565b5f604051808303815f87803b158015610de1575f80fd5b505af1158015610df3573d5f803e3d5ffd5b5050505050505050505050565b5f546001600160a01b03163314610e295760405162461bcd60e51b8152600401610398906125a9565b5f5b82811015610b0d578160055f868685818110610e4957610e49612846565b9050602002016020810190610e5e91906121d0565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055811515848483818110610e9a57610e9a612846565b9050602002016020810190610eaf91906121d0565b6001600160a01b03167f43572750395348a3948322f95d3b0bf4773311c6c19ec9a575cde194e5bac21160405160405180910390a3600101610e2b565b5f546001600160a01b03163314610f155760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b038116610f3b5760405162461bcd60e51b81526004016103989061285a565b815f03610f4e57610f4b83611b29565b91505b811561102b5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03841603611017575f816001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610fc1576040519150601f19603f3d011682016040523d82523d5f602084013e610fc6565b606091505b5050905080610b0d5760405162461bcd60e51b815260206004820152601d60248201527f4b535265736375653a204554485f5452414e534645525f4641494c45440000006044820152606401610398565b61102b6001600160a01b0384168284611bd5565b505050565b5f546001600160a01b031633146110595760405162461bcd60e51b8152600401610398906125a9565b6001600160a01b0381166110be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610398565b6110c7816110fb565b50565b5f546001600160a01b031633146110f35760405162461bcd60e51b8152600401610398906125a9565b610436611c27565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f54600160a01b900460ff16156111965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610398565b5f805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111d03390565b6040516001600160a01b03909116815260200160405180910390a1565b60026003540361123f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610398565b6002600355565b6112536020830183612953565b905061125f8380612953565b905014801561128657506112766040830183612953565b90506112828380612953565b9050145b6112cc5760405162461bcd60e51b81526020600482015260176024820152765a6170526f757465723a20696e76616c6964206461746160481b6044820152606401610398565b34335f6112d98580612953565b90506001600160401b038111156112f2576112f26123c6565b60405190808252806020026020018201604052801561134257816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f199092019101816113105790505b5090505f805b6113528780612953565b90508110156116ad5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee61137a8880612953565b8381811061138a5761138a612846565b905060200201602081019061139f91906121d0565b6001600160a01b031603611432575f851180156113de57506113c46020880188612953565b828181106113d4576113d4612846565b9050602002013585145b61142a5760405162461bcd60e51b815260206004820152601c60248201527f5a6170526f757465723a20696e76616c6964206d73672076616c7565000000006044820152606401610398565b5f945061161a565b6114a58461144360408a018a612953565b8481811061145357611453612846565b90506020028101906114659190612633565b61146f8b80612953565b8681811061147f5761147f612846565b905060200201602081019061149491906121d0565b6001600160a01b0316929190611ca9565b806114de57506114b86040880188612953565b828181106114c8576114c8612846565b90506020028101906114da9190612633565b1590505b156115545761154f84876114f560208b018b612953565b8581811061150557611505612846565b602002919091013590506115198b80612953565b8681811061152957611529612846565b905060200201602081019061153e91906121d0565b6001600160a01b0316929190611cf6565b61161a565b6040518060800160405280856001600160a01b03168152602001876001600160a01b0316815260200188806020019061158d9190612953565b8481811061159d5761159d612846565b905060200201356001600160a01b0316815260200188805f01906115c19190612953565b848181106115d1576115d1612846565b90506020020160208101906115e691906121d0565b6001600160a01b0316905283836115fc816129ac565b94508151811061160e5761160e612846565b60200260200101819052505b6116276020880188612953565b8281811061163757611637612846565b6020029190910135905061164b8880612953565b8381811061165b5761165b612846565b905060200201602081019061167091906121d0565b6001600160a01b03167f542ffabdd5320a08598fbaa483210c5e34df4cfbd7f2541470a88d43c640311460405160405180910390a3600101611348565b5083156116fc5760405162461bcd60e51b815260206004820152601c60248201527f5a6170526f757465723a20696e76616c6964206d73672076616c7565000000006044820152606401610398565b8015611892575f6117106060880188612633565b90501115611815575f6001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba316632a2d80d160e01b61175860608a018a612633565b60405160200161176a939291906129c4565b60408051601f1981840301815290829052611784916129e7565b5f604051808303815f865af19150503d805f81146117bd576040519150601f19603f3d011682016040523d82523d5f602084013e6117c2565b606091505b50509050806118135760405162461bcd60e51b815260206004820181905260248201527f5a6170526f757465723a207065726d697432207065726d6974206661696c65646044820152606401610398565b505b808252604051630d58b1db60e01b81526001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31690630d58b1db906118649085906004016129fd565b5f604051808303815f87803b15801561187b575f80fd5b505af115801561188d573d5f803e3d5ffd5b505050505b505050505050565b6118a76020830183612953565b90506118b38380612953565b90501480156118da57506118ca6040830183612953565b90506118d68380612953565b9050145b6119205760405162461bcd60e51b81526020600482015260176024820152765a6170526f757465723a20696e76616c6964206461746160481b6044820152606401610398565b5f5b61192c8380612953565b905081101561102b576119ce6119456020850185612953565b8381811061195557611955612846565b9050602002013584806040019061196c9190612953565b8481811061197c5761197c612846565b905060200281019061198e9190612633565b6119988780612953565b868181106119a8576119a8612846565b90506020020160208101906119bd91906121d0565b6001600160a01b0316929190611d7c565b506119d98380612953565b828181106119e9576119e9612846565b90506020020160208101906119fe91906121d0565b6001600160a01b03166342842e0e3384611a1b6020880188612953565b86818110611a2b57611a2b612846565b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152949093166024850152506020909102013560448201526064015f604051808303815f87803b158015611a7f575f80fd5b505af1158015611a91573d5f803e3d5ffd5b50611aa3925050506020840184612953565b82818110611ab357611ab3612846565b60200291909101359050611ac78480612953565b83818110611ad757611ad7612846565b9050602002016020810190611aec91906121d0565b6001600160a01b03167fa6fb63d713a5a606436dc801f04dfdfd00d8e5211c54bc1332aeb047992c06f760405160405180910390a3600101611922565b5f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03831603611b55575047611bbe565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611b97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bbb9190612891565b90505b8015611bd057611bcd81612a74565b90505b919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261102b908490611dba565b5f54600160a01b900460ff16611c765760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610398565b5f805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336111d0565b5f60a0829003611cce57611cc7858563d505accf60e01b8686611e8b565b9050611cee565b60c0829003611ceb57611cc785856323f2ebc360e21b8686611e8b565b505f5b949350505050565b8015610b0d575f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af13d15601f3d1160015f511416171691505f81525f60208201525f60408201525f60608201525080610c0557610c05856323b872dd60e01b633c9fd93960e21b611f24565b5f6080829003611d9b57611cc78585637ac2ff7b60e01b86865f611f9c565b60e0829003611ceb57611cc78585630f5730f160e01b868660a0611f9c565b5f611e0e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120459092919063ffffffff16565b80519091501561102b5780806020019051810190611e2c91906127b5565b61102b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610398565b5f80611e98836044612a89565b6001600160401b03811115611eaf57611eaf6123c6565b6040519080825280601f01601f191660200182016040528015611ed9576020820181803683370190505b509050846020820152856024820152306044820152828460648301375f808251602084015f8b5af1915081611f1a57611f1a878663203aa5b560e11b611f24565b5095945050505050565b6040516390bfb86560e01b8082526001600160a01b03851660048301526001600160e01b031984166024830152608060448301526020601f3d018190040260a0810160648401523d608484015290913d5f60a483013e60048260a4018201526001600160e01b031984168260c4018201528160e40181fd5b5f80611fa9846044612a89565b6001600160401b03811115611fc057611fc06123c6565b6040519080825280601f01601f191660200182016040528015611fea576020820181803683370190505b5090508560208201523060248201528660448201528385606483013782156120155782600484018201525b5f808251602084015f8c5af191508161203a5761203a8887630efd078d60e11b611f24565b509695505050505050565b606061205384845f8561205d565b90505b9392505050565b6060824710156120be5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610398565b843b61210c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610398565b5f80866001600160a01b0316858760405161212791906129e7565b5f6040518083038185875af1925050503d805f8114612161576040519150601f19603f3d011682016040523d82523d5f602084013e612166565b606091505b5091509150612176828286612181565b979650505050505050565b60608315612190575081612056565b8251156121a05782518084602001fd5b8160405162461bcd60e51b815260040161039891906122bb565b80356001600160a01b0381168114611bd0575f80fd5b5f602082840312156121e0575f80fd5b612056826121ba565b80151581146110c7575f80fd5b5f8060408385031215612207575f80fd5b612210836121ba565b91506020830135612220816121e9565b809150509250929050565b5f806040838503121561223c575f80fd5b82356001600160401b03811115612251575f80fd5b830160808186031215612262575f80fd5b915060208301356001600160401b0381111561227c575f80fd5b830160a08186031215612220575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f612056602083018461228d565b5f8083601f8401126122dd575f80fd5b5081356001600160401b038111156122f3575f80fd5b6020830191508360208260051b850101111561230d575f80fd5b9250929050565b5f805f60408486031215612326575f80fd5b83356001600160401b0381111561233b575f80fd5b612347868287016122cd565b909450925050602084013561235b816121e9565b809150509250925092565b5f805f8060608587031215612379575f80fd5b612382856121ba565b935060208501356001600160401b0381111561239c575f80fd5b6123a8878288016122cd565b90945092506123bb9050604086016121ba565b905092959194509250565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612402576124026123c6565b604052919050565b5f8083601f84011261241a575f80fd5b5081356001600160401b03811115612430575f80fd5b60208301915083602082850101111561230d575f80fd5b5f805f805f805f60a0888a03121561245d575f80fd5b612466886121ba565b965060208801356001600160401b03811115612480575f80fd5b61248c8a828b016122cd565b90975095505060408801356001600160401b038111156124aa575f80fd5b8801601f81018a136124ba575f80fd5b80356001600160401b038111156124d3576124d36123c6565b8060051b6124e3602082016123da565b9182526020818401810192908101908d8411156124fe575f80fd5b6020850194505b8385101561252457843580835260209586019590935090910190612505565b9750505050606089013590506001600160401b03811115612543575f80fd5b61254f8a828b0161240a565b90945092506125629050608089016121ba565b905092959891949750929550565b5f805f60608486031215612582575f80fd5b61258b846121ba565b9250602084013591506125a0604085016121ba565b90509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b5f602082840312156125ee575f80fd5b813563ffffffff81168114612056575f80fd5b5f8235607e19833603018112612615575f80fd5b9190910192915050565b5f8235605e19833603018112612615575f80fd5b5f808335601e19843603018112612648575f80fd5b8301803591506001600160401b03821115612661575f80fd5b60200191503681900382131561230d575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60ff84168152604060208201525f6126b9604083018486612675565b95945050505050565b5f602082840312156126d2575f80fd5b81516001600160401b038111156126e7575f80fd5b8201601f810184136126f7575f80fd5b80516001600160401b03811115612710576127106123c6565b612723601f8201601f19166020016123da565b818152856020838501011115612737575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b602081525f612053602083018486612675565b60ff86168152608060208201525f612783608083018688612675565b8281036040840152612795818661228d565b905082810360608401526127a9818561228d565b98975050505050505050565b5f602082840312156127c5575f80fd5b8151612056816121e9565b6001600160a01b0389811682528816602082015260c0604082018190525f906127fc908301888a612675565b828103606084015261280f818789612675565b90508281036080840152612823818661228d565b905082810360a0840152612837818561228d565b9b9a5050505050505050505050565b634e487b7160e01b5f52603260045260245ffd5b6020808252601b908201527f4b535265736375653a20696e76616c696420726563697069656e740000000000604082015260600190565b5f602082840312156128a1575f80fd5b5051919050565b6001600160a01b0388811682528716602082015260a06040820181905281018590525f6001600160fb1b038611156128de575f80fd5b8560051b808860c085013760c090830183810382016060850152865191810182905260208701915f9160e001905b8083101561292f578351825260208201915060208401935060018301925061290c565b508481036080860152612943818789612675565b9c9b505050505050505050505050565b5f808335601e19843603018112612968575f80fd5b8301803591506001600160401b03821115612981575f80fd5b6020019150600581901b360382131561230d575f80fd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016129bd576129bd612998565b5060010190565b6001600160e01b031984168152818360048301375f910160040190815292915050565b5f82518060208501845e5f920191825250919050565b602080825282518282018190525f918401906040840190835b81811015612a6957835180516001600160a01b0390811685526020808301518216818701526040808401518316908701526060928301519091169185019190915290930192608090920191600101612a16565b509095945050505050565b5f81612a8257612a82612998565b505f190190565b80820180821115610a1b57610a1b61299856fea264697066735822122073164cba18e7287230affb12454056d4d2ff647cb680dffc4d6373f03ca1371f64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
-----Decoded View---------------
Arg [0] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1.01
Net Worth in ETH
0.000522
Token Allocations
CRVFRAX
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $1.01 | 1 | $1.01 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.