Source Code
Latest 25 from a total of 254 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Zap | 426657665 | 23 hrs ago | IN | 0.00032361 ETH | 0.0000391 | ||||
| Zap | 426132799 | 2 days ago | IN | 0.001 ETH | 0.00002181 | ||||
| Zap | 424632144 | 6 days ago | IN | 0.0002 ETH | 0.00000654 | ||||
| Zap | 424008459 | 8 days ago | IN | 0 ETH | 0.00001192 | ||||
| Zap | 424008330 | 8 days ago | IN | 0 ETH | 0.00001183 | ||||
| Zap | 424008242 | 8 days ago | IN | 0 ETH | 0.00000752 | ||||
| Zap | 424007956 | 8 days ago | IN | 0 ETH | 0.0000119 | ||||
| Zap | 424007535 | 8 days ago | IN | 0 ETH | 0.00001073 | ||||
| Zap | 424006102 | 8 days ago | IN | 0 ETH | 0.0000096 | ||||
| Zap | 424005882 | 8 days ago | IN | 0 ETH | 0.00001207 | ||||
| Zap | 423698519 | 9 days ago | IN | 0 ETH | 0.00001269 | ||||
| Zap | 423658245 | 9 days ago | IN | 0.0002 ETH | 0.00000542 | ||||
| Zap | 423590223 | 9 days ago | IN | 0.0002 ETH | 0.00001101 | ||||
| Zap | 423357673 | 10 days ago | IN | 0.0002 ETH | 0.00000627 | ||||
| Zap | 423252211 | 10 days ago | IN | 0.0002 ETH | 0.00000469 | ||||
| Zap | 422984755 | 11 days ago | IN | 0.0002 ETH | 0.0000047 | ||||
| Zap | 422962374 | 11 days ago | IN | 0 ETH | 0.00001309 | ||||
| Zap | 422929343 | 11 days ago | IN | 0.0002 ETH | 0.0000047 | ||||
| Zap | 422900416 | 11 days ago | IN | 0.0002 ETH | 0.00000471 | ||||
| Zap | 422899357 | 11 days ago | IN | 0 ETH | 0.00003476 | ||||
| Zap | 422647284 | 12 days ago | IN | 0 ETH | 0.00002205 | ||||
| Zap | 422646417 | 12 days ago | IN | 0 ETH | 0.000009 | ||||
| Zap | 422645470 | 12 days ago | IN | 0 ETH | 0.00001406 | ||||
| Zap | 421889113 | 14 days ago | IN | 0.0002 ETH | 0.00002698 | ||||
| Zap | 419888153 | 20 days ago | IN | 0 ETH | 0.00002073 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 426657665 | 23 hrs ago | 3 wei | ||||
| 426657665 | 23 hrs ago | 0.00000032 ETH | ||||
| 426657665 | 23 hrs ago | 0.00032329 ETH | ||||
| 426132799 | 2 days ago | 0 ETH | ||||
| 426132799 | 2 days ago | 0.000001 ETH | ||||
| 426132799 | 2 days ago | 0.00099899 ETH | ||||
| 424632144 | 6 days ago | 0.0002 ETH | ||||
| 423658245 | 9 days ago | 0.0002 ETH | ||||
| 423590223 | 9 days ago | 0.0002 ETH | ||||
| 423358937 | 10 days ago | 0.00008001 ETH | ||||
| 423358937 | 10 days ago | 0.00008001 ETH | ||||
| 423357673 | 10 days ago | 0.0002 ETH | ||||
| 423252211 | 10 days ago | 0.0002 ETH | ||||
| 422984755 | 11 days ago | 0.0002 ETH | ||||
| 422929343 | 11 days ago | 0.0002 ETH | ||||
| 422900416 | 11 days ago | 0.0002 ETH | ||||
| 421889113 | 14 days ago | 0.00000038 ETH | ||||
| 421889113 | 14 days ago | 0.0003942 ETH | ||||
| 421889113 | 14 days ago | 0.00006441 ETH | ||||
| 421889113 | 14 days ago | 0.00007978 ETH | ||||
| 421889113 | 14 days ago | 0.0000504 ETH | ||||
| 418837902 | 23 days ago | 0.00007536 ETH | ||||
| 418837902 | 23 days ago | 0.00007536 ETH | ||||
| 418832313 | 23 days ago | 0.0000001 ETH | ||||
| 418832313 | 23 days ago | 0.0000999 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DZapZapCore
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 300 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { LibAsset } from "../shared/libraries/LibAsset.sol";
import { LibPermit } from "../shared/libraries/LibPermit.sol";
import { IDZapZapCore } from "../interfaces/IDZapZapCore.sol";
import { PermitBatchTransferFrom } from "../interfaces/IPermit2.sol";
import { DZapCoreBase } from "./DZapCoreBase.sol";
import { DZapExecution } from "./DZapExecution.sol";
import { FeeConfig, ZapData, InputErc20Tokens, TokenInfo } from "./Types.sol";
import { DustReceiverIsZeroAddress, IntegratorIsZeroAddress } from "./Errors.sol";
/*
---------------------------------------------------------
---------------------------------------------------------
/$$$$$$$ /$$$$$$$$ /$$$$$$ /$$$$$$$
| $$__ $$|_____ $$ /$$__ $$| $$__ $$
| $$ \ $$ /$$/ | $$ \ $$| $$ \ $$
| $$ | $$ /$$/ | $$$$$$$$| $$$$$$$/
| $$ | $$ /$$/ | $$__ $$| $$____/
| $$ | $$ /$$/ | $$ | $$| $$
| $$$$$$$/ /$$$$$$$$| $$ | $$| $$
|_______/ |________/|__/ |__/|__/
Author: DZap <https://dzap.io> (https://x.com/dzap_io)
---------------------------------------------------------
---------------------------------------------------------
*/
/// @title DZapZapCore
/// @notice Main contract for executing zap transactions across protocols
/// @dev Inherits from modular abstract contracts for clean separation of concerns
contract DZapZapCore is ReentrancyGuard, DZapExecution, IDZapZapCore {
// ============= CONSTRUCTOR =============
/// @param _owner Owner of the contract
/// @param _protocolFeeVault Address where protocol fees are sent
/// @param _zapVerifier Address of the zap verifier
/// @param _permit2 Address of the permit2 contract
/// @param _uniswapPermit2 Address of the uniswap permit2 contract
/// @param _uniswapPermit2BytecodeHash Hash of the uniswap permit2 bytecode
/// @param _salt Random salt for contract creation
constructor(
address _owner,
address _protocolFeeVault,
address _zapVerifier,
address _permit2,
address _uniswapPermit2,
bytes32 _uniswapPermit2BytecodeHash,
bytes32 _salt
) DZapCoreBase(_owner, _protocolFeeVault, _zapVerifier, _permit2, _uniswapPermit2, _uniswapPermit2BytecodeHash, _salt) {}
// ============= EXTERNAL FUNCTIONS =============
/// @inheritdoc IDZapZapCore
function zap(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
uint256 _deadline,
address _dustReceiver,
InputErc20Tokens[] calldata _inputTokens,
FeeConfig calldata _feeConfig,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable nonReentrant whenNotPaused refundExcessNative(_dustReceiver) {
require(_dustReceiver != address(0), DustReceiverIsZeroAddress());
require(_feeConfig.integrator != address(0), IntegratorIsZeroAddress());
bytes32 zapDataHash = keccak256(abi.encode(_zapData));
bytes32 feeDataHash = keccak256(abi.encode(_feeConfig));
_handleZapVerification(_transactionId, zapDataHash, feeDataHash, msg.sender, _deadline, _zapVerificationSignature);
LibAsset.depositBatch(permit2, msg.sender, _inputTokens);
_handleZap(_zapData, msg.sender);
_processFee(_feeConfig);
_handleSweepTokens(_sweepDust, _dustReceiver);
emit Zapped(_transactionId, msg.sender, _feeConfig.integrator, _crosschainData);
}
/// @inheritdoc IDZapZapCore
function zapWithBatchDeposit(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
bytes calldata _batchDepositSignature,
uint256 _deadline,
address _dustReceiver,
PermitBatchTransferFrom calldata _tokenDepositDetails,
FeeConfig calldata _feeConfig,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable nonReentrant whenNotPaused refundExcessNative(_dustReceiver) {
require(_dustReceiver != address(0), DustReceiverIsZeroAddress());
require(_feeConfig.integrator != address(0), IntegratorIsZeroAddress());
bytes32 zapDataHash = keccak256(abi.encode(_zapData));
bytes32 feeDataHash = keccak256(abi.encode(_feeConfig));
_handleZapVerification(_transactionId, zapDataHash, feeDataHash, msg.sender, _deadline, _zapVerificationSignature);
LibAsset.depositBatch(permit2, msg.sender, _tokenDepositDetails, _batchDepositSignature);
_handleZap(_zapData, msg.sender);
_processFee(_feeConfig);
_handleSweepTokens(_sweepDust, _dustReceiver);
emit Zapped(_transactionId, msg.sender, _feeConfig.integrator, _crosschainData);
}
/// @inheritdoc IDZapZapCore
function executeZap(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
bytes calldata _userIntentSignature,
uint256 _zapDeadline,
uint256 _userIntentDeadline,
address _user,
address _dustReceiver,
InputErc20Tokens[] calldata _inputTokens,
FeeConfig calldata _feeConfig,
TokenInfo[] calldata _executorFeeInfo,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable nonReentrant whenNotPaused refundExcessNative(_dustReceiver) {
require(_dustReceiver != address(0), DustReceiverIsZeroAddress());
require(_feeConfig.integrator != address(0), IntegratorIsZeroAddress());
bytes32 zapDataHash = keccak256(abi.encode(_zapData));
bytes32 feeDataHash = keccak256(abi.encode(_feeConfig));
_handleZapVerification(_transactionId, zapDataHash, feeDataHash, _user, _zapDeadline, _zapVerificationSignature);
_handleGaslessVerification(
_transactionId,
zapDataHash,
feeDataHash,
keccak256(abi.encode(_executorFeeInfo)),
keccak256(_crosschainData),
keccak256(abi.encode(_sweepDust)),
_user,
_dustReceiver,
_userIntentDeadline,
_userIntentSignature
);
LibAsset.depositBatch(permit2, _user, _inputTokens);
_handleZap(_zapData, _user);
_processFee(_feeConfig);
_transferExecutorFees(_executorFeeInfo);
_handleSweepTokens(_sweepDust, _dustReceiver);
emit GaslessZapped(_transactionId, msg.sender, _user, _feeConfig.integrator, _crosschainData);
}
/// @inheritdoc IDZapZapCore
function executeZapWithWitness(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
bytes calldata _userIntentSignature,
uint256 _zapDeadline,
address _user,
address _dustReceiver,
PermitBatchTransferFrom calldata _tokenDepositDetails,
FeeConfig calldata _feeConfig,
TokenInfo[] calldata _executorFeeInfo,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable nonReentrant whenNotPaused refundExcessNative(_dustReceiver) {
require(_dustReceiver != address(0), DustReceiverIsZeroAddress());
require(_feeConfig.integrator != address(0), IntegratorIsZeroAddress());
bytes32 zapDataHash = keccak256(abi.encode(_zapData));
bytes32 feeDataHash = keccak256(abi.encode(_feeConfig));
_handleZapVerification(_transactionId, zapDataHash, feeDataHash, _user, _zapDeadline, _zapVerificationSignature);
bytes32 witness = keccak256(
abi.encode(
_GASLESS_WITNESS_TYPEHASH,
_transactionId,
_user,
_dustReceiver,
zapDataHash,
feeDataHash,
keccak256(abi.encode(_executorFeeInfo)),
keccak256(_crosschainData),
keccak256(abi.encode(_sweepDust))
)
);
LibPermit.permit2BatchWitnessTransferFrom(
permit2,
_user,
address(this),
witness,
_tokenDepositDetails,
_userIntentSignature,
_GASLESS_WITNESS_TYPE_STRING
);
_handleZap(_zapData, _user);
_processFee(_feeConfig);
_transferExecutorFees(_executorFeeInfo);
_handleSweepTokens(_sweepDust, _dustReceiver);
emit GaslessZapped(_transactionId, msg.sender, _user, _feeConfig.integrator, _crosschainData);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// 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
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC-1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[ERC].
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` amount of tokens of 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 value of tokens of token type `id` owned by `account`.
*/
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 zero address.
*/
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 a `value` amount of tokens of type `id` from `from` to `to`.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155Received} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* 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 `value` 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 value, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
*
* Requirements:
*
* - `ids` and `values` 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 values,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC-1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC-1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.20;
import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
import {IERC1155Receiver} from "../IERC1155Receiver.sol";
/**
* @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*/
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// 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.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
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 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 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. 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.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @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).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @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).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC-721 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 ERC-721 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 ERC-721
* 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 address zero.
*
* 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
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
* {IERC721-setApprovalForAll}.
*/
abstract contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) private pure {
// 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 ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(
bytes32 hash,
bytes memory signature
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly ("memory-safe") {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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 {
bool private _paused;
/**
* @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);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @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
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @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 EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* 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;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
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
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// 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
pragma solidity 0.8.30;
import { InputErc20Tokens, FeeConfig, ZapData, TokenInfo } from "../zap/Types.sol";
import { PermitBatchTransferFrom } from "../interfaces/IPermit2.sol";
interface IDZapZapCore {
// ============= EXTERNAL FUNCTIONS =============
/// @notice Executes a zap with individual token permits
/// @param _transactionId Unique transaction identifier
/// @param _crosschainData Additional crosschain data
/// @param _zapVerificationSignature Verifier signature for zap authorization
/// @param _deadline Signature expiration timestamp
/// @param _dustReceiver Address to receive leftover tokens
/// @param _inputTokens Input tokens with permit data
/// @param _feeConfig Fee distribution configuration
/// @param _zapData Array of zap execution data
/// @param _sweepDust Token addresses to sweep as dust
function zap(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
uint256 _deadline,
address _dustReceiver,
InputErc20Tokens[] calldata _inputTokens,
FeeConfig calldata _feeConfig,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable;
/// @notice Executes a zap with batch permit2 transfer
/// @param _transactionId Unique transaction identifier
/// @param _crosschainData Additional crosschain data
/// @param _zapVerificationSignature Verifier signature for zap authorization
/// @param _batchDepositSignature User signature for batch transfer
/// @param _deadline Signature expiration timestamp
/// @param _dustReceiver Address to receive leftover tokens
/// @param _tokenDepositDetails Batch transfer permit details
/// @param _feeConfig Fee distribution configuration
/// @param _zapData Array of zap execution data
/// @param _sweepDust Token addresses to sweep as dust
function zapWithBatchDeposit(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
bytes calldata _batchDepositSignature,
uint256 _deadline,
address _dustReceiver,
PermitBatchTransferFrom calldata _tokenDepositDetails,
FeeConfig calldata _feeConfig,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable;
/// @notice Executes a zap with individual token permits
/// @param _transactionId Unique transaction identifier
/// @param _crosschainData Additional crosschain data
/// @param _zapVerificationSignature Verifier signature for zap authorization
/// @param _userIntentSignature User's intent signature
/// @param _zapDeadline Zap deadline
/// @param _userIntentDeadline User intent deadline
/// @param _user User address
/// @param _dustReceiver Address to receive leftover tokens
/// @param _inputTokens Input tokens with permit data
/// @param _feeConfig Fee distribution configuration
/// @param _executorFeeInfo Executor fee information
/// @param _zapData Array of zap execution data
/// @param _sweepDust Token addresses to sweep as dust
function executeZap(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
bytes calldata _userIntentSignature,
uint256 _zapDeadline,
uint256 _userIntentDeadline,
address _user,
address _dustReceiver,
InputErc20Tokens[] calldata _inputTokens,
FeeConfig calldata _feeConfig,
TokenInfo[] calldata _executorFeeInfo,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable;
/// @notice Executes a gasless zap on behalf of a user (with batch permit2)
/// @param _transactionId Unique transaction identifier
/// @param _crosschainData Additional crosschain data
/// @param _zapVerificationSignature Verifier signature for zap authorization
/// @param _userIntentSignature User's signature for gasless execution
/// @param _zapDeadline Zap verification signature deadline
/// @param _user User address on whose behalf the zap is executed
/// @param _dustReceiver Address to receive leftover tokens
/// @param _tokenDepositDetails Batch transfer permit details
/// @param _feeConfig Fee distribution configuration
/// @param _executorFeeInfo Executor fee information
/// @param _zapData Array of zap execution data
/// @param _sweepDust Token addresses to sweep as dust
function executeZapWithWitness(
bytes32 _transactionId,
bytes calldata _crosschainData,
bytes calldata _zapVerificationSignature,
bytes calldata _userIntentSignature,
uint256 _zapDeadline,
address _user,
address _dustReceiver,
PermitBatchTransferFrom calldata _tokenDepositDetails,
FeeConfig calldata _feeConfig,
TokenInfo[] calldata _executorFeeInfo,
ZapData[] calldata _zapData,
address[] calldata _sweepDust
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
struct PermitDetails {
address token;
uint160 amount;
uint48 expiration;
uint48 nonce;
}
struct PermitSingle {
PermitDetails details;
address spender;
uint256 sigDeadline;
}
struct TokenPermissions {
address token;
uint256 amount;
}
struct PermitTransferFrom {
TokenPermissions permitted;
uint256 nonce;
uint256 deadline;
}
struct SignatureTransferDetails {
address to;
uint256 requestedAmount;
}
struct PermitBatchTransferFrom {
// the tokens and corresponding amounts permitted for a transfer
TokenPermissions[] permitted;
// a unique value for every token owner's signature to prevent signature replays
uint256 nonce;
// deadline on the permit signature
uint256 deadline;
}
interface IPermit2 {
function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;
function approve(address token, address spender, uint160 amount, uint48 deadline) external;
function transferFrom(address from, address to, uint160 amount, address token) external;
function allowance(address owner, address token, address spender) external view returns (uint160, uint48, uint48);
function permitWitnessTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
function permitWitnessTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { IPermit2, PermitBatchTransferFrom } from "../../interfaces/IPermit2.sol";
import { InputErc20Tokens, PermitType } from "../../zap/Types.sol";
import { LibPermit } from "./LibPermit.sol";
/**
* @title LibAsset
* @author DZap
* @notice This library contains helpers for dealing with onchain transfers
* of assets, including accounting for the native asset `assetId`
* conventions and any noncompliant ERC20 transfers
*/
library LibAsset {
using SafeERC20 for IERC20;
// ============= ERRORS =============
error NativeTransferFailed();
error NoTransferToNullAddress();
error NullAddrIsNotAValidSpender();
error InvalidAmount();
error InvalidPermitType();
// ============= CONSTANTS =============
address internal constant _NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// ============= BALANCE QUERY FUNCTIONS =============
function selfNativeBalance() internal view returns (uint256 contractBalance) {
assembly {
contractBalance := selfbalance()
}
}
function getErc20Balance(address _token, address _account) internal view returns (uint256) {
return IERC20(_token).balanceOf(_account);
}
function getBalance(address _token, address _account) internal view returns (uint256) {
return _token == _NATIVE_TOKEN ? _account.balance : IERC20(_token).balanceOf(_account);
}
function getNativeBalance(address _account) internal view returns (uint256) {
return _account.balance;
}
function getOwnerOfERC721(address _token, uint256 _id) internal view returns (address) {
return IERC721(_token).ownerOf(_id);
}
function getBalanceOfERC1155(address _token, address _account, uint256 _id) internal view returns (uint256) {
return IERC1155(_token).balanceOf(_account, _id);
}
// ============= TRANSFER FUNCTIONS =============
function transferToken(address _token, address _to, uint256 _amount) internal {
if (_token == _NATIVE_TOKEN) transferNativeToken(_to, _amount);
else transferERC20(_token, _to, _amount);
}
function transferNativeToken(address _to, uint256 _amount) internal {
if (_amount == 0) return;
require(_to != address(0), NoTransferToNullAddress());
(bool success, ) = _to.call{ value: _amount }("");
require(success, NativeTransferFailed());
}
function transferERC20(address _token, address _to, uint256 _amount) internal {
if (_amount == 0) return;
require(_to != address(0), NoTransferToNullAddress());
IERC20(_token).safeTransfer(_to, _amount);
}
function transferERC20WithoutChecks(address _token, address _to, uint256 _amount) internal {
IERC20(_token).safeTransfer(_to, _amount);
}
function transferFromERC20(address _token, address _from, address _to, uint256 _amount) internal {
IERC20(_token).safeTransferFrom(_from, _to, _amount);
}
function transferERC721(address _token, address _to, uint256 _id) internal {
IERC721(_token).safeTransferFrom(address(this), _to, _id);
}
function transferERC721(address _token, address _from, address _to, uint256 _id) internal {
IERC721(_token).safeTransferFrom(_from, _to, _id);
}
function transferBatchERC1155(address _token, address _to, uint256[] memory _ids, uint256[] memory _amounts) internal {
IERC1155(_token).safeBatchTransferFrom(address(this), _to, _ids, _amounts, "");
}
function transferERC1155(address _token, address _from, address _to, uint256 _id, uint256 _amount) internal {
IERC1155(_token).safeTransferFrom(_from, _to, _id, _amount, "");
}
// ============= APPROVAL FUNCTIONS =============
/// @notice If the current allowance is insufficient, then MAX_UINT allowance for a given spender
function maxApproveERC20(address _token, address _spender, uint256 _amount) internal {
require(_spender != address(this), NullAddrIsNotAValidSpender());
uint256 allowance = IERC20(_token).allowance(address(this), _spender);
if (allowance < _amount) {
SafeERC20.forceApprove(IERC20(_token), _spender, type(uint256).max);
}
}
function maxPermit2Approve(address _permit2, address _token, address _spender, uint256 _amount) internal {
require(_spender != address(0), NullAddrIsNotAValidSpender());
(uint160 allowance, uint48 expiration, ) = IPermit2(_permit2).allowance(address(this), _token, _spender);
if (allowance < _amount || block.timestamp > expiration) {
IPermit2(_permit2).approve(_token, _spender, type(uint160).max, type(uint48).max);
}
maxApproveERC20(_token, _permit2, _amount);
}
function approveERC721(address _token, address _to, uint256 _tokenId) internal {
require(_to != address(0), NullAddrIsNotAValidSpender());
IERC721(_token).approve(_to, _tokenId);
}
function approveERC1155(address _token, address _spender) internal {
IERC1155(_token).setApprovalForAll(_spender, true);
}
function isErc1155ApprovedForAll(address _token, address _operator, address _spender) internal view returns (bool) {
return IERC1155(_token).isApprovedForAll(_operator, _spender);
}
function revokeERC1155(address _token, address _spender) internal {
IERC1155(_token).setApprovalForAll(_spender, false);
}
// ============= DEPOSIT FUNCTIONS =============
/// @notice Deposits tokens from a sender to the inheriting contract
/// @dev only handles erc20 token
function depositErc20(address _permit2, address _user, address _token, uint256 _amount, bytes calldata _permit) internal {
(PermitType permitType, bytes memory data) = abi.decode(_permit, (PermitType, bytes));
if (permitType == PermitType.PERMIT2_WITNESS_TRANSFER) {
LibPermit.permit2WitnessTransferFrom(_permit2, _user, address(this), _token, _amount, data);
} else if (permitType == PermitType.PERMIT) {
if (data.length != 0) LibPermit.eip2612Permit(_user, address(this), _token, _amount, data);
transferFromERC20(_token, _user, address(this), _amount);
} else if (permitType == PermitType.PERMIT2_APPROVE) {
LibPermit.permit2ApproveAndTransfer(_permit2, _user, address(this), _token, uint160(_amount), data);
} else {
revert InvalidPermitType();
}
}
function depositBatch(address _permit2, address _user, InputErc20Tokens[] calldata erc20Tokens) internal {
uint256 length = erc20Tokens.length;
for (uint256 i; i < length; ++i) {
depositErc20(_permit2, _user, erc20Tokens[i].token, erc20Tokens[i].amount, erc20Tokens[i].permit);
}
}
function depositBatch(address _permit2, address _user, PermitBatchTransferFrom calldata permit, bytes calldata permitSignature) internal {
LibPermit.permit2BatchWitnessTransferFrom(_permit2, _user, address(this), permit, permitSignature);
}
// ============= UTILITY FUNCTIONS =============
/// @notice Determines whether the given token is the native token
function isNativeToken(address _token) internal pure returns (bool) {
return _token == _NATIVE_TOKEN;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { IERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import { PermitTransferFrom, PermitBatchTransferFrom, SignatureTransferDetails, PermitSingle, PermitDetails, TokenPermissions, IPermit2 } from "../../interfaces/IPermit2.sol";
/**
* @title LibPermit
* @author DZap
* @notice This library contains helpers for using permit and permit2
*/
library LibPermit {
// ============= ERRORS =============
error InvalidPermit(string reason);
// ============= CONSTANTS =============
string internal constant _DZAP_TRANSFER_WITNESS_TYPE_STRING =
"DZapTransferWitness witness)DZapTransferWitness(address owner,address recipient)TokenPermissions(address token,uint256 amount)";
bytes32 internal constant _DZAP_TRANSFER_WITNESS_TYPEHASH = keccak256("DZapTransferWitness(address owner,address recipient)");
// ============= EIP-2612 PERMIT FUNCTIONS =============
/// @notice Handles eip2612 permit
function eip2612Permit(address _owner, address _spender, address _token, uint256 _amount, bytes memory _data) internal {
(uint256 deadline, uint8 v, bytes32 r, bytes32 s) = abi.decode(_data, (uint256, uint8, bytes32, bytes32));
IERC20Permit(_token).permit(_owner, _spender, _amount, deadline, v, r, s);
}
// ============= PERMIT2 FUNCTIONS =============
/// @notice Handles permit2 approve and transfer
function permit2ApproveAndTransfer(address _permit2, address _from, address _to, address _token, uint160 _amount, bytes memory data) internal {
permit2Approve(_permit2, _from, _to, _token, _amount, data);
IPermit2(_permit2).transferFrom(_from, _to, uint160(_amount), _token);
}
/// @notice Handles permit2 approve
function permit2Approve(address _permit2, address _owner, address _spender, address _token, uint160 _amount, bytes memory _data) internal {
if (_data.length == 0) return;
IPermit2 permit2Contract = IPermit2(_permit2);
(uint48 nonce, uint48 expiration, uint256 sigDeadline, bytes memory signature) = abi.decode(_data, (uint48, uint48, uint256, bytes));
try
permit2Contract.permit(_owner, PermitSingle(PermitDetails(_token, _amount, expiration, nonce), _spender, sigDeadline), signature)
{} catch Error(string memory reason) {
(uint256 currentAllowance, uint256 allowanceExpiration, ) = permit2Contract.allowance(_owner, _token, _spender);
require(currentAllowance >= _amount && allowanceExpiration >= block.timestamp, InvalidPermit(reason));
}
}
/// @notice Handles permit2 witness transfer from
function permit2WitnessTransferFrom(
address _permit2,
address _owner,
address _recipient,
address _token,
uint256 _amount,
bytes memory _data
) internal {
(uint256 nonce, uint256 deadline, bytes memory _signature) = abi.decode(_data, (uint256, uint256, bytes));
IPermit2(_permit2).permitWitnessTransferFrom(
PermitTransferFrom(TokenPermissions(_token, _amount), nonce, deadline),
SignatureTransferDetails(_recipient, _amount),
_owner,
_createWitnessTransferFromHash(_owner, _recipient),
_DZAP_TRANSFER_WITNESS_TYPE_STRING,
_signature
);
}
/// @notice Handles permit2 batch witness transfer from
function permit2BatchWitnessTransferFrom(
address _permit2,
address _owner,
address _recipient,
PermitBatchTransferFrom calldata permit,
bytes calldata _signature
) internal {
uint256 length = permit.permitted.length;
SignatureTransferDetails[] memory details = new SignatureTransferDetails[](length);
for (uint256 i; i < length; ++i) {
details[i] = SignatureTransferDetails(_recipient, permit.permitted[i].amount);
}
IPermit2(_permit2).permitWitnessTransferFrom(
permit,
details,
_owner,
_createWitnessTransferFromHash(_owner, _recipient),
_DZAP_TRANSFER_WITNESS_TYPE_STRING,
_signature
);
}
/// @notice Handles permit2 batch witness transfer from
function permit2BatchWitnessTransferFrom(
address _permit2,
address _owner,
address _recipient,
bytes32 _witness,
PermitBatchTransferFrom calldata permit,
bytes calldata _signature,
string memory _witnessTypeString
) internal {
uint256 length = permit.permitted.length;
SignatureTransferDetails[] memory details = new SignatureTransferDetails[](length);
for (uint256 i; i < length; ++i) {
details[i] = SignatureTransferDetails(_recipient, permit.permitted[i].amount);
}
IPermit2(_permit2).permitWitnessTransferFrom(permit, details, _owner, _witness, _witnessTypeString, _signature);
}
/* ========= PRIVATE ========= */
function _createWitnessTransferFromHash(address _owner, address _recipient) private pure returns (bytes32) {
return keccak256(abi.encode(_DZAP_TRANSFER_WITNESS_TYPEHASH, _owner, _recipient));
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { LibAsset } from "../shared/libraries/LibAsset.sol";
import { DZapCoreBase } from "./DZapCoreBase.sol";
import { InvalidProtocolFeeVault, ZeroAddress, NoTransferToNullAddress, UniswapPermit2AlreadySet, UniswapPermit2ByteCodeMismatch, ProtectedSelector } from "./Errors.sol";
/// @title DZapAdmin
/// @author DZap
/// @notice Abstract contract containing all administrative functions
/// @dev Provides gas-optimized admin operations for contract management
abstract contract DZapAdmin is DZapCoreBase, Pausable {
// ============= PROTOCOL CONFIGURATION =============
/// @notice Updates protocol fee vault address
/// @param _protocolFeeVault New protocol fee vault address
function setProtocolFeeVault(address _protocolFeeVault) external onlyOwner {
require(_protocolFeeVault != address(0) && _protocolFeeVault != address(this), InvalidProtocolFeeVault());
protocolFeeVault = _protocolFeeVault;
emit ProtocolFeeVaultSet(_protocolFeeVault);
}
/// @notice Updates zap verifier address
/// @param _verifier New verifier address
function setVerifier(address _verifier) external onlyOwner {
require(_verifier != address(0), ZeroAddress());
zapVerifier = _verifier;
emit ZapVerifierSet(_verifier);
}
/// @notice Updates to Uniswap Permit2 if bytecode matches expected hash
function updateToUniswapPermit2() external onlyOwnerOrAdmin {
require(permit2 != UNISWAP_PERMIT2, UniswapPermit2AlreadySet());
require(keccak256(UNISWAP_PERMIT2.code) == EXPECTED_PERMIT2_RUNTIME_HASH, UniswapPermit2ByteCodeMismatch());
permit2 = UNISWAP_PERMIT2;
emit Permit2Updated();
}
// ============= ADMIN MANAGEMENT =============
/// @notice Adds an address as an admin
/// @param _account Address to add as admin
function addAdmin(address _account) external onlyOwner {
admins[_account] = true;
emit AdminAdded(_account);
}
/// @notice Removes an address from admin role
/// @param _account Address to remove from admin
function removeAdmin(address _account) external onlyOwner {
admins[_account] = false;
emit AdminRemoved(_account);
}
// ============= WHITELIST MANAGEMENT =============
/// @notice Updates adapter whitelist status for multiple addresses
/// @param _adapters Array of adapter addresses to update
/// @param _whitelisted Whether adapters should be whitelisted
function whitelistAdapters(address[] calldata _adapters, bool _whitelisted) external onlyOwner {
uint256 length = _adapters.length;
for (uint256 i; i < length; ++i) {
address adapter = _adapters[i];
require(adapter != address(0), ZeroAddress());
_adaptersAllowlist[adapter] = _whitelisted;
}
emit AdaptersWhitelistingUpdated(_adapters, _whitelisted);
}
/// @notice Updates ERC1155 spender whitelist status for multiple addresses
/// @param _spenders Array of spender addresses to update
/// @param _whitelisted Whether spenders should be whitelisted
function whitelistErc1155Spender(address[] calldata _spenders, bool _whitelisted) external onlyOwner {
uint256 length = _spenders.length;
for (uint256 i; i < length; ++i) {
address spender = _spenders[i];
require(spender != address(0), ZeroAddress());
_allowedErc1155Spender[spender] = _whitelisted;
}
emit Erc1155SpenderWhitelistingUpdated(_spenders, _whitelisted);
}
/// @notice Blocks multiple selectors
/// @param _selectors Array of selectors to block
function blockSelectors(bytes4[] calldata _selectors) external onlyOwner {
uint256 length = _selectors.length;
for (uint256 i; i < length; ++i) {
bytes4 selector = _selectors[i];
blockedSelectors[selector] = true;
}
emit SelectorsBlacklistingUpdated(_selectors, true);
}
/// @notice Unblocks multiple selectors
/// @param _selectors Array of selectors to unblock
function unblockSelectors(bytes4[] calldata _selectors) external onlyOwner {
uint256 length = _selectors.length;
for (uint256 i; i < length; ++i) {
bytes4 selector = _selectors[i];
require(!_isProtectedSelector(selector), ProtectedSelector(selector));
blockedSelectors[selector] = false;
}
emit SelectorsBlacklistingUpdated(_selectors, false);
}
// ============= EMERGENCY RECOVERY =============
/// @notice Recovers stuck ERC20/native tokens from the contract
/// @param _token Token address (use LibAsset._NATIVE_TOKEN for native)
/// @param _recipient Recovery recipient address
/// @param _amount Amount to recover
function recoverToken(address _token, address _recipient, uint256 _amount) external onlyOwner {
require(_recipient != address(0), NoTransferToNullAddress());
LibAsset.transferToken(_token, _recipient, _amount);
emit TokenRecovered(_token, _recipient, _amount);
}
/// @notice Recovers stuck ERC721 tokens from the contract
/// @param _token ERC721 contract address
/// @param _recipient Recovery recipient address
/// @param _id Token ID to recover
function recoverERC721(address _token, address _recipient, uint256 _id) external onlyOwner {
require(_recipient != address(0), NoTransferToNullAddress());
LibAsset.transferERC721(_token, _recipient, _id);
emit ERC721Recovered(_token, _recipient, _id);
}
/// @notice Recovers stuck ERC1155 tokens from the contract
/// @param _token ERC1155 contract address
/// @param _recipient Recovery recipient address
/// @param _ids Array of token IDs to recover
/// @param _amounts Array of amounts to recover for each ID
function recoverERC1155(address _token, address _recipient, uint256[] calldata _ids, uint256[] calldata _amounts) external onlyOwner {
require(_recipient != address(0), NoTransferToNullAddress());
LibAsset.transferBatchERC1155(_token, _recipient, _ids, _amounts);
emit ERC1155Recovered(_token, _recipient, _ids, _amounts);
}
// ============= PAUSE FUNCTIONALITY =============
/// @notice Pauses contract operations
function pause() external onlyOwnerOrAdmin whenNotPaused {
_pause();
}
/// @notice Unpauses contract operations
function unpause() external onlyOwnerOrAdmin whenPaused {
_unpause();
}
// solhint-disable-next-line code-complexity
function _isProtectedSelector(bytes4 selector) private pure returns (bool) {
if (selector == bytes4(0)) return true;
// ERC20 functions
if (selector == IERC20.approve.selector) return true;
if (selector == IERC20.transfer.selector) return true;
if (selector == IERC20.transferFrom.selector) return true;
// ERC721 functions
if (selector == IERC721.approve.selector) return true;
if (selector == IERC721.transferFrom.selector) return true;
if (selector == IERC721.setApprovalForAll.selector) return true;
if (selector == bytes4(keccak256("safeTransferFrom(address,address,uint256)"))) return true;
if (selector == bytes4(keccak256("safeTransferFrom(address,address,uint256,bytes)"))) return true;
// ERC1155 functions
if (selector == IERC1155.safeTransferFrom.selector) return true;
if (selector == IERC1155.safeBatchTransferFrom.selector) return true;
if (selector == IERC1155.setApprovalForAll.selector) return true;
return false;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { LibAsset } from "../shared/libraries/LibAsset.sol";
import { InvalidProtocolFeeVault, ZeroAddress, NoTransferToNullAddress, CallerIsNotOwnerOrAdmin } from "./Errors.sol";
/// @title DZapCoreBase
/// @author DZap
/// @notice Base contract containing core state variables, modifiers, and constructor
/// @dev This contract establishes the foundation for the modular DZap architecture
abstract contract DZapCoreBase is Ownable, ERC721Holder, ERC1155Holder, ReentrancyGuard {
// ============= PUBLIC STORAGE =============
address public protocolFeeVault;
address public zapVerifier;
address public permit2;
// ============= MAPPINGS =============
mapping(address user => uint256 nonce) public nonce;
mapping(address admin => bool isAdmin) public admins;
mapping(bytes4 selector => bool isBlocked) public blockedSelectors;
mapping(address adapter => bool isWhitelisted) internal _adaptersAllowlist;
mapping(address spender => bool isWhitelisted) internal _allowedErc1155Spender;
// ============= IMMUTABLE VARIABLES =============
address public immutable UNISWAP_PERMIT2;
bytes32 public immutable EXPECTED_PERMIT2_RUNTIME_HASH;
bytes32 internal immutable _DOMAIN_SEPARATOR;
// ============= CONSTANTS =============
string internal constant _DOMAIN_NAME = "DZapVerifier";
string internal constant _ZAP_VERSION = "1";
bytes32 internal constant _GASLESS_WITNESS_TYPEHASH =
keccak256(
"DZapGaslessZapWitness(bytes32 txId,address user,address dustReceiver,bytes32 zapDataHash,bytes32 feeDataHash,bytes32 executorFeeDataHash,bytes32 crosschainDataHash,bytes32 sweepDataHash)"
);
bytes32 internal constant _SIGNED_GASLESS_DATA_TYPEHASH =
keccak256(
"DZapGaslessZapData(bytes32 txId,address user,address dustReceiver,uint256 nonce,uint256 deadline,bytes32 zapDataHash,bytes32 feeDataHash,bytes32 executorFeeDataHash,bytes32 crosschainDataHash,bytes32 sweepDataHash)"
);
bytes32 internal constant _SIGNED_ZAP_DATA_TYPEHASH =
keccak256("DZapSignedZapData(bytes32 txId,address user,uint256 nonce,uint256 deadline,bytes32 zapDataHash,bytes32 feeDataHash)");
bytes32 private constant _DOMAIN_TYPEHASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)");
string internal constant _GASLESS_WITNESS_TYPE_STRING =
"DZapGaslessZapWitness witness)DZapGaslessZapWitness(bytes32 txId,address user,address dustReceiver,bytes32 zapDataHash,bytes32 feeDataHash,bytes32 executorFeeDataHash,bytes32 crosschainDataHash,bytes32 sweepDataHash)TokenPermissions(address token,uint256 amount)";
// ============= EVENTS =============
event ProtocolFeeVaultSet(address indexed newVault);
event ZapVerifierSet(address indexed newVerifier);
event Permit2Updated();
event AdminAdded(address indexed admin);
event AdminRemoved(address indexed admin);
event SelectorsBlacklistingUpdated(bytes4[] selectors, bool whitelisted);
event AdaptersWhitelistingUpdated(address[] adapters, bool whitelisted);
event Erc1155SpenderWhitelistingUpdated(address[] spenders, bool whitelisted);
event TokenRecovered(address indexed token, address indexed recipient, uint256 amount);
event ERC721Recovered(address indexed token, address indexed recipient, uint256 indexed tokenId);
event ERC1155Recovered(address indexed token, address indexed recipient, uint256[] tokenIds, uint256[] amounts);
event Zapped(bytes32 indexed transactionId, address indexed user, address indexed integrator, bytes crosschainData);
event GaslessZapped(bytes32 indexed transactionId, address executor, address indexed user, address indexed integrator, bytes crosschainData);
// ============= MODIFIERS =============
/// @notice Restricts access to owner or admin
modifier onlyOwnerOrAdmin() {
require(msg.sender == owner() || admins[msg.sender], CallerIsNotOwnerOrAdmin());
_;
}
/// @notice Validates dust receiver address
modifier validDustReceiver(address _dustReceiver) {
require(_dustReceiver != address(0), NoTransferToNullAddress());
_;
}
modifier refundExcessNative(address _refundee) {
uint256 initialBalance = LibAsset.selfNativeBalance() - msg.value;
_;
uint256 finalBalance = LibAsset.selfNativeBalance();
if (finalBalance > initialBalance) LibAsset.transferNativeToken(_refundee, finalBalance - initialBalance);
}
// ============= VIEWS =============
function isAdapterWhitelisted(address adapter) public view returns (bool isWhitelisted) {
return _adaptersAllowlist[adapter];
}
function isErc1155SpenderWhitelisted(address spender) public view returns (bool isWhitelisted) {
return _allowedErc1155Spender[spender];
}
// ============= CONSTRUCTOR =============
/// @notice Initializes the DZap core base contract
/// @param _owner Contract owner address
/// @param _protocolFeeVault Protocol fee recipient address
/// @param _zapVerifier Address authorized to sign zap verifications
/// @param _permit2 Permit2 contract address
/// @param _uniswapPermit2 Uniswap Permit2 contract address
/// @param _uniswapPermit2BytecodeHash Expected bytecode hash for Uniswap Permit2
/// @param _salt Domain separator salt
constructor(
address _owner,
address _protocolFeeVault,
address _zapVerifier,
address _permit2,
address _uniswapPermit2,
bytes32 _uniswapPermit2BytecodeHash,
bytes32 _salt
) Ownable(_owner) {
require(_zapVerifier != address(0) && _permit2 != address(0), ZeroAddress());
require(_protocolFeeVault != address(0) && _protocolFeeVault != address(this), InvalidProtocolFeeVault());
protocolFeeVault = _protocolFeeVault;
zapVerifier = _zapVerifier;
permit2 = _permit2;
UNISWAP_PERMIT2 = _uniswapPermit2;
EXPECTED_PERMIT2_RUNTIME_HASH = _uniswapPermit2BytecodeHash;
_DOMAIN_SEPARATOR = keccak256(
abi.encode(_DOMAIN_TYPEHASH, keccak256(bytes(_DOMAIN_NAME)), keccak256(bytes(_ZAP_VERSION)), block.chainid, address(this), _salt)
);
blockedSelectors[IERC20.approve.selector] = true;
blockedSelectors[IERC20.transfer.selector] = true;
blockedSelectors[IERC20.transferFrom.selector] = true;
blockedSelectors[IERC721.approve.selector] = true;
blockedSelectors[IERC721.transferFrom.selector] = true;
blockedSelectors[IERC721.setApprovalForAll.selector] = true;
blockedSelectors[bytes4(keccak256("safeTransferFrom(address,address,uint256)"))] = true;
blockedSelectors[bytes4(keccak256("safeTransferFrom(address,address,uint256,bytes)"))] = true;
blockedSelectors[IERC1155.safeTransferFrom.selector] = true;
blockedSelectors[IERC1155.safeBatchTransferFrom.selector] = true;
blockedSelectors[IERC1155.setApprovalForAll.selector] = true;
}
// ============= RECEIVE NATIVE TOKENS =============
/// @notice Allows contract to receive native tokens
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { DZapTokenHandler } from "./DZapTokenHandler.sol";
import { ZapData } from "./Types.sol";
import { UnauthorizedCall, ZapExecutionFailed, SelectorNotAllowed } from "./Errors.sol";
/// @title DZapExecution
/// @author DZap
/// @notice Abstract contract for handling zap execution logic
/// @dev Provides gas-optimized execution of external calls and zap operations
abstract contract DZapExecution is DZapTokenHandler {
// ============= CORE EXECUTION FUNCTIONS =============
/// @notice Executes a single external call (regular call or delegatecall)
/// @param _zapData Zap execution data containing call information
function _execute(ZapData memory _zapData) internal {
if (_zapData.callData.length == 0) return;
bool success;
bytes memory result;
if (_zapData.isDelegateCall) {
require(_zapData.callTo != address(this), UnauthorizedCall(_zapData.callTo));
// solhint-disable-next-line
(success, result) = _zapData.callTo.delegatecall(_zapData.callData);
} else {
bytes4 selector = bytes4(_zapData.callData);
require(!blockedSelectors[selector], SelectorNotAllowed(_zapData.callTo, selector));
(success, result) = _zapData.callTo.call{ value: _zapData.nativeValue }(_zapData.callData);
}
require(success, ZapExecutionFailed(_zapData.callTo, bytes4(_zapData.callData), result));
}
/// @notice Executes a complete zap operation with multiple steps
/// @param _zapData Array of zap execution steps
function _handleZap(ZapData[] calldata _zapData, address _user) internal {
uint256 length = _zapData.length;
for (uint256 i; i < length; ++i) {
bool hasErc1155AsInput = _processInputTokens(_zapData[i].inputTokens, _user, _zapData[i].approveTo);
uint256[] memory initialOutputBalances = _getOutputTokensInitialBalances(_zapData[i].outputTokens, _zapData[i].nativeValue);
_execute(_zapData[i]);
_processOutputTokens(_zapData[i].outputTokens, initialOutputBalances);
if (hasErc1155AsInput) {
_revokeErc1155Approvals(_zapData[i].inputTokens, _zapData[i].approveTo);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { LibAsset } from "../shared/libraries/LibAsset.sol";
import { DZapVerification } from "./DZapVerification.sol";
import { InputToken, OutputToken, TokenType, InputTransferType, OutputTransferType, TokenInfo, FeeConfig } from "./Types.sol";
import { InvalidTokenOwner, InvalidReturnAmount, InvalidRecipient, FeeExceedsReturnAmount, Erc1155SpenderNotWhitelisted } from "./Errors.sol";
/// @title DZapTokenHandler
/// @author DZap
/// @notice Abstract contract for handling token input and output operations
/// @dev Provides gas-optimized functions for processing various token standards
abstract contract DZapTokenHandler is DZapVerification {
// ============= INPUT TOKEN PROCESSING =============
/// @notice Processes all input tokens for a zap operation
/// @param _inputTokens Array of input token specifications
/// @param _spender Address to approve/transfer tokens to
/// @return hasErc1155AsInput Whether any ERC1155 tokens are being used as input
function _processInputTokens(InputToken[] calldata _inputTokens, address _user, address _spender) internal returns (bool hasErc1155AsInput) {
uint256 length = _inputTokens.length;
for (uint256 i; i < length; ++i) {
InputToken calldata inputToken = _inputTokens[i];
if (inputToken.tokenType == TokenType.NATIVE) {
_handleNativeInput(inputToken, _spender);
} else if (inputToken.tokenType == TokenType.ERC20) {
_handleErc20Input(inputToken, _spender);
} else if (inputToken.tokenType == TokenType.ERC721) {
_handleErc721Input(inputToken, _user, _spender);
} else if (inputToken.tokenType == TokenType.ERC1155) {
hasErc1155AsInput = true;
_handleErc1155Input(inputToken, _user, _spender);
}
}
}
/// @notice Handles native token input operations
/// @param _inputToken Input token specification
/// @param _spender Address to transfer to
function _handleNativeInput(InputToken calldata _inputToken, address _spender) private {
if (_inputToken.transferType == InputTransferType.TransferToSpender) {
LibAsset.transferNativeToken(_spender, _inputToken.amount);
}
}
/// @notice Handles ERC20 token input operations
/// @param _inputToken Input token specification
/// @param _spender Address to approve/transfer to
function _handleErc20Input(InputToken calldata _inputToken, address _spender) private {
if (_inputToken.transferType == InputTransferType.ApproveForSpender) {
LibAsset.maxApproveERC20(_inputToken.tokenAddress, _spender, _inputToken.amount);
} else if (_inputToken.transferType == InputTransferType.TransferToSpender) {
LibAsset.transferERC20(_inputToken.tokenAddress, _spender, _inputToken.amount);
} else if (_inputToken.transferType == InputTransferType.ApproveForSpenderViaPermit2) {
LibAsset.maxPermit2Approve(permit2, _inputToken.tokenAddress, _spender, _inputToken.amount);
}
}
/// @notice Handles ERC721 token input operations
/// @param _inputToken Input token specification
/// @param _spender Address to approve/transfer to
function _handleErc721Input(InputToken calldata _inputToken, address _user, address _spender) private {
if (_inputToken.transferType == InputTransferType.ApproveForSpender) {
address currentOwner = LibAsset.getOwnerOfERC721(_inputToken.tokenAddress, _inputToken.tokenId);
if (currentOwner != address(this)) {
LibAsset.transferERC721(_inputToken.tokenAddress, _user, address(this), _inputToken.tokenId);
}
LibAsset.approveERC721(_inputToken.tokenAddress, _spender, _inputToken.tokenId);
} else if (_inputToken.transferType == InputTransferType.TransferToSpender) {
LibAsset.transferERC721(_inputToken.tokenAddress, _spender, _inputToken.tokenId);
} else if (_inputToken.transferType == InputTransferType.DirectTransferToSpender) {
LibAsset.transferERC721(_inputToken.tokenAddress, _user, _spender, _inputToken.tokenId);
}
}
/// @notice Handles ERC1155 token input operations
/// @param _inputToken Input token specification
/// @param _spender Address to approve/transfer to
function _handleErc1155Input(InputToken calldata _inputToken, address _user, address _spender) private {
require(_allowedErc1155Spender[_spender], Erc1155SpenderNotWhitelisted(_spender));
if (_inputToken.transferType == InputTransferType.DirectTransferToSpender) {
LibAsset.transferERC1155(_inputToken.tokenAddress, _user, _spender, _inputToken.tokenId, _inputToken.amount);
return;
}
uint256 currentBalance = LibAsset.getBalanceOfERC1155(_inputToken.tokenAddress, address(this), _inputToken.tokenId);
if (currentBalance < _inputToken.amount) {
uint256 needed = _inputToken.amount - currentBalance;
LibAsset.transferERC1155(_inputToken.tokenAddress, _user, address(this), _inputToken.tokenId, needed);
}
if (_inputToken.transferType == InputTransferType.ApproveForSpender) {
if (!LibAsset.isErc1155ApprovedForAll(_inputToken.tokenAddress, address(this), _spender)) {
LibAsset.approveERC1155(_inputToken.tokenAddress, _spender);
}
} else if (_inputToken.transferType == InputTransferType.TransferToSpender) {
LibAsset.transferERC1155(_inputToken.tokenAddress, address(this), _spender, _inputToken.tokenId, _inputToken.amount);
}
}
/// @notice Revokes ERC1155 approvals after zap execution
/// @param _inputTokens Array of input tokens
/// @param _spender Address to revoke approvals from
function _revokeErc1155Approvals(InputToken[] calldata _inputTokens, address _spender) internal {
uint256 length = _inputTokens.length;
for (uint256 i; i < length; ++i) {
InputToken calldata inputToken = _inputTokens[i];
if (inputToken.tokenType == TokenType.ERC1155) {
if (LibAsset.isErc1155ApprovedForAll(inputToken.tokenAddress, address(this), _spender)) {
LibAsset.revokeERC1155(inputToken.tokenAddress, _spender);
}
}
}
}
// ============= OUTPUT TOKEN PROCESSING =============
/// @notice Gets initial balances for output tokens before zap execution
/// @param _outputTokens Array of output token specifications
/// @param _nativeValueUsed Native value being used in the execution
/// @return initialBalances Array of initial balances
function _getOutputTokensInitialBalances(
OutputToken[] calldata _outputTokens,
uint256 _nativeValueUsed
) internal view returns (uint256[] memory initialBalances) {
uint256 length = _outputTokens.length;
initialBalances = new uint256[](length);
for (uint256 i; i < length; ++i) {
OutputToken calldata outputToken = _outputTokens[i];
if (outputToken.transferType == OutputTransferType.ReceiveInContract) {
require(outputToken.recipient == address(this), InvalidRecipient());
}
address recipient = _getRecipient(outputToken);
if (outputToken.tokenType == TokenType.ERC20) {
initialBalances[i] = LibAsset.getErc20Balance(outputToken.tokenAddress, recipient);
} else if (outputToken.tokenType == TokenType.NATIVE) {
uint256 balance = recipient == address(this) ? LibAsset.selfNativeBalance() - _nativeValueUsed : LibAsset.getNativeBalance(recipient);
initialBalances[i] = balance;
} else if (outputToken.tokenType == TokenType.ERC1155) {
initialBalances[i] = LibAsset.getBalanceOfERC1155(outputToken.tokenAddress, recipient, outputToken.tokenId);
}
}
}
/// @notice Processes all output tokens after zap execution
/// @param _outputTokens Array of output token specifications
/// @param _initialBalances Array of initial balances before execution
function _processOutputTokens(OutputToken[] calldata _outputTokens, uint256[] memory _initialBalances) internal {
uint256 length = _outputTokens.length;
for (uint256 i; i < length; ++i) {
TokenType tokenType = _outputTokens[i].tokenType;
if (tokenType == TokenType.ERC20) {
_handleERC20Output(_outputTokens[i], _initialBalances[i]);
} else if (tokenType == TokenType.NATIVE) {
_handleNativeOutput(_outputTokens[i], _initialBalances[i]);
} else if (tokenType == TokenType.ERC721) {
_handleERC721Output(_outputTokens[i]);
} else if (tokenType == TokenType.ERC1155) {
_handleERC1155Output(_outputTokens[i], _initialBalances[i]);
}
}
}
/// @notice Handles ERC20 output token validation and transfer
/// @param _outputToken Output token specification
/// @param _initialBalance Initial balance before execution
function _handleERC20Output(OutputToken calldata _outputToken, uint256 _initialBalance) private {
address recipient = _getRecipient(_outputToken);
uint256 currentBalance = LibAsset.getBalance(_outputToken.tokenAddress, recipient);
uint256 returnAmount = currentBalance - _initialBalance;
require(returnAmount >= _outputToken.minReturn, InvalidReturnAmount(returnAmount, _outputToken.minReturn));
if (_outputToken.transferType == OutputTransferType.ReceiveAndTransfer) {
require(_outputToken.feeAmount <= returnAmount, FeeExceedsReturnAmount(returnAmount, _outputToken.feeAmount));
uint256 transferAmount = returnAmount - _outputToken.feeAmount;
LibAsset.transferERC20(_outputToken.tokenAddress, _outputToken.recipient, transferAmount);
}
}
/// @notice Handles native token output validation and transfer
/// @param _outputToken Output token specification
/// @param _initialBalance Initial balance before execution
function _handleNativeOutput(OutputToken calldata _outputToken, uint256 _initialBalance) private {
address recipient = _getRecipient(_outputToken);
uint256 currentBalance = LibAsset.getBalance(_outputToken.tokenAddress, recipient);
uint256 returnAmount = currentBalance - _initialBalance;
require(returnAmount >= _outputToken.minReturn, InvalidReturnAmount(returnAmount, _outputToken.minReturn));
if (_outputToken.transferType == OutputTransferType.ReceiveAndTransfer) {
uint256 transferAmount = returnAmount - _outputToken.feeAmount;
LibAsset.transferNativeToken(_outputToken.recipient, transferAmount);
}
}
/// @notice Handles ERC721 output validation and transfer
/// @param _outputToken Output token specification
function _handleERC721Output(OutputToken calldata _outputToken) private {
address recipient = _getRecipient(_outputToken);
address tokenOwner = LibAsset.getOwnerOfERC721(_outputToken.tokenAddress, _outputToken.tokenId);
require(recipient == tokenOwner, InvalidTokenOwner(_outputToken.tokenId));
if (_outputToken.transferType == OutputTransferType.ReceiveAndTransfer) {
LibAsset.transferERC721(_outputToken.tokenAddress, _outputToken.recipient, _outputToken.tokenId);
}
}
/// @notice Handles ERC1155 output validation and transfer
/// @param _outputToken Output token specification
/// @param _initialBalance Initial balance before execution
function _handleERC1155Output(OutputToken calldata _outputToken, uint256 _initialBalance) private {
address recipient = _getRecipient(_outputToken);
uint256 currentBalance = LibAsset.getBalanceOfERC1155(_outputToken.tokenAddress, recipient, _outputToken.tokenId);
uint256 returnAmount = currentBalance - _initialBalance;
require(returnAmount >= _outputToken.minReturn, InvalidReturnAmount(returnAmount, _outputToken.minReturn));
if (_outputToken.transferType == OutputTransferType.ReceiveAndTransfer) {
LibAsset.transferERC1155(_outputToken.tokenAddress, address(this), _outputToken.recipient, _outputToken.tokenId, returnAmount);
}
}
/// @notice Determines the actual recipient address for output tokens
/// @param _outputToken Output token specification
/// @return recipient The actual recipient address
function _getRecipient(OutputToken calldata _outputToken) private view returns (address recipient) {
recipient = _outputToken.transferType == OutputTransferType.ReceiveAndTransfer ? address(this) : _outputToken.recipient;
}
// ============= FEE AND SWEEP FUNCTIONS =============
/// @notice Processes fee payments to integrator and protocol
/// @param _feeConfig Fee configuration
function _processFee(FeeConfig calldata _feeConfig) internal {
uint256 length = _feeConfig.fees.length;
for (uint256 i; i < length; ++i) {
LibAsset.transferToken(_feeConfig.fees[i].token, _feeConfig.integrator, _feeConfig.fees[i].integratorFeeAmount);
LibAsset.transferToken(_feeConfig.fees[i].token, protocolFeeVault, _feeConfig.fees[i].protocolFeeAmount);
}
}
/// @notice Transfers executor fees to the transaction executor
/// @param _executorFeeInfo Array of executor fee specifications
function _transferExecutorFees(TokenInfo[] calldata _executorFeeInfo) internal {
uint256 length = _executorFeeInfo.length;
for (uint256 i; i < length; ++i) {
LibAsset.transferERC20WithoutChecks(_executorFeeInfo[i].token, msg.sender, _executorFeeInfo[i].amount);
}
}
/// @notice Sweeps remaining tokens to dust receiver
/// @param _sweepTokens Array of token addresses to sweep
/// @param _dustReceiver Address to receive swept tokens
function _handleSweepTokens(address[] calldata _sweepTokens, address _dustReceiver) internal {
uint256 length = _sweepTokens.length;
for (uint256 i; i < length; ++i) {
uint256 balance = LibAsset.getBalance(_sweepTokens[i], address(this));
if (balance > 0) {
LibAsset.transferERC20WithoutChecks(_sweepTokens[i], _dustReceiver, balance);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { DZapAdmin } from "./DZapAdmin.sol";
import { UnauthorizedSigner, SigDeadlineExpired } from "./Errors.sol";
/// @title DZapVerification
/// @author DZap
/// @notice Abstract contract handling all signature verification logic
/// @dev Implements EIP-712 signature verification for zap operations
abstract contract DZapVerification is DZapAdmin {
// ============= INTERNAL VERIFICATION FUNCTIONS =============
/// @notice Verifies EIP-712 signature against expected signer
/// @param _verifier Expected signer address
/// @param _msgHash Message hash to verify
/// @param _signature Signature to verify
function _verifySignature(address _verifier, bytes32 _msgHash, bytes calldata _signature) internal view {
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", _DOMAIN_SEPARATOR, _msgHash));
require(ECDSA.recover(digest, _signature) == _verifier, UnauthorizedSigner());
}
/// @notice Handles zap verification with signature validation
/// @param _transactionId Unique transaction identifier
/// @param _zapDataHash Hash of zap execution data
/// @param _feeDataHash Hash of fee configuration
/// @param _user User address for nonce tracking
/// @param _deadline Signature expiration timestamp
/// @param _signature Verifier signature
function _handleZapVerification(
bytes32 _transactionId,
bytes32 _zapDataHash,
bytes32 _feeDataHash,
address _user,
uint256 _deadline,
bytes calldata _signature
) internal {
require(_deadline >= block.timestamp, SigDeadlineExpired());
bytes32 msgHash = keccak256(
abi.encode(_SIGNED_ZAP_DATA_TYPEHASH, _transactionId, _user, nonce[_user], _deadline, _zapDataHash, _feeDataHash)
);
_verifySignature(zapVerifier, msgHash, _signature);
unchecked {
++nonce[_user];
}
}
/// @notice Handles gasless verification with user intent signature
/// @param _transactionId Unique transaction identifier
/// @param _zapDataHash Hash of zap execution data
/// @param _feeDataHash Hash of fee configuration
/// @param _executorFeeDataHash Hash of executor fee data
/// @param _crosschainDataHash Hash of crosschain data
/// @param _sweepDustHash Hash of sweep dust data
/// @param _user User address for nonce tracking
/// @param _dustReceiver Address to receive leftover tokens
/// @param _deadline Signature expiration timestamp
/// @param _userIntentSignature User's intent signature
function _handleGaslessVerification(
bytes32 _transactionId,
bytes32 _zapDataHash,
bytes32 _feeDataHash,
bytes32 _executorFeeDataHash,
bytes32 _crosschainDataHash,
bytes32 _sweepDustHash,
address _user,
address _dustReceiver,
uint256 _deadline,
bytes calldata _userIntentSignature
) internal {
require(_deadline >= block.timestamp, SigDeadlineExpired());
bytes32 msgHash = keccak256(
abi.encode(
_SIGNED_GASLESS_DATA_TYPEHASH,
_transactionId,
_user,
_dustReceiver,
nonce[_user],
_deadline,
_zapDataHash,
_feeDataHash,
_executorFeeDataHash,
_crosschainDataHash,
_sweepDustHash
)
);
_verifySignature(_user, msgHash, _userIntentSignature);
unchecked {
++nonce[_user];
}
}
/// @notice Creates witness hash for gasless batch permit2 operations
/// @param _transactionId Unique transaction identifier
/// @param _user User address
/// @param _dustReceiver Address to receive leftover tokens
/// @param _userNonce Current user nonce
/// @param _deadline Signature expiration timestamp
/// @param _zapDataHash Hash of zap execution data
/// @param _feeDataHash Hash of fee configuration
/// @param _executorFeeDataHash Hash of executor fee data
/// @param _crosschainDataHash Hash of crosschain data
/// @param _sweepDustHash Hash of sweep dust data
/// @return witness Computed witness hash for permit2
function _createGaslessWitness(
bytes32 _transactionId,
address _user,
address _dustReceiver,
uint256 _userNonce,
uint256 _deadline,
bytes32 _zapDataHash,
bytes32 _feeDataHash,
bytes32 _executorFeeDataHash,
bytes32 _crosschainDataHash,
bytes32 _sweepDustHash
) internal pure returns (bytes32 witness) {
witness = keccak256(
abi.encode(
_GASLESS_WITNESS_TYPEHASH,
_transactionId,
_user,
_dustReceiver,
_userNonce,
_deadline,
_zapDataHash,
_feeDataHash,
_executorFeeDataHash,
_crosschainDataHash,
_sweepDustHash
)
);
}
}// SPDX-License-Identifier: MIT pragma solidity 0.8.30; // ============= ZAP ERRORS ============= error CallerIsNotOwnerOrAdmin(); error ZeroAddress(); error NoTransferToNullAddress(); error DustReceiverIsZeroAddress(); error IntegratorIsZeroAddress(); error UnauthorizedSigner(); error SigDeadlineExpired(); error InvalidRecipient(); error InvalidTokenOwner(uint256); error InvalidReturnAmount(uint256 returnAmount, uint256 minReturn); error FeeExceedsReturnAmount(uint256 returnAmount, uint256 feeAmount); error InvalidProtocolFeeVault(); error UniswapPermit2AlreadySet(); error UniswapPermit2ByteCodeMismatch(); error UnauthorizedCall(address callTo); error ZapExecutionFailed(address target, bytes4 funSig, bytes reason); error SelectorNotAllowed(address target, bytes4 selector); error Erc1155SpenderNotWhitelisted(address spender); error ProtectedSelector(bytes4 selector);
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
/// @title Types
/// @notice Contains type definitions
enum PermitType {
PERMIT, // EIP2612
PERMIT2_APPROVE,
PERMIT2_WITNESS_TRANSFER,
BATCH_PERMIT2_WITNESS_TRANSFER
}
enum TokenType {
UNDEFINED,
NATIVE,
ERC20,
ERC721,
ERC1155
}
enum InputTransferType {
None,
ApproveForSpender,
TransferToSpender,
DirectTransferToSpender,
ApproveForSpenderViaPermit2
}
enum OutputTransferType {
ReceiveInContract,
ReceiveAndTransfer,
DirectTransferToRecipient
}
struct InputToken {
TokenType tokenType;
InputTransferType transferType;
address tokenAddress;
uint256 amount;
uint256 tokenId;
}
struct OutputToken {
TokenType tokenType;
OutputTransferType transferType;
address tokenAddress;
address recipient;
uint96 feeAmount;
uint256 minReturn;
uint256 tokenId;
}
/// @dev Core zap execution data structure
struct ZapData {
address callTo; // Address to call for zap execution
address approveTo; // Address to approve tokens to
bytes callData; // Encoded function call data
bool isDelegateCall; // Whether to use delegatecall
uint256 nativeValue; // Native token value to send
InputToken[] inputTokens; // Input token specifications
OutputToken[] outputTokens; // Output token specifications
}
/// @dev ERC20 token input with permit data
struct InputErc20Tokens {
address token; // Token contract address
uint256 amount; // Amount to transfer
bytes permit; // Permit signature data
}
/// @dev Simple token amount pair
struct TokenInfo {
address token; // Token contract address
uint256 amount; // Token amount
}
/// @dev Fee distribution data
struct Fees {
address token; // Fee token address
uint256 integratorFeeAmount; // Fee amount for integrator
uint256 protocolFeeAmount; // Fee amount for protocol
}
/// @dev Fee configuration for a transaction
struct FeeConfig {
address integrator; // Integrator address to receive fees
Fees[] fees; // Array of fee distributions
}{
"optimizer": {
"enabled": true,
"runs": 300
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_protocolFeeVault","type":"address"},{"internalType":"address","name":"_zapVerifier","type":"address"},{"internalType":"address","name":"_permit2","type":"address"},{"internalType":"address","name":"_uniswapPermit2","type":"address"},{"internalType":"bytes32","name":"_uniswapPermit2BytecodeHash","type":"bytes32"},{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerIsNotOwnerOrAdmin","type":"error"},{"inputs":[],"name":"DustReceiverIsZeroAddress","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"Erc1155SpenderNotWhitelisted","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FeeExceedsReturnAmount","type":"error"},{"inputs":[],"name":"IntegratorIsZeroAddress","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"InvalidPermitType","type":"error"},{"inputs":[],"name":"InvalidProtocolFeeVault","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"}],"name":"InvalidReturnAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"InvalidTokenOwner","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"NoTransferToNullAddress","type":"error"},{"inputs":[],"name":"NoTransferToNullAddress","type":"error"},{"inputs":[],"name":"NullAddrIsNotAValidSpender","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"ProtectedSelector","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"SelectorNotAllowed","type":"error"},{"inputs":[],"name":"SigDeadlineExpired","type":"error"},{"inputs":[{"internalType":"address","name":"callTo","type":"address"}],"name":"UnauthorizedCall","type":"error"},{"inputs":[],"name":"UnauthorizedSigner","type":"error"},{"inputs":[],"name":"UniswapPermit2AlreadySet","type":"error"},{"inputs":[],"name":"UniswapPermit2ByteCodeMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"funSig","type":"bytes4"},{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"ZapExecutionFailed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"adapters","type":"address[]"},{"indexed":false,"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"AdaptersWhitelistingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"AdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"ERC1155Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"spenders","type":"address[]"},{"indexed":false,"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"Erc1155SpenderWhitelistingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"integrator","type":"address"},{"indexed":false,"internalType":"bytes","name":"crosschainData","type":"bytes"}],"name":"GaslessZapped","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":[],"name":"Permit2Updated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newVault","type":"address"}],"name":"ProtocolFeeVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"},{"indexed":false,"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"SelectorsBlacklistingUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newVerifier","type":"address"}],"name":"ZapVerifierSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"integrator","type":"address"},{"indexed":false,"internalType":"bytes","name":"crosschainData","type":"bytes"}],"name":"Zapped","type":"event"},{"inputs":[],"name":"EXPECTED_PERMIT2_RUNTIME_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNISWAP_PERMIT2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"isAdmin","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"_selectors","type":"bytes4[]"}],"name":"blockSelectors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"blockedSelectors","outputs":[{"internalType":"bool","name":"isBlocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_transactionId","type":"bytes32"},{"internalType":"bytes","name":"_crosschainData","type":"bytes"},{"internalType":"bytes","name":"_zapVerificationSignature","type":"bytes"},{"internalType":"bytes","name":"_userIntentSignature","type":"bytes"},{"internalType":"uint256","name":"_zapDeadline","type":"uint256"},{"internalType":"uint256","name":"_userIntentDeadline","type":"uint256"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_dustReceiver","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"permit","type":"bytes"}],"internalType":"struct InputErc20Tokens[]","name":"_inputTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"integrator","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"integratorFeeAmount","type":"uint256"},{"internalType":"uint256","name":"protocolFeeAmount","type":"uint256"}],"internalType":"struct Fees[]","name":"fees","type":"tuple[]"}],"internalType":"struct FeeConfig","name":"_feeConfig","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenInfo[]","name":"_executorFeeInfo","type":"tuple[]"},{"components":[{"internalType":"address","name":"callTo","type":"address"},{"internalType":"address","name":"approveTo","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bool","name":"isDelegateCall","type":"bool"},{"internalType":"uint256","name":"nativeValue","type":"uint256"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum InputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct InputToken[]","name":"inputTokens","type":"tuple[]"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum OutputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"feeAmount","type":"uint96"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct OutputToken[]","name":"outputTokens","type":"tuple[]"}],"internalType":"struct ZapData[]","name":"_zapData","type":"tuple[]"},{"internalType":"address[]","name":"_sweepDust","type":"address[]"}],"name":"executeZap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_transactionId","type":"bytes32"},{"internalType":"bytes","name":"_crosschainData","type":"bytes"},{"internalType":"bytes","name":"_zapVerificationSignature","type":"bytes"},{"internalType":"bytes","name":"_userIntentSignature","type":"bytes"},{"internalType":"uint256","name":"_zapDeadline","type":"uint256"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_dustReceiver","type":"address"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenPermissions[]","name":"permitted","type":"tuple[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct PermitBatchTransferFrom","name":"_tokenDepositDetails","type":"tuple"},{"components":[{"internalType":"address","name":"integrator","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"integratorFeeAmount","type":"uint256"},{"internalType":"uint256","name":"protocolFeeAmount","type":"uint256"}],"internalType":"struct Fees[]","name":"fees","type":"tuple[]"}],"internalType":"struct FeeConfig","name":"_feeConfig","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenInfo[]","name":"_executorFeeInfo","type":"tuple[]"},{"components":[{"internalType":"address","name":"callTo","type":"address"},{"internalType":"address","name":"approveTo","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bool","name":"isDelegateCall","type":"bool"},{"internalType":"uint256","name":"nativeValue","type":"uint256"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum InputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct InputToken[]","name":"inputTokens","type":"tuple[]"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum OutputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"feeAmount","type":"uint96"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct OutputToken[]","name":"outputTokens","type":"tuple[]"}],"internalType":"struct ZapData[]","name":"_zapData","type":"tuple[]"},{"internalType":"address[]","name":"_sweepDust","type":"address[]"}],"name":"executeZapWithWitness","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"}],"name":"isAdapterWhitelisted","outputs":[{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"isErc1155SpenderWhitelisted","outputs":[{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"nonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"recoverERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_protocolFeeVault","type":"address"}],"name":"setProtocolFeeVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifier","type":"address"}],"name":"setVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"_selectors","type":"bytes4[]"}],"name":"unblockSelectors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateToUniswapPermit2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_adapters","type":"address[]"},{"internalType":"bool","name":"_whitelisted","type":"bool"}],"name":"whitelistAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_spenders","type":"address[]"},{"internalType":"bool","name":"_whitelisted","type":"bool"}],"name":"whitelistErc1155Spender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_transactionId","type":"bytes32"},{"internalType":"bytes","name":"_crosschainData","type":"bytes"},{"internalType":"bytes","name":"_zapVerificationSignature","type":"bytes"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"address","name":"_dustReceiver","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"permit","type":"bytes"}],"internalType":"struct InputErc20Tokens[]","name":"_inputTokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"integrator","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"integratorFeeAmount","type":"uint256"},{"internalType":"uint256","name":"protocolFeeAmount","type":"uint256"}],"internalType":"struct Fees[]","name":"fees","type":"tuple[]"}],"internalType":"struct FeeConfig","name":"_feeConfig","type":"tuple"},{"components":[{"internalType":"address","name":"callTo","type":"address"},{"internalType":"address","name":"approveTo","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bool","name":"isDelegateCall","type":"bool"},{"internalType":"uint256","name":"nativeValue","type":"uint256"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum InputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct InputToken[]","name":"inputTokens","type":"tuple[]"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum OutputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"feeAmount","type":"uint96"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct OutputToken[]","name":"outputTokens","type":"tuple[]"}],"internalType":"struct ZapData[]","name":"_zapData","type":"tuple[]"},{"internalType":"address[]","name":"_sweepDust","type":"address[]"}],"name":"zap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"zapVerifier","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_transactionId","type":"bytes32"},{"internalType":"bytes","name":"_crosschainData","type":"bytes"},{"internalType":"bytes","name":"_zapVerificationSignature","type":"bytes"},{"internalType":"bytes","name":"_batchDepositSignature","type":"bytes"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"address","name":"_dustReceiver","type":"address"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenPermissions[]","name":"permitted","type":"tuple[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct PermitBatchTransferFrom","name":"_tokenDepositDetails","type":"tuple"},{"components":[{"internalType":"address","name":"integrator","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"integratorFeeAmount","type":"uint256"},{"internalType":"uint256","name":"protocolFeeAmount","type":"uint256"}],"internalType":"struct Fees[]","name":"fees","type":"tuple[]"}],"internalType":"struct FeeConfig","name":"_feeConfig","type":"tuple"},{"components":[{"internalType":"address","name":"callTo","type":"address"},{"internalType":"address","name":"approveTo","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bool","name":"isDelegateCall","type":"bool"},{"internalType":"uint256","name":"nativeValue","type":"uint256"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum InputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct InputToken[]","name":"inputTokens","type":"tuple[]"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"enum OutputTransferType","name":"transferType","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"feeAmount","type":"uint96"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct OutputToken[]","name":"outputTokens","type":"tuple[]"}],"internalType":"struct ZapData[]","name":"_zapData","type":"tuple[]"},{"internalType":"address[]","name":"_sweepDust","type":"address[]"}],"name":"zapWithBatchDeposit","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e080604052346103f05760e0816155d3803803809161001f82856103f5565b8339810103126103f0576100328161042e565b9061003f6020820161042e565b61004b6040830161042e565b906100586060840161042e565b906100656080850161042e565b9260c060a08601519501519560018060a01b031680156103da57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3600180556001600160a01b031690811515806103c8575b156103b7576001600160a01b0316801515806103ad575b1561039c5760018060a01b0319600254161760025560018060a01b0319600354161760035560018060a01b031660018060a01b0319600454161760045560805260a05260405161013f6040826103f5565b600c81526b222d30b82b32b934b334b2b960a11b602090910152604080517fa1d9b1587d1cdcf2a70ea404b54a42fe06f3d0742dc8c87336986927bf127942929161018a90826103f5565b600181526020810190603160f81b8252519020906040519160208301937fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac564728552604084015260608301524660808301523060a083015260c082015260c081526101f460e0826103f5565b51902060c05260076020527f6ce1993b501ce2732f70f6d7ca5fa0a9413afb22ce1d2446c186d1fc0da7f9c78054600160ff1991821681179092557fa7e212da3b20a27fd68c1db136888cdd9a108921fab83dc3f5cd5df9348f44f980548216831790557fd8d6a3cfddbd2a617f312b3252a69071bcdcc1397584678d3540d52a372b498880548216831790557f9e3c8537f085a0f8e748b5c144b5d37adab0b3720be489d4b5760dfed0284d2c80548216831790557fbdf05ba9a90f2dcc5a2e7cc15b5ae45bc7e0e3c1ecc83326d55b2447ce27395e80548216831790557f9873d1eca3a1580e00b419e8235ec55bfcd85d0e8acebb28db2e8fd38572b49a80548216831790557f2167552ec4f2f824ceb2cfb56bfc62119737aa0cd98a146836268fd3ee44670d80548216831790557fe8d7ebe62994acb6a9ff255026b8fd941dd994e81a288e743dd572badcc47fdd8054821690921790915563a22cb46560e01b600052600a8054909116905560405161519090816104438239608051818181610b0e0152611f17015260a051818181610b76015261180b015260c051816142740152f35b6326ca8b5360e01b60005260046000fd5b50308114156100ee565b63d92e233d60e01b60005260046000fd5b506001600160a01b03831615156100d7565b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b601f909101601f19168101906001600160401b0382119082101761041857604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036103f05756fe61036080604052600436101561001e575b50361561001c57600080fd5b005b600061032052610320513560e01c90816301ffc9a7146120c55750806312261ee71461209c578063150b7a02146120475780631785f53c14611fd25780632cdf2c3514611f645780632dfb524d14611f3b578063335abd4514611ef557806335df8967146119075780633f4ba83a14611871578063429b62e51461182e5780634343ef21146117f15780635437988d146117805780635c975abb1461175b5780636ffe200b1461145d57806370480275146113e557806370ae92d2146113a7578063715018a61461134557806373ae843e146112a35780637afa1d40146111e25780637d1d0d2b146110495780638161988d14610f475780638419330114610e125780638456cb5914610d7957806388e95c4714610ce15780638da5cb5b14610cb6578063a7229fd914610c32578063ad224fa814610ada578063af1af3b914610ab1578063bc197c8114610a1c578063d9f21eaf146109d9578063e10ea0d7146107ba578063ed7a92c114610338578063f23a6e61146102e3578063f2fde38b1461024d578063f6f38e7c1461020a5763f8965b90146101bf5738610010565b34610203576020366003190112610203576001600160e01b03196101e1612115565b1661032051526007602052602060ff6040610320512054166040519015158152f35b6103205180fd5b34610203576020366003190112610203576001600160a01b0361022b612146565b1661032051526008602052602060ff6040610320512054166040519015158152f35b34610203576020366003190112610203576001600160a01b0361026e612146565b610276612968565b1680156102c7576103205180546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36103205180f35b631e4fbdf760e01b610320515261032051600452602461032051fd5b346102035760a0366003190112610203576102fc612146565b5061030561215c565b506084356001600160401b0381116102035761032590369060040161228c565b5060405163f23a6e6160e01b8152602090f35b6101a0366003190112610203576024356001600160401b038111610203576103649036906004016122e4565b61014052610120526044356001600160401b0381116102035761038b9036906004016122e4565b906064356001600160401b038111610203576103ab9036906004016122e4565b6103b6929192612188565b6101805260e4356101a08190526001600160a01b038116900361020357610104356001600160401b038111610203576103f3903690600401612341565b61012494919435610100526001600160401b036101005111610203576040600319610100513603011261020357610144356001600160401b03811161020357610440903690600401612311565b60a05294610164356001600160401b03811161020357610464903690600401612341565b60805293610184356001600160401b03811161020357610488903690600401612341565b60e05260c052610496612a09565b61049e612a2b565b6104a83447612437565b610160526001600160a01b036101a05116156107a5576001600160a01b036104d56101005160040161245a565b16156107905761053a6040516020810190610505816104f76080518b866124c3565b03601f198101835282612219565b519020986040516020810190610525816104f76101005160040185612778565b51902097608435610180518a8d600435612acc565b6040516020810190610553816104f760a0518c8661284a565b51902090610568366101405161012051612255565b6020815191012094604051602081019060208252610592816104f76040820160e05160c051612886565b519020974260a4351061077b576106ce9a6106b6996106a89861066e966001600160a01b036101805116610320515260056020526040610320512054946040519460208601967f5436d32061e18645e8d0b1ad2e3a2e5279b63a221538a2926f164c63bbb63211885260043560408801526001600160a01b03610180511660608801526001600160a01b036101a05116608088015260a087015260a43560c087015260e0860152610100850152610120840152610140830152610160820152610160815261066261018082612219565b5190206101805161424d565b6001600160a01b036101805116610320515260056020526040610320512060018154019055610180516001600160a01b0360045416613e20565b610180519060805190612e3e565b6106c561010051600401613baa565b60a05190613c3f565b6106e06101a05160e05160c051613c88565b6001600160a01b036106f76101005160040161245a565b166040516001600160a01b036101805116907f96dab0d3a79d5fe6e4b8023f5e33f1a4399ca8959fd3f13024902c11b490f8356004359180610741610140516101205133846128c8565b0390a44761016051811161075b575b600180556103205180f35b61076c610775916101605190612437565b6101a051612a78565b80610750565b63e354457160e01b6103205152600461032051fd5b632b3e1a9d60e01b6103205152600461032051fd5b6332abd14b60e01b6103205152600461032051fd5b610120366003190112610203576004356024356001600160401b038111610203576107e99036906004016122e4565b906044356001600160401b038111610203576108099036906004016122e4565b9290936103205150608435936001600160a01b038516958686036102035760a4356001600160401b03811161020357610846903690600401612341565b9160c4356001600160401b038111610203576040816004019160031990360301126102035760e4356001600160401b0381116102035761088a903690600401612341565b939094610104356001600160401b038111610203576108ad903690600401612341565b906108b6612a09565b6108be612a2b565b6108c83447612437565b9d156107a5576001600160a01b036108df8661245a565b16156107905761097d886001600160a01b03988f956109769061098b988f7fcd2a0ffd0d58b7b7c404a4e5f6551ebba356aa485923870ebcfcf9392cf19caa9f6109a89f9d8d6109909f9361096b94604051610944816104f78d6020830195866124c3565b5190209160405161095d816104f7602082019485612778565b519020606435923392612acc565b338d60045416613e20565b3391612e3e565b61098685613baa565b613c88565b61245a565b1694604051918291602083523396602084019161246e565b0390a4478281116109be57600180556103205180f35b6109d1926109cb91612437565b90612a78565b808080610750565b34610203576020366003190112610203576001600160a01b036109fa612146565b1661032051526009602052602060ff6040610320512054166040519015158152f35b346102035760a036600319011261020357610a35612146565b50610a3e61215c565b506044356001600160401b03811161020357610a5e90369060040161241c565b506064356001600160401b03811161020357610a7e90369060040161241c565b506084356001600160401b03811161020357610a9e90369060040161228c565b5060405163bc197c8160e01b8152602090f35b3461020357610320513660031901126102035760206001600160a01b0360025416604051908152f35b346102035761032051366003190112610203576001600160a01b0361032051541633148015610c16575b15610c01576004547f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03821691826001600160a01b03831614610bec57803b610b548161223a565b90610b626040519283612219565b80825260208201928361032051913c5190207f000000000000000000000000000000000000000000000000000000000000000003610bd7576001600160a01b03191617600455610320517f0a2c9e2facbf5893a918ca6981a7723f870e3c90a3f2cb0c1449e04585e942199080a16103205180f35b630525d2e160e31b6103205152600461032051fd5b630781cfbd60e01b6103205152600461032051fd5b637c51fa9d60e11b6103205152600461032051fd5b50336103205152600660205260ff604061032051205416610b04565b3461020357610c40366122aa565b90610c49612968565b6001600160a01b038116928315610ca1576001600160a01b0381610c91857f879f92dded0f26b83c3e00b12e0395dc72cfc3077343d1854ed6988edd1f909695602095613dc3565b6040519485521692a36103205180f35b6321f7434560e01b6103205152600461032051fd5b3461020357610320513660031901126102035760206001600160a01b03610320515416604051908152f35b34610203576020366003190112610203576001600160a01b03610d02612146565b610d0a612968565b1680151580610d6f575b15610d5a57600280546001600160a01b03191682179055610320517f5023575f35c92bf0a4d83e393b05da7b0e70f45719d04e57e02270324e3c61d29080a26103205180f35b6326ca8b5360e01b6103205152600461032051fd5b5030811415610d14565b346102035761032051366003190112610203576001600160a01b0361032051541633148015610df6575b15610c0157610db0612a2b565b610db8612a2b565b600160ff19600a541617600a557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a16103205180f35b50336103205152600660205260ff604061032051205416610da3565b34610203576020366003190112610203576004356001600160401b03811161020357610e42903690600401612341565b610e4a612968565b610320515b818110610eda575060405190610320515080604083016040845252606082019290610320515b818110610eb2576103205160208501527f53625d2d39d45376dc6f4d009fb607be69cb55bc332ae8612e0c184451a00ad284860385a16103205180f35b90919360208060019263ffffffff60e01b610ecc89612131565b168152019501929101610e75565b610eed610ee88284866128e8565b612953565b610ef681613d34565b610f26579060019163ffffffff60e01b16610320515260076020526040610320512060ff19815416905501610e4f565b63128b2def60e31b610320515263ffffffff60e01b16600452602461032051fd5b34610203576020366003190112610203576004356001600160401b03811161020357610f77903690600401612341565b610f7f612968565b610320515b81811061100d575060405190610320515080604083016040845252606082019290610320515b818110610fe557600160208501527f53625d2d39d45376dc6f4d009fb607be69cb55bc332ae8612e0c184451a00ad284860385a16103205180f35b90919360208060019263ffffffff60e01b610fff89612131565b168152019501929101610faa565b6001906001600160e01b0319611027610ee88386886128e8565b1661032051526007602052604061032051208260ff1982541617905501610f84565b3461020357608036600319011261020357611062612146565b61106a61215c565b906044356001600160401b0381116102035761108a903690600401612341565b9290606435936001600160401b038511610203576110b46001600160a01b03953690600401612341565b9590936110bf612968565b16948515610ca1576110d23683856123d0565b6001600160a01b036110e53684886123d0565b961695863b15610203576111339061112160405193631759616b60e11b85523060048601528a602486015260a0604486015260a4850190613d00565b83810360031901606485015290613d00565b818103906003198201608484015261032051905281602061032051920181610320518a5af180156111d4576111b9575b507ff4120cf4cc98e70461ae37cc5479b37ce728a1cda2c9dd0757905a33c457d4b8936111af916111a160405195869560408752604087019161292f565b91848303602086015261292f565b0390a36103205180f35b610320516111c691612219565b610320516102035786611163565b6040513d61032051823e3d90fd5b34610203576111f03661237e565b916111f9612968565b610320515b82811061124157506112377f9d601757730dea2d7f3dcc03179c9565ebbe275e0409685dc8334eea776d7131936040519384938461290e565b0390a16103205180f35b6001600160a01b0361125761098b8386866128e8565b1690811561128e576001916103205152600860205261128885604061032051209060ff801983541691151516179055565b016111fe565b63d92e233d60e01b6103205152600461032051fd5b34610203576112b13661237e565b916112ba612968565b610320515b8281106112f857506112377fbbeef6f5fd30d06b8e7b13a6e24bb63c8e440baa786df030fb291322661cdb37936040519384938461290e565b6001600160a01b0361130e61098b8386866128e8565b1690811561128e576001916103205152600960205261133f85604061032051209060ff801983541691151516179055565b016112bf565b34610203576103205136600319011261020357611360612968565b6103205180546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a36103205180f35b34610203576020366003190112610203576001600160a01b036113c8612146565b166103205152600560205260206040610320512054604051908152f35b34610203576020366003190112610203576001600160a01b03611406612146565b61140e612968565b16806103205152600660205260406103205120600160ff198254161790557f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e3396103205161032051a26103205180f35b610140366003190112610203576024356001600160401b038111610203576114899036906004016122e4565b906044356001600160401b038111610203576114a99036906004016122e4565b9290916064356001600160401b038111610203576114cb9036906004016122e4565b90936114d5612172565b9460c435916001600160401b038311610203576060836004019360031990360301126102035760e435926001600160401b038411610203576040600319853603011261020357610104356001600160401b0381116102035761153b903690600401612341565b9091610124356001600160401b0381116102035761155d903690600401612341565b979094611568612a09565b611570612a2b565b61157a3447612437565b9c6001600160a01b038d16156107a5576001600160a01b0361159e8a60040161245a565b1615610790576115ed9160405160208101906115bf816104f78a8c866124c3565b5190208a6040516115db816104f7602082019460040185612778565b51902090608435913391600435612acc565b6001600160a01b03600454166116038380612b8f565b93905061160f84612bc4565b610320519094905b81811061170f57505061162a3033614924565b90611633614526565b93833b1561020357611663906040519a8b968795869563fe8ec1a760e01b8752610320519a339160048901612c8e565b039161032051905af19384156111d45789946116eb575b50946116a5926116996116ad9695936001600160a01b03983391612e3e565b61098685600401613baa565b60040161245a565b16917fcd2a0ffd0d58b7b7c404a4e5f6551ebba356aa485923870ebcfcf9392cf19caa60405160208152806109a8339560043595602084019161246e565b6116fd91939594506103205190612219565b6103205161020357879293918a61167a565b8060206117286001936117228780612b8f565b90612c22565b013560405190611737826121b2565b30825260208201526117498289612c32565b526117548188612c32565b5001611617565b34610203576103205136600319011261020357602060ff600a54166040519015158152f35b34610203576020366003190112610203576001600160a01b036117a1612146565b6117a9612968565b16801561128e57600380546001600160a01b03191682179055610320517f1f32c57ae657a3f3ab90e3fe76f97d4f0b6a354bb93021f4eb8f73541fdab4cc9080a26103205180f35b3461020357610320513660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203576020366003190112610203576001600160a01b0361184f612146565b1661032051526006602052602060ff6040610320512054166040519015158152f35b346102035761032051366003190112610203576001600160a01b03610320515416331480156118eb575b15610c01576118a8613ce2565b6118b0613ce2565b60ff19600a5416600a557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a16103205180f35b50336103205152600660205260ff60406103205120541661189b565b610180366003190112610203576024356001600160401b038111610203576119339036906004016122e4565b6102c0526102a0526044356001600160401b0381116102035761195a9036906004016122e4565b906064356001600160401b0381116102035761197a9036906004016122e4565b919092611985612172565b6102e052611991612188565b6103405260e435916001600160401b03831161020357606060031984360301126102035761010435610280526001600160401b036102805111610203576040600319610280513603011261020357610124356001600160401b038111610203576119ff903690600401612311565b6102205261020052610144356001600160401b03811161020357611a27903690600401612341565b6101e0526101c052610164356001600160401b03811161020357611a4f903690600401612341565b6102605261024052611a5f612a09565b611a67612a2b565b611a713447612437565b610300526001600160a01b036103405116156107a5576001600160a01b03611a9e6102805160040161245a565b161561079057611af96040516020810190611ac4816104f76101e0516101c051866124c3565b519020926040516020810190611ae4816104f76102805160040185612778565b519020926084356102e0518587600435612acc565b6040516020810190611b16816104f761022051610200518661284a565b519020611b2a366102c0516102a051612255565b6020815191012090604051602081019060208252611b56816104f7604082016102605161024051612886565b51902092604051947f7b11bd3d663bf130c1c54e3ddccc063b44ae0be4e06e969fae5a8603214ea551602087015260043560408701526001600160a01b036102e0511660608701526001600160a01b036103405116608087015260a086015260c085015260e08401526101008301526101208201526101208152611bdc61014082612219565b8051602090910120600454604051926001600160a01b039091169190611c0461014085612219565b61010684527f445a61704761736c6573735a61705769746e657373207769746e65737329445a60208501527f61704761736c6573735a61705769746e6573732862797465733332207478496460408501527f2c6164647265737320757365722c61646472657373206475737452656365697660608501527f65722c62797465733332207a617044617461486173682c62797465733332206660808501527f656544617461486173682c62797465733332206578656375746f72466565446160a08501527f7461486173682c627974657333322063726f7373636861696e4461746148617360c08501527f682c62797465733332207377656570446174614861736829546f6b656e50657260e08501527f6d697373696f6e73286164647265737320746f6b656e2c75696e743235362061610100850152656d6f756e742960d01b610120850152611d576004820180612b8f565b959050611d6386612bc4565b610320519096905b818110611eac575050833b1561020357611da9906040519788968795869563fe8ec1a760e01b8752610320519a6102e0519160040160048901612c8e565b039161032051905af180156111d457611e99575b50611dd26102e0516101e0516101c051612e3e565b611de161028051600401613baa565b611df16102205161020051613c3f565b611e05610340516102605161024051613c88565b6001600160a01b03611e1c6102805160040161245a565b166040516001600160a01b036102e05116907f96dab0d3a79d5fe6e4b8023f5e33f1a4399ca8959fd3f13024902c11b490f8356004359180611e666102c0516102a05133846128c8565b0390a447610300518111611e7f57600180556103205180f35b611e90610775916103005190612437565b61034051612a78565b61032051611ea691612219565b80611dbd565b6001906020611ec2826117226004890180612b8f565b013560405190611ed1826121b2565b3082526020820152611ee3828b612c32565b52611eee818a612c32565b5001611d6b565b3461020357610320513660031901126102035760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610320513660031901126102035760206001600160a01b0360035416604051908152f35b3461020357611f72366122aa565b9190611f7c612968565b6001600160a01b038116918215610ca157611fa0846001600160a01b039383612991565b167f6a30e6784464f0d1f4158aa4cb65ae9239b0fa87c7f2c083ee6dde44ba97b5e66103205161032051a46103205180f35b34610203576020366003190112610203576001600160a01b03611ff3612146565b611ffb612968565b1680610320515260066020526040610320512060ff1981541690557fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f6103205161032051a26103205180f35b3461020357608036600319011261020357612060612146565b5061206961215c565b506064356001600160401b0381116102035761208990369060040161228c565b50604051630a85bd0160e11b8152602090f35b3461020357610320513660031901126102035760206001600160a01b0360045416604051908152f35b34610203576020366003190112610203576020906001600160e01b03196120ea612115565b16630271189760e51b8114908115612104575b5015158152f35b6301ffc9a760e01b149050836120fd565b600435906001600160e01b03198216820361212c57565b600080fd5b35906001600160e01b03198216820361212c57565b600435906001600160a01b038216820361212c57565b602435906001600160a01b038216820361212c57565b60a435906001600160a01b038216820361212c57565b60c435906001600160a01b038216820361212c57565b35906001600160a01b038216820361212c57565b604081019081106001600160401b038211176121cd57604052565b634e487b7160e01b600052604160045260246000fd5b60e081019081106001600160401b038211176121cd57604052565b606081019081106001600160401b038211176121cd57604052565b90601f801991011681019081106001600160401b038211176121cd57604052565b6001600160401b0381116121cd57601f01601f191660200190565b9291926122618261223a565b9161226f6040519384612219565b82948184528183011161212c578281602093846000960137010152565b9080601f8301121561212c578160206122a793359101612255565b90565b606090600319011261212c576004356001600160a01b038116810361212c57906024356001600160a01b038116810361212c579060443590565b9181601f8401121561212c578235916001600160401b03831161212c576020838186019501011161212c57565b9181601f8401121561212c578235916001600160401b03831161212c576020808501948460061b01011161212c57565b9181601f8401121561212c578235916001600160401b03831161212c576020808501948460051b01011161212c57565b3590811515820361212c57565b604060031982011261212c57600435906001600160401b03821161212c576123a891600401612341565b9091602435801515810361212c5790565b6001600160401b0381116121cd5760051b60200190565b9291906123dc816123b9565b936123ea6040519586612219565b602085838152019160051b810192831161212c57905b82821061240c57505050565b8135815260209182019101612400565b9080601f8301121561212c578160206122a7933591016123d0565b9190820391821161244457565b634e487b7160e01b600052601160045260246000fd5b356001600160a01b038116810361212c5790565b908060209392818452848401376000828201840152601f01601f1916010190565b6005111561249957565b634e487b7160e01b600052602160045260246000fd5b35906001600160601b038216820361212c57565b82602082016020835252604081019260408160051b830101938360009360de1982360301905b8486106124fa575050505050505090565b90919293949596603f1982820301855287358381121561212c578401906001600160a01b036125288361219e565b1681526001600160a01b0361253f6020840161219e565b16602082015236829003601e19019160408101358381121561212c5781016020813591016001600160401b03821161212c57813603811361212c5761258f9160e0604086015260e085019161246e565b9261259c60608301612371565b151560608401526080820135608084015260a08201358181121561212c578201602081359101946001600160401b03821161212c5760a082023603861361212c5784810360a086015281815260200194906000905b8082106127025750505060c08201359081121561212c570190602082359201926001600160401b03831161212c5760e083023603841361212c578160c060209383039101528281520191906000905b808210612661575050506020806001929901950196019493959291906124e9565b9091928335600581101561212c576126788161248f565b8152602084013590600382101561212c5760e0809160019360208201526001600160a01b036126a96040890161219e565b1660408201526001600160a01b036126c36060890161219e565b1660608201526001600160601b036126dd608089016124af565b16608082015260a087013560a082015260c087013560c0820152019401920190612640565b9091958635600581101561212c576127198161248f565b8152602087013590600582101561212c5760a080918361273a60019561248f565b60208201526001600160a01b0361275360408c0161219e565b16604082015260608a0135606082015260808a013560808201520197019201906125f1565b906020825260608201906001600160a01b036127938261219e565b1660208401526020810135601e198236030181121561212c570190602082359201926001600160401b03831161212c57606083023603841361212c57826080926040808401525201919060005b8181106127ed5750505090565b9091926060806001926001600160a01b036128078861219e565b168152602087013560208201526040870135604082015201940191019190916127e0565b602080916001600160a01b036128408261219e565b1684520135910152565b602080825281018390526040019160005b8181106128685750505090565b9091926040808261287b6001948861282b565b01940192910161285b565b9160209082815201919060005b8181106128a05750505090565b9091926020806001926001600160a01b036128ba8861219e565b168152019401929101612893565b6040906001600160a01b036122a79593168152816020820152019161246e565b91908110156128f85760051b0190565b634e487b7160e01b600052603260045260246000fd5b9160209161292791959495604085526040850191612886565b931515910152565b81835290916001600160fb1b03831161212c5760209260051b809284830137010190565b356001600160e01b03198116810361212c5790565b6001600160a01b0360005416330361297c57565b63118cdaa760e01b6000523360045260246000fd5b9091906001600160a01b0316803b1561212c57604051632142170760e11b81523060048201526001600160a01b0390931660248401526044830191909152819081606481015b918160008096819503925af180156129fe576129f1575050565b816129fb91612219565b50565b6040513d84823e3d90fd5b600260015414612a1a576002600155565b633ee5aeb560e01b60005260046000fd5b60ff600a5416612a3757565b63d93c066560e01b60005260046000fd5b3d15612a73573d90612a598261223a565b91612a676040519384612219565b82523d6000602084013e565b606090565b8115612ac8576001600160a01b03811615612ab757600080809381935af1612a9e612a48565b5015612aa657565b633d2cec6f60e21b60005260046000fd5b6321f7434560e01b60005260046000fd5b5050565b9195939095949294428210612b7e576001600160a01b03612b68961696876000526005602052604060002054926040519360208501957f35e34fdbc052ba343caab21badcef36ff38be3518fe4f444f7e5c95605b69e4787526040860152896060860152608085015260a084015260c083015260e082015260e08152612b5461010082612219565b5190206001600160a01b036003541661424d565b6000526005602052604060002060018154019055565b63e354457160e01b60005260046000fd5b903590601e198136030182121561212c57018035906001600160401b03821161212c57602001918160061b3603831361212c57565b90612bce826123b9565b612bdb6040519182612219565b8281528092612bec601f19916123b9565b019060005b828110612bfd57505050565b602090604051612c0c816121b2565b6000815260008382015282828501015201612bf1565b91908110156128f85760061b0190565b80518210156128f85760209160051b010190565b60005b838110612c595750506000910152565b8181015183820152602001612c49565b90602091612c8281518092818552858086019101612c46565b601f01601f1916010190565b959391979694929060c087526101208701908035601e198236030181121561212c578101602081359101926001600160401b03821161212c578160061b3603841361212c578190606060c08c0152526101408901929060005b818110612d9457505050806020604092013560e08a0152013561010088015286810360208801526020808a51928381520199019060005b818110612d6157505050916122a79697916001600160a01b03612d539416604088015260608701528582036080870152612c69565b9260a081850391015261246e565b9091996020604082612d896001948f51602080916001600160a01b0381511684520151910152565b019b01929101612d1e565b90919360408082612da76001948961282b565b019501929101612ce7565b91908110156128f85760051b8101359060de198136030182121561212c570190565b903590601e198136030182121561212c57018035906001600160401b03821161212c576020019160a082023603831361212c57565b903590601e198136030182121561212c57018035906001600160401b03821161212c576020019160e082023603831361212c57565b919060005b818110612e505750505050565b612e68612e5e828487612db2565b60a0810190612dd4565b90612e7f6020612e7985878a612db2565b0161245a565b9060009260005b81811061374d5750505050612ea9612e9f838588612db2565b60c0810190612e09565b906080612eb785878a612db2565b013590612ec3836123b9565b92612ed16040519485612219565b808452601f19612ee0826123b9565b0136602086013760005b8181106135a35750505050612f00838588612db2565b60e08136031261212c5760405190612f17826121e3565b612f208161219e565b8252612f2e6020820161219e565b602083015260408101356001600160401b03811161212c57612f53903690830161228c565b6040830152612f6460608201612371565b60608301526080810135608083015260a08101356001600160401b03811161212c57810136601f8201121561212c578035612f9e816123b9565b91612fac6040519384612219565b818352602060a081850193028201019036821161212c57602001915b8183106135265750505060a083015260c0810135906001600160401b03821161212c570136601f8201121561212c578035613002816123b9565b916130106040519384612219565b818352602060e081850193028201019036821161212c57602001915b8183106134975750505060c08201526130449061433e565b613052612e9f848689612db2565b60005b818110613167575050505061306d575b600101612e43565b61307b612e5e828487612db2565b61308b6020612e7985878a612db2565b9060005b81811061309f5750505050613065565b6130aa8183866142e1565b8035600581101561212c576004906130c18161248f565b146130d0575b5060010161308f565b6040016130e7846130e08361245a565b3090614863565b156130c7576130fd6001600160a01b039161245a565b1690813b1561212c576000809260446040518095819363a22cb46560e01b83526001600160a01b038a1660048401528160248401525af191821561315b5760019261314a575b50906130c7565b600061315591612219565b38613143565b6040513d6000823e3d90fd5b6131728183856142f1565b35600581101561212c576131858161248f565b6002810361329757506131998183856142f1565b6131a38286612c32565b51906131cd6131b182614797565b926131c860408401946131c38661245a565b61448d565b612437565b6131df60a0830135828181101561482f565b6020820135600381101561212c57600160009114613206575b505050506001905b01613055565b6080830190826001600160601b0361321d8461484f565b16116132288361484f565b9061327757505091613268606061326161325b60019897956001600160601b0361325461326e9961484f565b1690612437565b9461245a565b920161245a565b906145d3565b903880806131f8565b630b12dd8f60e31b825260048490526001600160601b0316602452604490fd5b6132a08161248f565b6001810361333957506132b48183856142f1565b906132db6132c28287612c32565b516131c86132cf85614797565b6131c36040870161245a565b6132ed60a0840135828181101561482f565b602083013592600384101561212c57600180941461330d575b5050613200565b61332d6060613261613332946001600160601b036132546080870161484f565b612a78565b3880613306565b6133428161248f565b600381036133e357506133568183856142f1565b9061336082614797565b604083019061336e8261245a565b906001600160a01b038061338760c08801358095614b35565b169116036133cf57602084013593600385101561212c5760018095146133b0575b505050613200565b6133c160606132616133c79561245a565b90612991565b3880806133a8565b6373514b5160e11b60005260045260246000fd5b6004906133ef8161248f565b146133fd575b600190613200565b6134088183856142f1565b906134138186612c32565b5161341d83614797565b61343e60408501926131c86134318561245a565b60c08801359485916147bd565b9061345160a0860135838181101561482f565b602085013594600386101561212c576001809614613475575b5050505090506133f5565b613486606061326161348e9661245a565b903090614a7b565b3880808061346a565b60e08336031261212c57604051906134ae826121e3565b8335600581101561212c578252602084013590600382101561212c57826020928360e09501526134e06040870161219e565b60408201526134f16060870161219e565b6060820152613502608087016124af565b608082015260a086013560a082015260c086013560c082015281520192019161302c565b60a08336031261212c576040519060a082018281106001600160401b038211176121cd576040528335600581101561212c578252602084013590600582101561212c57826020928360a095015261357f6040870161219e565b60408201526060860135606082015260808601356080820152815201920191612fc8565b6135ae8183856142f1565b602081013590600382101561212c5760009115613723575b6135cf81614797565b908035600581101561371f576135e48161248f565b6002810361368c57506001600160a01b0360248161360660406020950161245a565b169360405194859384926370a0823160e01b84521660048301525afa918215613680578092613648575b5050906001916136408288612c32565b525b01612eea565b9091506020823d8211613678575b8161366360209383612219565b81010312613675575051600138613630565b80fd5b3d9150613656565b604051903d90823e3d90fd5b60019493919061369b8161248f565b8086036136d6575050506001600160a01b03811630036136d057506136c08547612437565b6136ca8288612c32565b52613642565b316136c0565b9091506004906136e58161248f565b146136f2575b5050613642565b61370d9160c06137046040840161245a565b920135916147bd565b6137178288612c32565b5238806136eb565b8380fd5b61372f6060820161245a565b6001600160a01b031630146135c657634e46966960e11b8252600482fd5b6137588183856142e1565b8035600581101561212c5761376c8161248f565b600181036137b5575090602082013591600583101561212c5760026001936137938161248f565b146137a1575b505b01612e86565b60606137af91013586612a78565b38613799565b60006137c08261248f565b600282036139d6575050906020820135600581101561212c576137e28161248f565b6001810361380e57506138098286606061380060406001970161245a565b92013591614bf7565b61379b565b60006138198261248f565b600282036138415750506138098286606061383860406001970161245a565b920135916145d3565b5060049061384e8161248f565b1461385d575b6001915061379b565b6001600160a01b036004541660606138776040850161245a565b930135926001600160a01b03871680156139c55760405163927da10560e01b81523060048201526001600160a01b03838116602483015289166044820152606081606481875afa90811561315b578690600090819361398c575b506001600160a01b03161090811561397a575b506138fd575b50926138f891600194614bf7565b613854565b939091803b1561212c57604051946387517c4560e01b86526001600160a01b038416600487015260248601526001600160a01b03604486015265ffffffffffff606486015260008560848183855af192831561315b576001956138f894613969575b50919450916138ea565b600061397491612219565b3861395f565b65ffffffffffff9150164211386138e4565b6001600160a01b0393506139b7915060603d81116139be575b6139af8183612219565b810190614bc1565b50926138d1565b503d6139a5565b6363ba9bff60e01b60005260046000fd5b506139e08161248f565b60038103613b335750906020820135600581101561212c57613a018161248f565b60018103613ac95750613a3e60408301613a296080613a1f8361245a565b9501358095614b35565b6001600160a01b0330911603613ab55761245a565b6001600160a01b038616156139c5576001600160a01b0316803b1561212c5760405163095ea7b360e01b81526001600160a01b038716600482015260248101939093526000908390604490829084905af191821561315b57600192613aa4575b5061379b565b6000613aaf91612219565b38613a9e565b61098b84308d613ac48561245a565b614aeb565b916001926000613ad88261248f565b60028203613afe57505080866080613af56040613809950161245a565b92013591612991565b50600390613b0b8161248f565b14613b16575061379b565b80868b6080613b2a6040613aaf960161245a565b93013592614aeb565b600490613b3f8161248f565b14613b4e575b5060019061379b565b9450600190613b5f858a8498614606565b90613b45565b903590601e198136030182121561212c57018035906001600160401b03821161212c5760200191606082023603831361212c57565b91908110156128f8576060020190565b60208101613bb88183613b65565b92905060005b838110613bcb5750505050565b80613c09613be861098b600194613be28888613b65565b90613b9a565b613bf18561245a565b6020613c0185613be28a8a613b65565b013591613dc3565b613c39613c1d61098b83613be28888613b65565b6001600160a01b03600254166040613c0185613be28a8a613b65565b01613bbe565b60005b828110613c4e57505050565b80613c82613c6261098b6001948787612c22565b6020613c6f848888612c22565b0135906001600160a01b033391166148e3565b01613c42565b9060005b818110613c995750505050565b600190613cae306131c361098b8487896128e8565b80613cbb575b5001613c8c565b613cdc90866001600160a01b03613cd661098b86898b6128e8565b166148e3565b38613cb4565b60ff600a541615613cef57565b638dfc202b60e01b60005260046000fd5b906020808351928381520192019060005b818110613d1e5750505090565b8251845260209384019390920191600101613d11565b6001600160e01b0319168015613dbd5763095ea7b360e01b8114613dbd5763a9059cbb60e01b8114613dbd576323b872dd60e01b8114613dbd5763a22cb46560e01b8114613dbd57632142170760e11b8114613dbd57635c46a7ef60e11b8114613dbd57637921219560e11b8114613dbd57631759616b60e11b14613db857600090565b600190565b50600190565b91906001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee03613df557613df39250612a78565b565b613df3926145d3565b91908110156128f85760051b81013590605e198136030182121561212c570190565b929160005b838110613e33575050505050565b613e4161098b828685613dfe565b906020613e4f828786613dfe565b0135613e5c828786613dfe565b604081013590601e198136030182121561212c57019283356001600160401b03811161212c576020850190803603821361212c5785019060408683031261212c573594600486101561212c576040810135916001600160401b03831161212c57613ecd92602080920192010161228c565b93613ed7816145fc565b6002810361405d5750835184019060608583031261212c576020850151916040860151956060810151916001600160401b03831161212c57613f2092602080920192010161497b565b6001600160a01b038a16936001600160a01b0360405193613f40856121b2565b16835280602084015260405192613f56846121fe565b8352602083019384526040830196875260405190613f73826121b2565b3082526020820152613f85308a614924565b613f8d614526565b91863b1561212c576040516309be14ff60e11b8152945180516001600160a01b03166004870152602001516024860152939788958695919051604487015251606486015280516001600160a01b031660848601526020015160a48501526001600160a01b038a1660c485015260e484015261010483016101409052610144830161401691612c69565b8281036003190161012484015261402c91612c69565b03815a6000948591f191821561315b5760019261404c575b505b01613e25565b600061405791612219565b38614044565b9093919061406a816145fc565b8061419f5750908051806140d3575b50506040516323b872dd60e01b60208201526001600160a01b03868116602483015230604483015260648201929092526001936140ce92906140c883608481015b03601f198101855284612219565b16614d27565b614046565b8160809181949301031261212c5760208201519160408101519060ff821680920361212c57608060608201519101516001600160a01b03871691823b1561212c5760006001600160a01b039360e4938c9383976040519a8b98899763d505accf60e01b89521660048801523060248801528a60448801526064870152608486015260a485015260c48401525af191821561315b576001946140c86140ba936001600160a01b03936140ce9661418e575b509450509450614079565b600061419991612219565b38614183565b6001906141ab816145fc565b0361423c576001600160a01b036141c8911691828530898c614df2565b6001600160a01b03871692833b1561212c576084600092836001600160a01b03966040519788958694631b63c28b60e11b8652828d16600487015230602487015260448601521660648401525af191821561315b5760019261422b575b50614046565b600061423691612219565b38614225565b632091924d60e21b60005260046000fd5b6142bd6142c6946142b76001600160a01b03958695604051602081019161190160f01b83527f000000000000000000000000000000000000000000000000000000000000000060228301526042820152604281526142ac606282612219565b519020923691612255565b906149bd565b909591956149f9565b169116036142d057565b636518c33d60e11b60005260046000fd5b91908110156128f85760a0020190565b91908110156128f85760e0020190565b80516020909101516001600160e01b0319811692919060048210614323575050565b6001600160e01b031960049290920360031b82901b16169150565b604081018051805115614488576060830151156143fd57506001600160a01b038251163081146143e957506000806001600160a01b03845116835190602082519201905af46143a26001600160a01b03614396612a48565b92945b51169251614301565b92156143ad57505050565b6143e59060405193849363df7acb8960e01b8552600485015263ffffffff60e01b166024840152606060448401526064830190612c69565b0390fd5b631b46195760e31b60005260045260246000fd5b6001600160e01b03199061441090614301565b1680600052600760205260ff6040600020541615156001600160a01b03845116906144715750506000806001600160a01b03845116608085015190845191602083519301915af16143a26001600160a01b0361446a612a48565b9294614399565b6375e81e2960e11b60005260045260245260446000fd5b505050565b6000906001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036144ba5750503190565b90916001600160a01b03602460209260405194859384926370a0823160e01b84521660048301525afa9182156136805780926144f557505090565b9091506020823d60201161451e575b8161451160209383612219565b8101031261367557505190565b3d9150614504565b6040519061453560a083612219565b607e82527f286164647265737320746f6b656e2c75696e7432353620616d6f756e742900006080837f445a61705472616e736665725769746e657373207769746e65737329445a617060208201527f5472616e736665725769746e6573732861646472657373206f776e65722c616460408201527f647265737320726563697069656e7429546f6b656e5065726d697373696f6e7360608201520152565b91908115614488576001600160a01b03811615612ab7576001600160a01b03613df393166148e3565b6004111561249957565b6000926001600160a01b03811692838552600960205260ff6040862054161561478357602083013592600584101561477f576146418461248f565b600384146147595760408101936146578561245a565b91606061466b6080830135809530906147bd565b9101359383858310614738575b5050506146848161248f565b600181036146fe575050506146a2903061469d8461245a565b614863565b156146ac57505050565b6146bd6001600160a01b039161245a565b1690813b156146fa57829160448392604051948593849263a22cb46560e01b84526004840152600160248401525af180156129fe576129f1575050565b8280fd5b9093956002929550506147108161248f565b1461471c575b50505050565b61472f9361472a309161245a565b614a7b565b38808080614716565b6147456147519387612437565b91309061472a8a61245a565b388083614678565b93509150613df3935061476e6040840161245a565b916080606085013594013592614a7b565b8580fd5b63d4ec784f60e01b85526004849052602485fd5b6020810135600381101561212c576001036147b157503090565b60606122a7910161245a565b604051627eeac760e11b81526001600160a01b039283166004820152602481019390935260209183916044918391165afa90811561315b57600091614800575090565b90506020813d602011614827575b8161481b60209383612219565b8101031261212c575190565b3d915061480e565b15614838575050565b630fb7818b60e01b60005260045260245260446000fd5b356001600160601b038116810361212c5790565b60405163e985e9c560e01b81526001600160a01b039283166004820152928216602484015260209183916044918391165afa90811561315b576000916148a7575090565b6020813d6020116148db575b816148c060209383612219565b810103126148d75751908115158203613675575090565b5080fd5b3d91506148b3565b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152613df39161491f606483612219565b614d27565b906001600160a01b03604051918160208401947f266a51557d4733337e3bc8128e6cd4856463d454dce2a9f9dfcb38e4f6037140865216604084015216606082015260608152614975608082612219565b51902090565b81601f8201121561212c5780516149918161223a565b9261499f6040519485612219565b8184526020828401011161212c576122a79160208085019101612c46565b81519190604183036149ee576149e792506020820151906060604084015193015160001a906150d1565b9192909190565b505060009160029190565b614a02816145fc565b80614a0b575050565b614a14816145fc565b60018103614a2d5763f645eedf60e01b60005260046000fd5b614a36816145fc565b60028103614a53575063fce698f760e01b60005260045260246000fd5b600390614a5f816145fc565b14614a675750565b6335e2f38360e21b60005260045260246000fd5b6001600160a01b039094919392941692833b1561212c576001600160a01b039260c4916040519586948593637921219560e11b85528760009a8b998a961660048801521660248601526044850152606484015260a060848401528160a48401525af180156129fe576129f1575050565b6001600160a01b031690813b1561212c57604051632142170760e11b81526001600160a01b03918216600482015292166024830152604482019290925290819081606481016129d7565b60209060246001600160a01b039360405194859384926331a9108f60e11b84526004840152165afa90811561315b57600091614b6f575090565b6020813d602011614ba6575b81614b8860209383612219565b810103126148d75751906001600160a01b0382168203613675575090565b3d9150614b7b565b519065ffffffffffff8216820361212c57565b9081606091031261212c5780516001600160a01b038116810361212c57916122a76040614bf060208501614bae565b9301614bae565b916001600160a01b038216923084146139c557604051636eb1769f60e11b81523060048201526001600160a01b039384166024820152921691602081604481865afa90811561315b57600091614cf5575b5010614c52575050565b604051906020600081840163095ea7b360e01b81528560248601528119604486015260448552614c83606486612219565b84519082855af16000513d82614cd9575b505015614ca057505050565b61491f613df3936040519063095ea7b360e01b602083015260248201526000604482015260448152614cd3606482612219565b82614d27565b909150614ced5750803b15155b3880614c94565b600114614ce6565b90506020813d602011614d1f575b81614d1060209383612219565b8101031261212c575138614c48565b3d9150614d03565b906000602091828151910182855af11561315b576000513d614d7657506001600160a01b0381163b155b614d585750565b6001600160a01b0390635274afe760e01b6000521660045260246000fd5b60011415614d51565b600060443d106122a7576040513d600319016004823e8051913d60248401116001600160401b03841117614dec57828201928351916001600160401b038311614de4573d84016003190185840160200111614de457506122a792910160200190612219565b949350505050565b92915050565b9490929181519460009686156150c7576001600160a01b03169583016080848203126150c357614e2460208501614bae565b90614e3160408601614bae565b946060810151916080820151906001600160401b0382116150bf57614e5d92602091820192010161497b565b9160405193608085018581106001600160401b038211176150ab576001600160a01b0365ffffffffffff93928492604052818b168852169788602088015216604086015216606084015260405192614eb4846121fe565b8352602083016001600160a01b038516815260408401918252883b156150a757614f508a936001600160a01b0393848b9465ffffffffffff60606040519a8b998a996302b67b5760e41b8b521660048a0152518481511660248a01528460208201511660448a01528260408201511660648a01520151166084870152511660a48501525160c484015261010060e4840152610104830190612c69565b0381838a5af19081615093575b5061508b576001948660033d1161507b575b6308c379a014614f86575b50505050506136805750565b614f8e614d7f565b9384614f9b575b50614f7a565b60405163927da10560e01b81526001600160a01b03968716600482015290861660248201529190941660448201528594509192606090839060649082905afa9182156150705785908693615046575b506001600160a01b031610159081615032575b501561500d578080808080614f95565b6040516352c3687b60e11b8152602060048201529081906143e5906024830190612c69565b905065ffffffffffff429116101538614ffd565b6001600160a01b039350615069915060603d6060116139be576139af8183612219565b5092614fea565b6040513d87823e3d90fd5b50600487803e865160e01c614f6f565b505050505050565b876150a091989298612219565b9538614f5d565b8980fd5b634e487b7160e01b8c52604160045260248cfd5b8b80fd5b8780fd5b5050505050505050565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161514e579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa1561315b576000516001600160a01b038116156151425790600090600090565b50600090600190600090565b5050506000916003919056fea26469706673582212205c28e7656598fcd625b5ea7d1b67a63a04bd730f5eefa02a8b3b21d12bd30bcc64736f6c634300081e003300000000000000000000000045679cdf728abdcdfce0f03a8f1d22ba49babc72000000000000000000000000545044020ffa4611fb0f2b7ede12d13becfceca300000000000000000000000092e5d0beef9793c49051481630db2392fed55c89000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3c67d1657868aa5146eaf24fb879fb1fdec3d2d493b3683a61c9c2f4fb285113173df26dc0b31f29cea42020922f5d18e1c7a923ec0a269f298f6fb7cd1da8b5f
Deployed Bytecode
0x61036080604052600436101561001e575b50361561001c57600080fd5b005b600061032052610320513560e01c90816301ffc9a7146120c55750806312261ee71461209c578063150b7a02146120475780631785f53c14611fd25780632cdf2c3514611f645780632dfb524d14611f3b578063335abd4514611ef557806335df8967146119075780633f4ba83a14611871578063429b62e51461182e5780634343ef21146117f15780635437988d146117805780635c975abb1461175b5780636ffe200b1461145d57806370480275146113e557806370ae92d2146113a7578063715018a61461134557806373ae843e146112a35780637afa1d40146111e25780637d1d0d2b146110495780638161988d14610f475780638419330114610e125780638456cb5914610d7957806388e95c4714610ce15780638da5cb5b14610cb6578063a7229fd914610c32578063ad224fa814610ada578063af1af3b914610ab1578063bc197c8114610a1c578063d9f21eaf146109d9578063e10ea0d7146107ba578063ed7a92c114610338578063f23a6e61146102e3578063f2fde38b1461024d578063f6f38e7c1461020a5763f8965b90146101bf5738610010565b34610203576020366003190112610203576001600160e01b03196101e1612115565b1661032051526007602052602060ff6040610320512054166040519015158152f35b6103205180fd5b34610203576020366003190112610203576001600160a01b0361022b612146565b1661032051526008602052602060ff6040610320512054166040519015158152f35b34610203576020366003190112610203576001600160a01b0361026e612146565b610276612968565b1680156102c7576103205180546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36103205180f35b631e4fbdf760e01b610320515261032051600452602461032051fd5b346102035760a0366003190112610203576102fc612146565b5061030561215c565b506084356001600160401b0381116102035761032590369060040161228c565b5060405163f23a6e6160e01b8152602090f35b6101a0366003190112610203576024356001600160401b038111610203576103649036906004016122e4565b61014052610120526044356001600160401b0381116102035761038b9036906004016122e4565b906064356001600160401b038111610203576103ab9036906004016122e4565b6103b6929192612188565b6101805260e4356101a08190526001600160a01b038116900361020357610104356001600160401b038111610203576103f3903690600401612341565b61012494919435610100526001600160401b036101005111610203576040600319610100513603011261020357610144356001600160401b03811161020357610440903690600401612311565b60a05294610164356001600160401b03811161020357610464903690600401612341565b60805293610184356001600160401b03811161020357610488903690600401612341565b60e05260c052610496612a09565b61049e612a2b565b6104a83447612437565b610160526001600160a01b036101a05116156107a5576001600160a01b036104d56101005160040161245a565b16156107905761053a6040516020810190610505816104f76080518b866124c3565b03601f198101835282612219565b519020986040516020810190610525816104f76101005160040185612778565b51902097608435610180518a8d600435612acc565b6040516020810190610553816104f760a0518c8661284a565b51902090610568366101405161012051612255565b6020815191012094604051602081019060208252610592816104f76040820160e05160c051612886565b519020974260a4351061077b576106ce9a6106b6996106a89861066e966001600160a01b036101805116610320515260056020526040610320512054946040519460208601967f5436d32061e18645e8d0b1ad2e3a2e5279b63a221538a2926f164c63bbb63211885260043560408801526001600160a01b03610180511660608801526001600160a01b036101a05116608088015260a087015260a43560c087015260e0860152610100850152610120840152610140830152610160820152610160815261066261018082612219565b5190206101805161424d565b6001600160a01b036101805116610320515260056020526040610320512060018154019055610180516001600160a01b0360045416613e20565b610180519060805190612e3e565b6106c561010051600401613baa565b60a05190613c3f565b6106e06101a05160e05160c051613c88565b6001600160a01b036106f76101005160040161245a565b166040516001600160a01b036101805116907f96dab0d3a79d5fe6e4b8023f5e33f1a4399ca8959fd3f13024902c11b490f8356004359180610741610140516101205133846128c8565b0390a44761016051811161075b575b600180556103205180f35b61076c610775916101605190612437565b6101a051612a78565b80610750565b63e354457160e01b6103205152600461032051fd5b632b3e1a9d60e01b6103205152600461032051fd5b6332abd14b60e01b6103205152600461032051fd5b610120366003190112610203576004356024356001600160401b038111610203576107e99036906004016122e4565b906044356001600160401b038111610203576108099036906004016122e4565b9290936103205150608435936001600160a01b038516958686036102035760a4356001600160401b03811161020357610846903690600401612341565b9160c4356001600160401b038111610203576040816004019160031990360301126102035760e4356001600160401b0381116102035761088a903690600401612341565b939094610104356001600160401b038111610203576108ad903690600401612341565b906108b6612a09565b6108be612a2b565b6108c83447612437565b9d156107a5576001600160a01b036108df8661245a565b16156107905761097d886001600160a01b03988f956109769061098b988f7fcd2a0ffd0d58b7b7c404a4e5f6551ebba356aa485923870ebcfcf9392cf19caa9f6109a89f9d8d6109909f9361096b94604051610944816104f78d6020830195866124c3565b5190209160405161095d816104f7602082019485612778565b519020606435923392612acc565b338d60045416613e20565b3391612e3e565b61098685613baa565b613c88565b61245a565b1694604051918291602083523396602084019161246e565b0390a4478281116109be57600180556103205180f35b6109d1926109cb91612437565b90612a78565b808080610750565b34610203576020366003190112610203576001600160a01b036109fa612146565b1661032051526009602052602060ff6040610320512054166040519015158152f35b346102035760a036600319011261020357610a35612146565b50610a3e61215c565b506044356001600160401b03811161020357610a5e90369060040161241c565b506064356001600160401b03811161020357610a7e90369060040161241c565b506084356001600160401b03811161020357610a9e90369060040161228c565b5060405163bc197c8160e01b8152602090f35b3461020357610320513660031901126102035760206001600160a01b0360025416604051908152f35b346102035761032051366003190112610203576001600160a01b0361032051541633148015610c16575b15610c01576004547f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3906001600160a01b03821691826001600160a01b03831614610bec57803b610b548161223a565b90610b626040519283612219565b80825260208201928361032051913c5190207fc67d1657868aa5146eaf24fb879fb1fdec3d2d493b3683a61c9c2f4fb285113103610bd7576001600160a01b03191617600455610320517f0a2c9e2facbf5893a918ca6981a7723f870e3c90a3f2cb0c1449e04585e942199080a16103205180f35b630525d2e160e31b6103205152600461032051fd5b630781cfbd60e01b6103205152600461032051fd5b637c51fa9d60e11b6103205152600461032051fd5b50336103205152600660205260ff604061032051205416610b04565b3461020357610c40366122aa565b90610c49612968565b6001600160a01b038116928315610ca1576001600160a01b0381610c91857f879f92dded0f26b83c3e00b12e0395dc72cfc3077343d1854ed6988edd1f909695602095613dc3565b6040519485521692a36103205180f35b6321f7434560e01b6103205152600461032051fd5b3461020357610320513660031901126102035760206001600160a01b03610320515416604051908152f35b34610203576020366003190112610203576001600160a01b03610d02612146565b610d0a612968565b1680151580610d6f575b15610d5a57600280546001600160a01b03191682179055610320517f5023575f35c92bf0a4d83e393b05da7b0e70f45719d04e57e02270324e3c61d29080a26103205180f35b6326ca8b5360e01b6103205152600461032051fd5b5030811415610d14565b346102035761032051366003190112610203576001600160a01b0361032051541633148015610df6575b15610c0157610db0612a2b565b610db8612a2b565b600160ff19600a541617600a557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a16103205180f35b50336103205152600660205260ff604061032051205416610da3565b34610203576020366003190112610203576004356001600160401b03811161020357610e42903690600401612341565b610e4a612968565b610320515b818110610eda575060405190610320515080604083016040845252606082019290610320515b818110610eb2576103205160208501527f53625d2d39d45376dc6f4d009fb607be69cb55bc332ae8612e0c184451a00ad284860385a16103205180f35b90919360208060019263ffffffff60e01b610ecc89612131565b168152019501929101610e75565b610eed610ee88284866128e8565b612953565b610ef681613d34565b610f26579060019163ffffffff60e01b16610320515260076020526040610320512060ff19815416905501610e4f565b63128b2def60e31b610320515263ffffffff60e01b16600452602461032051fd5b34610203576020366003190112610203576004356001600160401b03811161020357610f77903690600401612341565b610f7f612968565b610320515b81811061100d575060405190610320515080604083016040845252606082019290610320515b818110610fe557600160208501527f53625d2d39d45376dc6f4d009fb607be69cb55bc332ae8612e0c184451a00ad284860385a16103205180f35b90919360208060019263ffffffff60e01b610fff89612131565b168152019501929101610faa565b6001906001600160e01b0319611027610ee88386886128e8565b1661032051526007602052604061032051208260ff1982541617905501610f84565b3461020357608036600319011261020357611062612146565b61106a61215c565b906044356001600160401b0381116102035761108a903690600401612341565b9290606435936001600160401b038511610203576110b46001600160a01b03953690600401612341565b9590936110bf612968565b16948515610ca1576110d23683856123d0565b6001600160a01b036110e53684886123d0565b961695863b15610203576111339061112160405193631759616b60e11b85523060048601528a602486015260a0604486015260a4850190613d00565b83810360031901606485015290613d00565b818103906003198201608484015261032051905281602061032051920181610320518a5af180156111d4576111b9575b507ff4120cf4cc98e70461ae37cc5479b37ce728a1cda2c9dd0757905a33c457d4b8936111af916111a160405195869560408752604087019161292f565b91848303602086015261292f565b0390a36103205180f35b610320516111c691612219565b610320516102035786611163565b6040513d61032051823e3d90fd5b34610203576111f03661237e565b916111f9612968565b610320515b82811061124157506112377f9d601757730dea2d7f3dcc03179c9565ebbe275e0409685dc8334eea776d7131936040519384938461290e565b0390a16103205180f35b6001600160a01b0361125761098b8386866128e8565b1690811561128e576001916103205152600860205261128885604061032051209060ff801983541691151516179055565b016111fe565b63d92e233d60e01b6103205152600461032051fd5b34610203576112b13661237e565b916112ba612968565b610320515b8281106112f857506112377fbbeef6f5fd30d06b8e7b13a6e24bb63c8e440baa786df030fb291322661cdb37936040519384938461290e565b6001600160a01b0361130e61098b8386866128e8565b1690811561128e576001916103205152600960205261133f85604061032051209060ff801983541691151516179055565b016112bf565b34610203576103205136600319011261020357611360612968565b6103205180546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a36103205180f35b34610203576020366003190112610203576001600160a01b036113c8612146565b166103205152600560205260206040610320512054604051908152f35b34610203576020366003190112610203576001600160a01b03611406612146565b61140e612968565b16806103205152600660205260406103205120600160ff198254161790557f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e3396103205161032051a26103205180f35b610140366003190112610203576024356001600160401b038111610203576114899036906004016122e4565b906044356001600160401b038111610203576114a99036906004016122e4565b9290916064356001600160401b038111610203576114cb9036906004016122e4565b90936114d5612172565b9460c435916001600160401b038311610203576060836004019360031990360301126102035760e435926001600160401b038411610203576040600319853603011261020357610104356001600160401b0381116102035761153b903690600401612341565b9091610124356001600160401b0381116102035761155d903690600401612341565b979094611568612a09565b611570612a2b565b61157a3447612437565b9c6001600160a01b038d16156107a5576001600160a01b0361159e8a60040161245a565b1615610790576115ed9160405160208101906115bf816104f78a8c866124c3565b5190208a6040516115db816104f7602082019460040185612778565b51902090608435913391600435612acc565b6001600160a01b03600454166116038380612b8f565b93905061160f84612bc4565b610320519094905b81811061170f57505061162a3033614924565b90611633614526565b93833b1561020357611663906040519a8b968795869563fe8ec1a760e01b8752610320519a339160048901612c8e565b039161032051905af19384156111d45789946116eb575b50946116a5926116996116ad9695936001600160a01b03983391612e3e565b61098685600401613baa565b60040161245a565b16917fcd2a0ffd0d58b7b7c404a4e5f6551ebba356aa485923870ebcfcf9392cf19caa60405160208152806109a8339560043595602084019161246e565b6116fd91939594506103205190612219565b6103205161020357879293918a61167a565b8060206117286001936117228780612b8f565b90612c22565b013560405190611737826121b2565b30825260208201526117498289612c32565b526117548188612c32565b5001611617565b34610203576103205136600319011261020357602060ff600a54166040519015158152f35b34610203576020366003190112610203576001600160a01b036117a1612146565b6117a9612968565b16801561128e57600380546001600160a01b03191682179055610320517f1f32c57ae657a3f3ab90e3fe76f97d4f0b6a354bb93021f4eb8f73541fdab4cc9080a26103205180f35b3461020357610320513660031901126102035760206040517fc67d1657868aa5146eaf24fb879fb1fdec3d2d493b3683a61c9c2f4fb28511318152f35b34610203576020366003190112610203576001600160a01b0361184f612146565b1661032051526006602052602060ff6040610320512054166040519015158152f35b346102035761032051366003190112610203576001600160a01b03610320515416331480156118eb575b15610c01576118a8613ce2565b6118b0613ce2565b60ff19600a5416600a557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a16103205180f35b50336103205152600660205260ff60406103205120541661189b565b610180366003190112610203576024356001600160401b038111610203576119339036906004016122e4565b6102c0526102a0526044356001600160401b0381116102035761195a9036906004016122e4565b906064356001600160401b0381116102035761197a9036906004016122e4565b919092611985612172565b6102e052611991612188565b6103405260e435916001600160401b03831161020357606060031984360301126102035761010435610280526001600160401b036102805111610203576040600319610280513603011261020357610124356001600160401b038111610203576119ff903690600401612311565b6102205261020052610144356001600160401b03811161020357611a27903690600401612341565b6101e0526101c052610164356001600160401b03811161020357611a4f903690600401612341565b6102605261024052611a5f612a09565b611a67612a2b565b611a713447612437565b610300526001600160a01b036103405116156107a5576001600160a01b03611a9e6102805160040161245a565b161561079057611af96040516020810190611ac4816104f76101e0516101c051866124c3565b519020926040516020810190611ae4816104f76102805160040185612778565b519020926084356102e0518587600435612acc565b6040516020810190611b16816104f761022051610200518661284a565b519020611b2a366102c0516102a051612255565b6020815191012090604051602081019060208252611b56816104f7604082016102605161024051612886565b51902092604051947f7b11bd3d663bf130c1c54e3ddccc063b44ae0be4e06e969fae5a8603214ea551602087015260043560408701526001600160a01b036102e0511660608701526001600160a01b036103405116608087015260a086015260c085015260e08401526101008301526101208201526101208152611bdc61014082612219565b8051602090910120600454604051926001600160a01b039091169190611c0461014085612219565b61010684527f445a61704761736c6573735a61705769746e657373207769746e65737329445a60208501527f61704761736c6573735a61705769746e6573732862797465733332207478496460408501527f2c6164647265737320757365722c61646472657373206475737452656365697660608501527f65722c62797465733332207a617044617461486173682c62797465733332206660808501527f656544617461486173682c62797465733332206578656375746f72466565446160a08501527f7461486173682c627974657333322063726f7373636861696e4461746148617360c08501527f682c62797465733332207377656570446174614861736829546f6b656e50657260e08501527f6d697373696f6e73286164647265737320746f6b656e2c75696e743235362061610100850152656d6f756e742960d01b610120850152611d576004820180612b8f565b959050611d6386612bc4565b610320519096905b818110611eac575050833b1561020357611da9906040519788968795869563fe8ec1a760e01b8752610320519a6102e0519160040160048901612c8e565b039161032051905af180156111d457611e99575b50611dd26102e0516101e0516101c051612e3e565b611de161028051600401613baa565b611df16102205161020051613c3f565b611e05610340516102605161024051613c88565b6001600160a01b03611e1c6102805160040161245a565b166040516001600160a01b036102e05116907f96dab0d3a79d5fe6e4b8023f5e33f1a4399ca8959fd3f13024902c11b490f8356004359180611e666102c0516102a05133846128c8565b0390a447610300518111611e7f57600180556103205180f35b611e90610775916103005190612437565b61034051612a78565b61032051611ea691612219565b80611dbd565b6001906020611ec2826117226004890180612b8f565b013560405190611ed1826121b2565b3082526020820152611ee3828b612c32565b52611eee818a612c32565b5001611d6b565b3461020357610320513660031901126102035760206040516001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3168152f35b3461020357610320513660031901126102035760206001600160a01b0360035416604051908152f35b3461020357611f72366122aa565b9190611f7c612968565b6001600160a01b038116918215610ca157611fa0846001600160a01b039383612991565b167f6a30e6784464f0d1f4158aa4cb65ae9239b0fa87c7f2c083ee6dde44ba97b5e66103205161032051a46103205180f35b34610203576020366003190112610203576001600160a01b03611ff3612146565b611ffb612968565b1680610320515260066020526040610320512060ff1981541690557fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f6103205161032051a26103205180f35b3461020357608036600319011261020357612060612146565b5061206961215c565b506064356001600160401b0381116102035761208990369060040161228c565b50604051630a85bd0160e11b8152602090f35b3461020357610320513660031901126102035760206001600160a01b0360045416604051908152f35b34610203576020366003190112610203576020906001600160e01b03196120ea612115565b16630271189760e51b8114908115612104575b5015158152f35b6301ffc9a760e01b149050836120fd565b600435906001600160e01b03198216820361212c57565b600080fd5b35906001600160e01b03198216820361212c57565b600435906001600160a01b038216820361212c57565b602435906001600160a01b038216820361212c57565b60a435906001600160a01b038216820361212c57565b60c435906001600160a01b038216820361212c57565b35906001600160a01b038216820361212c57565b604081019081106001600160401b038211176121cd57604052565b634e487b7160e01b600052604160045260246000fd5b60e081019081106001600160401b038211176121cd57604052565b606081019081106001600160401b038211176121cd57604052565b90601f801991011681019081106001600160401b038211176121cd57604052565b6001600160401b0381116121cd57601f01601f191660200190565b9291926122618261223a565b9161226f6040519384612219565b82948184528183011161212c578281602093846000960137010152565b9080601f8301121561212c578160206122a793359101612255565b90565b606090600319011261212c576004356001600160a01b038116810361212c57906024356001600160a01b038116810361212c579060443590565b9181601f8401121561212c578235916001600160401b03831161212c576020838186019501011161212c57565b9181601f8401121561212c578235916001600160401b03831161212c576020808501948460061b01011161212c57565b9181601f8401121561212c578235916001600160401b03831161212c576020808501948460051b01011161212c57565b3590811515820361212c57565b604060031982011261212c57600435906001600160401b03821161212c576123a891600401612341565b9091602435801515810361212c5790565b6001600160401b0381116121cd5760051b60200190565b9291906123dc816123b9565b936123ea6040519586612219565b602085838152019160051b810192831161212c57905b82821061240c57505050565b8135815260209182019101612400565b9080601f8301121561212c578160206122a7933591016123d0565b9190820391821161244457565b634e487b7160e01b600052601160045260246000fd5b356001600160a01b038116810361212c5790565b908060209392818452848401376000828201840152601f01601f1916010190565b6005111561249957565b634e487b7160e01b600052602160045260246000fd5b35906001600160601b038216820361212c57565b82602082016020835252604081019260408160051b830101938360009360de1982360301905b8486106124fa575050505050505090565b90919293949596603f1982820301855287358381121561212c578401906001600160a01b036125288361219e565b1681526001600160a01b0361253f6020840161219e565b16602082015236829003601e19019160408101358381121561212c5781016020813591016001600160401b03821161212c57813603811361212c5761258f9160e0604086015260e085019161246e565b9261259c60608301612371565b151560608401526080820135608084015260a08201358181121561212c578201602081359101946001600160401b03821161212c5760a082023603861361212c5784810360a086015281815260200194906000905b8082106127025750505060c08201359081121561212c570190602082359201926001600160401b03831161212c5760e083023603841361212c578160c060209383039101528281520191906000905b808210612661575050506020806001929901950196019493959291906124e9565b9091928335600581101561212c576126788161248f565b8152602084013590600382101561212c5760e0809160019360208201526001600160a01b036126a96040890161219e565b1660408201526001600160a01b036126c36060890161219e565b1660608201526001600160601b036126dd608089016124af565b16608082015260a087013560a082015260c087013560c0820152019401920190612640565b9091958635600581101561212c576127198161248f565b8152602087013590600582101561212c5760a080918361273a60019561248f565b60208201526001600160a01b0361275360408c0161219e565b16604082015260608a0135606082015260808a013560808201520197019201906125f1565b906020825260608201906001600160a01b036127938261219e565b1660208401526020810135601e198236030181121561212c570190602082359201926001600160401b03831161212c57606083023603841361212c57826080926040808401525201919060005b8181106127ed5750505090565b9091926060806001926001600160a01b036128078861219e565b168152602087013560208201526040870135604082015201940191019190916127e0565b602080916001600160a01b036128408261219e565b1684520135910152565b602080825281018390526040019160005b8181106128685750505090565b9091926040808261287b6001948861282b565b01940192910161285b565b9160209082815201919060005b8181106128a05750505090565b9091926020806001926001600160a01b036128ba8861219e565b168152019401929101612893565b6040906001600160a01b036122a79593168152816020820152019161246e565b91908110156128f85760051b0190565b634e487b7160e01b600052603260045260246000fd5b9160209161292791959495604085526040850191612886565b931515910152565b81835290916001600160fb1b03831161212c5760209260051b809284830137010190565b356001600160e01b03198116810361212c5790565b6001600160a01b0360005416330361297c57565b63118cdaa760e01b6000523360045260246000fd5b9091906001600160a01b0316803b1561212c57604051632142170760e11b81523060048201526001600160a01b0390931660248401526044830191909152819081606481015b918160008096819503925af180156129fe576129f1575050565b816129fb91612219565b50565b6040513d84823e3d90fd5b600260015414612a1a576002600155565b633ee5aeb560e01b60005260046000fd5b60ff600a5416612a3757565b63d93c066560e01b60005260046000fd5b3d15612a73573d90612a598261223a565b91612a676040519384612219565b82523d6000602084013e565b606090565b8115612ac8576001600160a01b03811615612ab757600080809381935af1612a9e612a48565b5015612aa657565b633d2cec6f60e21b60005260046000fd5b6321f7434560e01b60005260046000fd5b5050565b9195939095949294428210612b7e576001600160a01b03612b68961696876000526005602052604060002054926040519360208501957f35e34fdbc052ba343caab21badcef36ff38be3518fe4f444f7e5c95605b69e4787526040860152896060860152608085015260a084015260c083015260e082015260e08152612b5461010082612219565b5190206001600160a01b036003541661424d565b6000526005602052604060002060018154019055565b63e354457160e01b60005260046000fd5b903590601e198136030182121561212c57018035906001600160401b03821161212c57602001918160061b3603831361212c57565b90612bce826123b9565b612bdb6040519182612219565b8281528092612bec601f19916123b9565b019060005b828110612bfd57505050565b602090604051612c0c816121b2565b6000815260008382015282828501015201612bf1565b91908110156128f85760061b0190565b80518210156128f85760209160051b010190565b60005b838110612c595750506000910152565b8181015183820152602001612c49565b90602091612c8281518092818552858086019101612c46565b601f01601f1916010190565b959391979694929060c087526101208701908035601e198236030181121561212c578101602081359101926001600160401b03821161212c578160061b3603841361212c578190606060c08c0152526101408901929060005b818110612d9457505050806020604092013560e08a0152013561010088015286810360208801526020808a51928381520199019060005b818110612d6157505050916122a79697916001600160a01b03612d539416604088015260608701528582036080870152612c69565b9260a081850391015261246e565b9091996020604082612d896001948f51602080916001600160a01b0381511684520151910152565b019b01929101612d1e565b90919360408082612da76001948961282b565b019501929101612ce7565b91908110156128f85760051b8101359060de198136030182121561212c570190565b903590601e198136030182121561212c57018035906001600160401b03821161212c576020019160a082023603831361212c57565b903590601e198136030182121561212c57018035906001600160401b03821161212c576020019160e082023603831361212c57565b919060005b818110612e505750505050565b612e68612e5e828487612db2565b60a0810190612dd4565b90612e7f6020612e7985878a612db2565b0161245a565b9060009260005b81811061374d5750505050612ea9612e9f838588612db2565b60c0810190612e09565b906080612eb785878a612db2565b013590612ec3836123b9565b92612ed16040519485612219565b808452601f19612ee0826123b9565b0136602086013760005b8181106135a35750505050612f00838588612db2565b60e08136031261212c5760405190612f17826121e3565b612f208161219e565b8252612f2e6020820161219e565b602083015260408101356001600160401b03811161212c57612f53903690830161228c565b6040830152612f6460608201612371565b60608301526080810135608083015260a08101356001600160401b03811161212c57810136601f8201121561212c578035612f9e816123b9565b91612fac6040519384612219565b818352602060a081850193028201019036821161212c57602001915b8183106135265750505060a083015260c0810135906001600160401b03821161212c570136601f8201121561212c578035613002816123b9565b916130106040519384612219565b818352602060e081850193028201019036821161212c57602001915b8183106134975750505060c08201526130449061433e565b613052612e9f848689612db2565b60005b818110613167575050505061306d575b600101612e43565b61307b612e5e828487612db2565b61308b6020612e7985878a612db2565b9060005b81811061309f5750505050613065565b6130aa8183866142e1565b8035600581101561212c576004906130c18161248f565b146130d0575b5060010161308f565b6040016130e7846130e08361245a565b3090614863565b156130c7576130fd6001600160a01b039161245a565b1690813b1561212c576000809260446040518095819363a22cb46560e01b83526001600160a01b038a1660048401528160248401525af191821561315b5760019261314a575b50906130c7565b600061315591612219565b38613143565b6040513d6000823e3d90fd5b6131728183856142f1565b35600581101561212c576131858161248f565b6002810361329757506131998183856142f1565b6131a38286612c32565b51906131cd6131b182614797565b926131c860408401946131c38661245a565b61448d565b612437565b6131df60a0830135828181101561482f565b6020820135600381101561212c57600160009114613206575b505050506001905b01613055565b6080830190826001600160601b0361321d8461484f565b16116132288361484f565b9061327757505091613268606061326161325b60019897956001600160601b0361325461326e9961484f565b1690612437565b9461245a565b920161245a565b906145d3565b903880806131f8565b630b12dd8f60e31b825260048490526001600160601b0316602452604490fd5b6132a08161248f565b6001810361333957506132b48183856142f1565b906132db6132c28287612c32565b516131c86132cf85614797565b6131c36040870161245a565b6132ed60a0840135828181101561482f565b602083013592600384101561212c57600180941461330d575b5050613200565b61332d6060613261613332946001600160601b036132546080870161484f565b612a78565b3880613306565b6133428161248f565b600381036133e357506133568183856142f1565b9061336082614797565b604083019061336e8261245a565b906001600160a01b038061338760c08801358095614b35565b169116036133cf57602084013593600385101561212c5760018095146133b0575b505050613200565b6133c160606132616133c79561245a565b90612991565b3880806133a8565b6373514b5160e11b60005260045260246000fd5b6004906133ef8161248f565b146133fd575b600190613200565b6134088183856142f1565b906134138186612c32565b5161341d83614797565b61343e60408501926131c86134318561245a565b60c08801359485916147bd565b9061345160a0860135838181101561482f565b602085013594600386101561212c576001809614613475575b5050505090506133f5565b613486606061326161348e9661245a565b903090614a7b565b3880808061346a565b60e08336031261212c57604051906134ae826121e3565b8335600581101561212c578252602084013590600382101561212c57826020928360e09501526134e06040870161219e565b60408201526134f16060870161219e565b6060820152613502608087016124af565b608082015260a086013560a082015260c086013560c082015281520192019161302c565b60a08336031261212c576040519060a082018281106001600160401b038211176121cd576040528335600581101561212c578252602084013590600582101561212c57826020928360a095015261357f6040870161219e565b60408201526060860135606082015260808601356080820152815201920191612fc8565b6135ae8183856142f1565b602081013590600382101561212c5760009115613723575b6135cf81614797565b908035600581101561371f576135e48161248f565b6002810361368c57506001600160a01b0360248161360660406020950161245a565b169360405194859384926370a0823160e01b84521660048301525afa918215613680578092613648575b5050906001916136408288612c32565b525b01612eea565b9091506020823d8211613678575b8161366360209383612219565b81010312613675575051600138613630565b80fd5b3d9150613656565b604051903d90823e3d90fd5b60019493919061369b8161248f565b8086036136d6575050506001600160a01b03811630036136d057506136c08547612437565b6136ca8288612c32565b52613642565b316136c0565b9091506004906136e58161248f565b146136f2575b5050613642565b61370d9160c06137046040840161245a565b920135916147bd565b6137178288612c32565b5238806136eb565b8380fd5b61372f6060820161245a565b6001600160a01b031630146135c657634e46966960e11b8252600482fd5b6137588183856142e1565b8035600581101561212c5761376c8161248f565b600181036137b5575090602082013591600583101561212c5760026001936137938161248f565b146137a1575b505b01612e86565b60606137af91013586612a78565b38613799565b60006137c08261248f565b600282036139d6575050906020820135600581101561212c576137e28161248f565b6001810361380e57506138098286606061380060406001970161245a565b92013591614bf7565b61379b565b60006138198261248f565b600282036138415750506138098286606061383860406001970161245a565b920135916145d3565b5060049061384e8161248f565b1461385d575b6001915061379b565b6001600160a01b036004541660606138776040850161245a565b930135926001600160a01b03871680156139c55760405163927da10560e01b81523060048201526001600160a01b03838116602483015289166044820152606081606481875afa90811561315b578690600090819361398c575b506001600160a01b03161090811561397a575b506138fd575b50926138f891600194614bf7565b613854565b939091803b1561212c57604051946387517c4560e01b86526001600160a01b038416600487015260248601526001600160a01b03604486015265ffffffffffff606486015260008560848183855af192831561315b576001956138f894613969575b50919450916138ea565b600061397491612219565b3861395f565b65ffffffffffff9150164211386138e4565b6001600160a01b0393506139b7915060603d81116139be575b6139af8183612219565b810190614bc1565b50926138d1565b503d6139a5565b6363ba9bff60e01b60005260046000fd5b506139e08161248f565b60038103613b335750906020820135600581101561212c57613a018161248f565b60018103613ac95750613a3e60408301613a296080613a1f8361245a565b9501358095614b35565b6001600160a01b0330911603613ab55761245a565b6001600160a01b038616156139c5576001600160a01b0316803b1561212c5760405163095ea7b360e01b81526001600160a01b038716600482015260248101939093526000908390604490829084905af191821561315b57600192613aa4575b5061379b565b6000613aaf91612219565b38613a9e565b61098b84308d613ac48561245a565b614aeb565b916001926000613ad88261248f565b60028203613afe57505080866080613af56040613809950161245a565b92013591612991565b50600390613b0b8161248f565b14613b16575061379b565b80868b6080613b2a6040613aaf960161245a565b93013592614aeb565b600490613b3f8161248f565b14613b4e575b5060019061379b565b9450600190613b5f858a8498614606565b90613b45565b903590601e198136030182121561212c57018035906001600160401b03821161212c5760200191606082023603831361212c57565b91908110156128f8576060020190565b60208101613bb88183613b65565b92905060005b838110613bcb5750505050565b80613c09613be861098b600194613be28888613b65565b90613b9a565b613bf18561245a565b6020613c0185613be28a8a613b65565b013591613dc3565b613c39613c1d61098b83613be28888613b65565b6001600160a01b03600254166040613c0185613be28a8a613b65565b01613bbe565b60005b828110613c4e57505050565b80613c82613c6261098b6001948787612c22565b6020613c6f848888612c22565b0135906001600160a01b033391166148e3565b01613c42565b9060005b818110613c995750505050565b600190613cae306131c361098b8487896128e8565b80613cbb575b5001613c8c565b613cdc90866001600160a01b03613cd661098b86898b6128e8565b166148e3565b38613cb4565b60ff600a541615613cef57565b638dfc202b60e01b60005260046000fd5b906020808351928381520192019060005b818110613d1e5750505090565b8251845260209384019390920191600101613d11565b6001600160e01b0319168015613dbd5763095ea7b360e01b8114613dbd5763a9059cbb60e01b8114613dbd576323b872dd60e01b8114613dbd5763a22cb46560e01b8114613dbd57632142170760e11b8114613dbd57635c46a7ef60e11b8114613dbd57637921219560e11b8114613dbd57631759616b60e11b14613db857600090565b600190565b50600190565b91906001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee03613df557613df39250612a78565b565b613df3926145d3565b91908110156128f85760051b81013590605e198136030182121561212c570190565b929160005b838110613e33575050505050565b613e4161098b828685613dfe565b906020613e4f828786613dfe565b0135613e5c828786613dfe565b604081013590601e198136030182121561212c57019283356001600160401b03811161212c576020850190803603821361212c5785019060408683031261212c573594600486101561212c576040810135916001600160401b03831161212c57613ecd92602080920192010161228c565b93613ed7816145fc565b6002810361405d5750835184019060608583031261212c576020850151916040860151956060810151916001600160401b03831161212c57613f2092602080920192010161497b565b6001600160a01b038a16936001600160a01b0360405193613f40856121b2565b16835280602084015260405192613f56846121fe565b8352602083019384526040830196875260405190613f73826121b2565b3082526020820152613f85308a614924565b613f8d614526565b91863b1561212c576040516309be14ff60e11b8152945180516001600160a01b03166004870152602001516024860152939788958695919051604487015251606486015280516001600160a01b031660848601526020015160a48501526001600160a01b038a1660c485015260e484015261010483016101409052610144830161401691612c69565b8281036003190161012484015261402c91612c69565b03815a6000948591f191821561315b5760019261404c575b505b01613e25565b600061405791612219565b38614044565b9093919061406a816145fc565b8061419f5750908051806140d3575b50506040516323b872dd60e01b60208201526001600160a01b03868116602483015230604483015260648201929092526001936140ce92906140c883608481015b03601f198101855284612219565b16614d27565b614046565b8160809181949301031261212c5760208201519160408101519060ff821680920361212c57608060608201519101516001600160a01b03871691823b1561212c5760006001600160a01b039360e4938c9383976040519a8b98899763d505accf60e01b89521660048801523060248801528a60448801526064870152608486015260a485015260c48401525af191821561315b576001946140c86140ba936001600160a01b03936140ce9661418e575b509450509450614079565b600061419991612219565b38614183565b6001906141ab816145fc565b0361423c576001600160a01b036141c8911691828530898c614df2565b6001600160a01b03871692833b1561212c576084600092836001600160a01b03966040519788958694631b63c28b60e11b8652828d16600487015230602487015260448601521660648401525af191821561315b5760019261422b575b50614046565b600061423691612219565b38614225565b632091924d60e21b60005260046000fd5b6142bd6142c6946142b76001600160a01b03958695604051602081019161190160f01b83527f924979066be73ff2684519a607fc11c9e79b757cc44f0104ad8082567d01b57260228301526042820152604281526142ac606282612219565b519020923691612255565b906149bd565b909591956149f9565b169116036142d057565b636518c33d60e11b60005260046000fd5b91908110156128f85760a0020190565b91908110156128f85760e0020190565b80516020909101516001600160e01b0319811692919060048210614323575050565b6001600160e01b031960049290920360031b82901b16169150565b604081018051805115614488576060830151156143fd57506001600160a01b038251163081146143e957506000806001600160a01b03845116835190602082519201905af46143a26001600160a01b03614396612a48565b92945b51169251614301565b92156143ad57505050565b6143e59060405193849363df7acb8960e01b8552600485015263ffffffff60e01b166024840152606060448401526064830190612c69565b0390fd5b631b46195760e31b60005260045260246000fd5b6001600160e01b03199061441090614301565b1680600052600760205260ff6040600020541615156001600160a01b03845116906144715750506000806001600160a01b03845116608085015190845191602083519301915af16143a26001600160a01b0361446a612a48565b9294614399565b6375e81e2960e11b60005260045260245260446000fd5b505050565b6000906001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036144ba5750503190565b90916001600160a01b03602460209260405194859384926370a0823160e01b84521660048301525afa9182156136805780926144f557505090565b9091506020823d60201161451e575b8161451160209383612219565b8101031261367557505190565b3d9150614504565b6040519061453560a083612219565b607e82527f286164647265737320746f6b656e2c75696e7432353620616d6f756e742900006080837f445a61705472616e736665725769746e657373207769746e65737329445a617060208201527f5472616e736665725769746e6573732861646472657373206f776e65722c616460408201527f647265737320726563697069656e7429546f6b656e5065726d697373696f6e7360608201520152565b91908115614488576001600160a01b03811615612ab7576001600160a01b03613df393166148e3565b6004111561249957565b6000926001600160a01b03811692838552600960205260ff6040862054161561478357602083013592600584101561477f576146418461248f565b600384146147595760408101936146578561245a565b91606061466b6080830135809530906147bd565b9101359383858310614738575b5050506146848161248f565b600181036146fe575050506146a2903061469d8461245a565b614863565b156146ac57505050565b6146bd6001600160a01b039161245a565b1690813b156146fa57829160448392604051948593849263a22cb46560e01b84526004840152600160248401525af180156129fe576129f1575050565b8280fd5b9093956002929550506147108161248f565b1461471c575b50505050565b61472f9361472a309161245a565b614a7b565b38808080614716565b6147456147519387612437565b91309061472a8a61245a565b388083614678565b93509150613df3935061476e6040840161245a565b916080606085013594013592614a7b565b8580fd5b63d4ec784f60e01b85526004849052602485fd5b6020810135600381101561212c576001036147b157503090565b60606122a7910161245a565b604051627eeac760e11b81526001600160a01b039283166004820152602481019390935260209183916044918391165afa90811561315b57600091614800575090565b90506020813d602011614827575b8161481b60209383612219565b8101031261212c575190565b3d915061480e565b15614838575050565b630fb7818b60e01b60005260045260245260446000fd5b356001600160601b038116810361212c5790565b60405163e985e9c560e01b81526001600160a01b039283166004820152928216602484015260209183916044918391165afa90811561315b576000916148a7575090565b6020813d6020116148db575b816148c060209383612219565b810103126148d75751908115158203613675575090565b5080fd5b3d91506148b3565b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152613df39161491f606483612219565b614d27565b906001600160a01b03604051918160208401947f266a51557d4733337e3bc8128e6cd4856463d454dce2a9f9dfcb38e4f6037140865216604084015216606082015260608152614975608082612219565b51902090565b81601f8201121561212c5780516149918161223a565b9261499f6040519485612219565b8184526020828401011161212c576122a79160208085019101612c46565b81519190604183036149ee576149e792506020820151906060604084015193015160001a906150d1565b9192909190565b505060009160029190565b614a02816145fc565b80614a0b575050565b614a14816145fc565b60018103614a2d5763f645eedf60e01b60005260046000fd5b614a36816145fc565b60028103614a53575063fce698f760e01b60005260045260246000fd5b600390614a5f816145fc565b14614a675750565b6335e2f38360e21b60005260045260246000fd5b6001600160a01b039094919392941692833b1561212c576001600160a01b039260c4916040519586948593637921219560e11b85528760009a8b998a961660048801521660248601526044850152606484015260a060848401528160a48401525af180156129fe576129f1575050565b6001600160a01b031690813b1561212c57604051632142170760e11b81526001600160a01b03918216600482015292166024830152604482019290925290819081606481016129d7565b60209060246001600160a01b039360405194859384926331a9108f60e11b84526004840152165afa90811561315b57600091614b6f575090565b6020813d602011614ba6575b81614b8860209383612219565b810103126148d75751906001600160a01b0382168203613675575090565b3d9150614b7b565b519065ffffffffffff8216820361212c57565b9081606091031261212c5780516001600160a01b038116810361212c57916122a76040614bf060208501614bae565b9301614bae565b916001600160a01b038216923084146139c557604051636eb1769f60e11b81523060048201526001600160a01b039384166024820152921691602081604481865afa90811561315b57600091614cf5575b5010614c52575050565b604051906020600081840163095ea7b360e01b81528560248601528119604486015260448552614c83606486612219565b84519082855af16000513d82614cd9575b505015614ca057505050565b61491f613df3936040519063095ea7b360e01b602083015260248201526000604482015260448152614cd3606482612219565b82614d27565b909150614ced5750803b15155b3880614c94565b600114614ce6565b90506020813d602011614d1f575b81614d1060209383612219565b8101031261212c575138614c48565b3d9150614d03565b906000602091828151910182855af11561315b576000513d614d7657506001600160a01b0381163b155b614d585750565b6001600160a01b0390635274afe760e01b6000521660045260246000fd5b60011415614d51565b600060443d106122a7576040513d600319016004823e8051913d60248401116001600160401b03841117614dec57828201928351916001600160401b038311614de4573d84016003190185840160200111614de457506122a792910160200190612219565b949350505050565b92915050565b9490929181519460009686156150c7576001600160a01b03169583016080848203126150c357614e2460208501614bae565b90614e3160408601614bae565b946060810151916080820151906001600160401b0382116150bf57614e5d92602091820192010161497b565b9160405193608085018581106001600160401b038211176150ab576001600160a01b0365ffffffffffff93928492604052818b168852169788602088015216604086015216606084015260405192614eb4846121fe565b8352602083016001600160a01b038516815260408401918252883b156150a757614f508a936001600160a01b0393848b9465ffffffffffff60606040519a8b998a996302b67b5760e41b8b521660048a0152518481511660248a01528460208201511660448a01528260408201511660648a01520151166084870152511660a48501525160c484015261010060e4840152610104830190612c69565b0381838a5af19081615093575b5061508b576001948660033d1161507b575b6308c379a014614f86575b50505050506136805750565b614f8e614d7f565b9384614f9b575b50614f7a565b60405163927da10560e01b81526001600160a01b03968716600482015290861660248201529190941660448201528594509192606090839060649082905afa9182156150705785908693615046575b506001600160a01b031610159081615032575b501561500d578080808080614f95565b6040516352c3687b60e11b8152602060048201529081906143e5906024830190612c69565b905065ffffffffffff429116101538614ffd565b6001600160a01b039350615069915060603d6060116139be576139af8183612219565b5092614fea565b6040513d87823e3d90fd5b50600487803e865160e01c614f6f565b505050505050565b876150a091989298612219565b9538614f5d565b8980fd5b634e487b7160e01b8c52604160045260248cfd5b8b80fd5b8780fd5b5050505050505050565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161514e579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa1561315b576000516001600160a01b038116156151425790600090600090565b50600090600190600090565b5050506000916003919056fea26469706673582212205c28e7656598fcd625b5ea7d1b67a63a04bd730f5eefa02a8b3b21d12bd30bcc64736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000045679cdf728abdcdfce0f03a8f1d22ba49babc72000000000000000000000000545044020ffa4611fb0f2b7ede12d13becfceca300000000000000000000000092e5d0beef9793c49051481630db2392fed55c89000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3c67d1657868aa5146eaf24fb879fb1fdec3d2d493b3683a61c9c2f4fb285113173df26dc0b31f29cea42020922f5d18e1c7a923ec0a269f298f6fb7cd1da8b5f
-----Decoded View---------------
Arg [0] : _owner (address): 0x45679CDF728abdcdfce0F03A8f1D22BA49BAbC72
Arg [1] : _protocolFeeVault (address): 0x545044020FFa4611fb0f2B7edE12d13BecfCECA3
Arg [2] : _zapVerifier (address): 0x92E5D0BeEF9793c49051481630Db2392fED55c89
Arg [3] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
Arg [4] : _uniswapPermit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
Arg [5] : _uniswapPermit2BytecodeHash (bytes32): 0xc67d1657868aa5146eaf24fb879fb1fdec3d2d493b3683a61c9c2f4fb2851131
Arg [6] : _salt (bytes32): 0x73df26dc0b31f29cea42020922f5d18e1c7a923ec0a269f298f6fb7cd1da8b5f
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000045679cdf728abdcdfce0f03a8f1d22ba49babc72
Arg [1] : 000000000000000000000000545044020ffa4611fb0f2b7ede12d13becfceca3
Arg [2] : 00000000000000000000000092e5d0beef9793c49051481630db2392fed55c89
Arg [3] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [4] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [5] : c67d1657868aa5146eaf24fb879fb1fdec3d2d493b3683a61c9c2f4fb2851131
Arg [6] : 73df26dc0b31f29cea42020922f5d18e1c7a923ec0a269f298f6fb7cd1da8b5f
Loading...
Loading
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.