ETH Price: $1,821.37 (-4.90%)

Transaction Decoder

Block:
24315631 at Jan-26-2026 01:11:35 AM +UTC
Transaction Fee:
0.000006498988586068 ETH $0.01
Gas Used:
57,794 Gas / 0.112450922 Gwei

Emitted Events:

598 0x328987ac555c05244c8c7262b8e9db418f68d667.0xe346f5c97a360db5188bfa5d3ec5f0583abde420c6ba4d08b6cfe61addc17105( 0xe346f5c97a360db5188bfa5d3ec5f0583abde420c6ba4d08b6cfe61addc17105, 9f87f17729bf40b2f2b18e37f34b278d93dca663f1f75a521f71f42c9d663030 )

Account State Difference:

  Address   Before After State Difference Code
0x1377C01C...E6C2E8e66
4.450687964075558572 Eth
Nonce: 59072
4.450681465086972504 Eth
Nonce: 59073
0.000006498988586068
0x328987AC...18F68D667 0.001145253481413199 Eth0 Eth0.001145253481413199
0x33b41fE1...5454F629c 66.748863163240356743 Eth66.748884324279486743 Eth0.00002116103913
(Titan Builder)
14.158824509992868548 Eth14.158824511423270048 Eth0.0000000014304015
0xadD6CF01...3038eb855 0.001947717072625163 Eth0.003071809514908362 Eth0.001124092442283199

Execution Trace

TransparentUpgradeableProxy.1f3177ba( )
  • 0x615667ccbc0f20d24f614869a79900174262da8c.1f3177ba( )
    • 0x328987ac555c05244c8c7262b8e9db418f68d667.23305703( )
      • EscrowDst.withdraw( secret=9F87F17729BF40B2F2B18E37F34B278D93DCA663F1F75A521F71F42C9D663030, immutables=[{name:orderHash, type:bytes32, order:1, indexed:false, value:D9F866D4931BC6CADCA77C7DE2FAF284EE861363A95B8C80C53F837F1207716E, valueString:D9F866D4931BC6CADCA77C7DE2FAF284EE861363A95B8C80C53F837F1207716E}, {name:hashlock, type:bytes32, order:2, indexed:false, value:F632C5D904CE5A3537C17A1A3EE7814786A12C048983D5636F6C7B3B823324BB, valueString:F632C5D904CE5A3537C17A1A3EE7814786A12C048983D5636F6C7B3B823324BB}, {name:maker, type:uint256, order:3, indexed:false, value:992445795584975339037942674417149536736071563349, valueString:992445795584975339037942674417149536736071563349}, {name:taker, type:uint256, order:4, indexed:false, value:295175440679871226750959972043725454192436798108, valueString:295175440679871226750959972043725454192436798108}, {name:token, type:uint256, order:5, indexed:false, value:0, valueString:0}, {name:amount, type:uint256, order:6, indexed:false, value:1124092442283199, valueString:1124092442283199}, {name:safetyDeposit, type:uint256, order:7, indexed:false, value:21161039130000, valueString:21161039130000}, {name:timelocks, type:uint256, order:8, indexed:false, value:47702654290921032878715067282462025963580548619670438246493860187981152780292, valueString:47702654290921032878715067282462025963580548619670438246493860187981152780292}] )
        • ETH 0.001124092442283199 0xadd6cf0184c7c27696312fb9579593f3038eb855.CALL( )
        • ETH 0.00002116103913 TransparentUpgradeableProxy.CALL( )
          • ETH 0.00002116103913 0x615667ccbc0f20d24f614869a79900174262da8c.DELEGATECALL( )
            File 1 of 2: TransparentUpgradeableProxy
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/TransparentUpgradeableProxy.sol)
            pragma solidity ^0.8.20;
            import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
            import {ERC1967Proxy} from "../ERC1967/ERC1967Proxy.sol";
            import {IERC1967} from "../../interfaces/IERC1967.sol";
            import {ProxyAdmin} from "./ProxyAdmin.sol";
            /**
             * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}
             * does not implement this interface directly, and its upgradeability mechanism is implemented by an internal dispatch
             * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not
             * include them in the ABI so this interface must be used to interact with it.
             */
            interface ITransparentUpgradeableProxy is IERC1967 {
                function upgradeToAndCall(address, bytes calldata) external payable;
            }
            /**
             * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance.
             *
             * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
             * clashing], which can potentially be used in an attack, this contract uses the
             * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
             * things that go hand in hand:
             *
             * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
             * that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself.
             * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to
             * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating
             * the proxy admin cannot fallback to the target implementation.
             *
             * These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a
             * dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to
             * call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and
             * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative
             * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership.
             *
             * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not
             * inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch
             * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to
             * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the
             * implementation.
             *
             * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a
             * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract.
             *
             * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an
             * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be
             * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an
             * undesirable state where the admin slot is different from the actual admin. Relying on the value of the admin slot
             * is generally fine if the implementation is trusted.
             *
             * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the
             * compiler will not check that there are no selector conflicts, due to the note above. A selector clash between any new
             * function and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This
             * could render the `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency.
             */
            contract TransparentUpgradeableProxy is ERC1967Proxy {
                // An immutable address for the admin to avoid unnecessary SLOADs before each call
                // at the expense of removing the ability to change the admin once it's set.
                // This is acceptable if the admin is always a ProxyAdmin instance or similar contract
                // with its own ability to transfer the permissions to another account.
                address private immutable _admin;
                /**
                 * @dev The proxy caller is the current admin, and can't fallback to the proxy target.
                 */
                error ProxyDeniedAdminAccess();
                /**
                 * @dev Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`,
                 * backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in
                 * {ERC1967Proxy-constructor}.
                 */
                constructor(address _logic, address initialOwner, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
                    _admin = address(new ProxyAdmin(initialOwner));
                    // Set the storage value and emit an event for ERC-1967 compatibility
                    ERC1967Utils.changeAdmin(_proxyAdmin());
                }
                /**
                 * @dev Returns the admin of this proxy.
                 */
                function _proxyAdmin() internal view virtual returns (address) {
                    return _admin;
                }
                /**
                 * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior.
                 */
                function _fallback() internal virtual override {
                    if (msg.sender == _proxyAdmin()) {
                        if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) {
                            revert ProxyDeniedAdminAccess();
                        } else {
                            _dispatchUpgradeToAndCall();
                        }
                    } else {
                        super._fallback();
                    }
                }
                /**
                 * @dev Upgrade the implementation of the proxy. See {ERC1967Utils-upgradeToAndCall}.
                 *
                 * Requirements:
                 *
                 * - If `data` is empty, `msg.value` must be zero.
                 */
                function _dispatchUpgradeToAndCall() private {
                    (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
                    ERC1967Utils.upgradeToAndCall(newImplementation, data);
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)
            pragma solidity ^0.8.20;
            import {IBeacon} from "../beacon/IBeacon.sol";
            import {Address} from "../../utils/Address.sol";
            import {StorageSlot} from "../../utils/StorageSlot.sol";
            /**
             * @dev This abstract contract provides getters and event emitting update functions for
             * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.
             */
            library ERC1967Utils {
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Emitted when the beacon is changed.
                 */
                event BeaconUpgraded(address indexed beacon);
                /**
                 * @dev Storage slot with the address of the current implementation.
                 * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
                 */
                // solhint-disable-next-line private-vars-leading-underscore
                bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
                /**
                 * @dev The `implementation` of the proxy is invalid.
                 */
                error ERC1967InvalidImplementation(address implementation);
                /**
                 * @dev The `admin` of the proxy is invalid.
                 */
                error ERC1967InvalidAdmin(address admin);
                /**
                 * @dev The `beacon` of the proxy is invalid.
                 */
                error ERC1967InvalidBeacon(address beacon);
                /**
                 * @dev An upgrade function sees `msg.value > 0` that may be lost.
                 */
                error ERC1967NonPayable();
                /**
                 * @dev Returns the current implementation address.
                 */
                function getImplementation() internal view returns (address) {
                    return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the ERC-1967 implementation slot.
                 */
                function _setImplementation(address newImplementation) private {
                    if (newImplementation.code.length == 0) {
                        revert ERC1967InvalidImplementation(newImplementation);
                    }
                    StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
                }
                /**
                 * @dev Performs implementation upgrade with additional setup call if data is nonempty.
                 * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
                 * to avoid stuck value in the contract.
                 *
                 * Emits an {IERC1967-Upgraded} event.
                 */
                function upgradeToAndCall(address newImplementation, bytes memory data) internal {
                    _setImplementation(newImplementation);
                    emit Upgraded(newImplementation);
                    if (data.length > 0) {
                        Address.functionDelegateCall(newImplementation, data);
                    } else {
                        _checkNonPayable();
                    }
                }
                /**
                 * @dev Storage slot with the admin of the contract.
                 * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
                 */
                // solhint-disable-next-line private-vars-leading-underscore
                bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
                /**
                 * @dev Returns the current admin.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
                 * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
                 */
                function getAdmin() internal view returns (address) {
                    return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
                }
                /**
                 * @dev Stores a new address in the ERC-1967 admin slot.
                 */
                function _setAdmin(address newAdmin) private {
                    if (newAdmin == address(0)) {
                        revert ERC1967InvalidAdmin(address(0));
                    }
                    StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
                }
                /**
                 * @dev Changes the admin of the proxy.
                 *
                 * Emits an {IERC1967-AdminChanged} event.
                 */
                function changeAdmin(address newAdmin) internal {
                    emit AdminChanged(getAdmin(), newAdmin);
                    _setAdmin(newAdmin);
                }
                /**
                 * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
                 * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
                 */
                // solhint-disable-next-line private-vars-leading-underscore
                bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
                /**
                 * @dev Returns the current beacon.
                 */
                function getBeacon() internal view returns (address) {
                    return StorageSlot.getAddressSlot(BEACON_SLOT).value;
                }
                /**
                 * @dev Stores a new beacon in the ERC-1967 beacon slot.
                 */
                function _setBeacon(address newBeacon) private {
                    if (newBeacon.code.length == 0) {
                        revert ERC1967InvalidBeacon(newBeacon);
                    }
                    StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
                    address beaconImplementation = IBeacon(newBeacon).implementation();
                    if (beaconImplementation.code.length == 0) {
                        revert ERC1967InvalidImplementation(beaconImplementation);
                    }
                }
                /**
                 * @dev Change the beacon and trigger a setup call if data is nonempty.
                 * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
                 * to avoid stuck value in the contract.
                 *
                 * Emits an {IERC1967-BeaconUpgraded} event.
                 *
                 * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
                 * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
                 * efficiency.
                 */
                function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
                    _setBeacon(newBeacon);
                    emit BeaconUpgraded(newBeacon);
                    if (data.length > 0) {
                        Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
                    } else {
                        _checkNonPayable();
                    }
                }
                /**
                 * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
                 * if an upgrade doesn't perform an initialization call.
                 */
                function _checkNonPayable() private {
                    if (msg.value > 0) {
                        revert ERC1967NonPayable();
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)
            pragma solidity ^0.8.20;
            import {Proxy} from "../Proxy.sol";
            import {ERC1967Utils} from "./ERC1967Utils.sol";
            /**
             * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
             * implementation address that can be changed. This address is stored in storage in the location specified by
             * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the
             * implementation behind the proxy.
             */
            contract ERC1967Proxy is Proxy {
                /**
                 * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
                 *
                 * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
                 * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
                 *
                 * Requirements:
                 *
                 * - If `data` is empty, `msg.value` must be zero.
                 */
                constructor(address implementation, bytes memory _data) payable {
                    ERC1967Utils.upgradeToAndCall(implementation, _data);
                }
                /**
                 * @dev Returns the current implementation address.
                 *
                 * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
                 * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
                 * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
                 */
                function _implementation() internal view virtual override returns (address) {
                    return ERC1967Utils.getImplementation();
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
            pragma solidity ^0.8.20;
            /**
             * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
             */
            interface IERC1967 {
                /**
                 * @dev Emitted when the implementation is upgraded.
                 */
                event Upgraded(address indexed implementation);
                /**
                 * @dev Emitted when the admin account has changed.
                 */
                event AdminChanged(address previousAdmin, address newAdmin);
                /**
                 * @dev Emitted when the beacon is changed.
                 */
                event BeaconUpgraded(address indexed beacon);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/ProxyAdmin.sol)
            pragma solidity ^0.8.20;
            import {ITransparentUpgradeableProxy} from "./TransparentUpgradeableProxy.sol";
            import {Ownable} from "../../access/Ownable.sol";
            /**
             * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
             * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
             */
            contract ProxyAdmin is Ownable {
                /**
                 * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)`
                 * and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
                 * while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string.
                 * If the getter returns `"5.0.0"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must
                 * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
                 * during an upgrade.
                 */
                string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
                /**
                 * @dev Sets the initial owner who can perform upgrades.
                 */
                constructor(address initialOwner) Ownable(initialOwner) {}
                /**
                 * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.
                 * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}.
                 *
                 * Requirements:
                 *
                 * - This contract must be the admin of `proxy`.
                 * - If `data` is empty, `msg.value` must be zero.
                 */
                function upgradeAndCall(
                    ITransparentUpgradeableProxy proxy,
                    address implementation,
                    bytes memory data
                ) public payable virtual onlyOwner {
                    proxy.upgradeToAndCall{value: msg.value}(implementation, data);
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
            pragma solidity ^0.8.20;
            /**
             * @dev This is the interface that {BeaconProxy} expects of its beacon.
             */
            interface IBeacon {
                /**
                 * @dev Must return an address that can be used as a delegate call target.
                 *
                 * {UpgradeableBeacon} will check that this address is a contract.
                 */
                function implementation() external view returns (address);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.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
                        /// @solidity memory-safe-assembly
                        assembly {
                            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.0) (utils/StorageSlot.sol)
            // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
            pragma solidity ^0.8.20;
            /**
             * @dev Library for reading and writing primitive types to specific storage slots.
             *
             * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
             * This library helps with reading and writing to such slots without the need for inline assembly.
             *
             * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
             *
             * Example usage to set ERC-1967 implementation slot:
             * ```solidity
             * contract ERC1967 {
             *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
             *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
             *
             *     function _getImplementation() internal view returns (address) {
             *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
             *     }
             *
             *     function _setImplementation(address newImplementation) internal {
             *         require(newImplementation.code.length > 0);
             *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
             *     }
             * }
             * ```
             *
             * TIP: Consider using this library along with {SlotDerivation}.
             */
            library StorageSlot {
                struct AddressSlot {
                    address value;
                }
                struct BooleanSlot {
                    bool value;
                }
                struct Bytes32Slot {
                    bytes32 value;
                }
                struct Uint256Slot {
                    uint256 value;
                }
                struct Int256Slot {
                    int256 value;
                }
                struct StringSlot {
                    string value;
                }
                struct BytesSlot {
                    bytes value;
                }
                /**
                 * @dev Returns an `AddressSlot` with member `value` located at `slot`.
                 */
                function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
                 */
                function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
                 */
                function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
                 */
                function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `Int256Slot` with member `value` located at `slot`.
                 */
                function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `StringSlot` with member `value` located at `slot`.
                 */
                function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
                 */
                function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := store.slot
                    }
                }
                /**
                 * @dev Returns an `BytesSlot` with member `value` located at `slot`.
                 */
                function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := slot
                    }
                }
                /**
                 * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
                 */
                function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        r.slot := store.slot
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)
            pragma solidity ^0.8.20;
            /**
             * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
             * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
             * be specified by overriding the virtual {_implementation} function.
             *
             * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
             * different contract through the {_delegate} function.
             *
             * The success and return data of the delegated call will be returned back to the caller of the proxy.
             */
            abstract contract Proxy {
                /**
                 * @dev Delegates the current call to `implementation`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _delegate(address implementation) internal virtual {
                    assembly {
                        // Copy msg.data. We take full control of memory in this inline assembly
                        // block because it will not return to Solidity code. We overwrite the
                        // Solidity scratch pad at memory position 0.
                        calldatacopy(0, 0, calldatasize())
                        // Call the implementation.
                        // out and outsize are 0 because we don't know the size yet.
                        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
                        // Copy the returned data.
                        returndatacopy(0, 0, returndatasize())
                        switch result
                        // delegatecall returns 0 on error.
                        case 0 {
                            revert(0, returndatasize())
                        }
                        default {
                            return(0, returndatasize())
                        }
                    }
                }
                /**
                 * @dev This is a virtual function that should be overridden so it returns the address to which the fallback
                 * function and {_fallback} should delegate.
                 */
                function _implementation() internal view virtual returns (address);
                /**
                 * @dev Delegates the current call to the address returned by `_implementation()`.
                 *
                 * This function does not return to its internal call site, it will return directly to the external caller.
                 */
                function _fallback() internal virtual {
                    _delegate(_implementation());
                }
                /**
                 * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
                 * function in the contract matches the call data.
                 */
                fallback() external payable virtual {
                    _fallback();
                }
            }
            // 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
            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.
             */
            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();
            }
            // 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;
                }
            }
            

            File 2 of 2: EscrowDst
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.23;
            import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
            import { SafeERC20 } from "solidity-utils/contracts/libraries/SafeERC20.sol";
            import { AddressLib, Address } from "solidity-utils/contracts/libraries/AddressLib.sol";
            import { Timelocks, TimelocksLib } from "./libraries/TimelocksLib.sol";
            import { IEscrowDst } from "./interfaces/IEscrowDst.sol";
            import { BaseEscrow } from "./BaseEscrow.sol";
            import { Escrow } from "./Escrow.sol";
            /**
             * @title Destination Escrow contract for cross-chain atomic swap.
             * @notice Contract to initially lock funds and then unlock them with verification of the secret presented.
             * @dev Funds are locked in at the time of contract deployment. For this taker calls the `EscrowFactory.createDstEscrow` function.
             * To perform any action, the caller must provide the same Immutables values used to deploy the clone contract.
             * @custom:security-contact security@1inch.io
             */
            contract EscrowDst is Escrow, IEscrowDst {
                using SafeERC20 for IERC20;
                using AddressLib for Address;
                using TimelocksLib for Timelocks;
                constructor(uint32 rescueDelay, IERC20 accessToken) BaseEscrow(rescueDelay, accessToken) {}
                /**
                 * @notice See {IBaseEscrow-withdraw}.
                 * @dev The function works on the time intervals highlighted with capital letters:
                 * ---- contract deployed --/-- finality --/-- PRIVATE WITHDRAWAL --/-- PUBLIC WITHDRAWAL --/-- private cancellation ----
                 */
                function withdraw(bytes32 secret, Immutables calldata immutables)
                    external
                    onlyTaker(immutables)
                    onlyAfter(immutables.timelocks.get(TimelocksLib.Stage.DstWithdrawal))
                    onlyBefore(immutables.timelocks.get(TimelocksLib.Stage.DstCancellation))
                {
                    _withdraw(secret, immutables);
                }
                /**
                 * @notice See {IBaseEscrow-publicWithdraw}.
                 * @dev The function works on the time intervals highlighted with capital letters:
                 * ---- contract deployed --/-- finality --/-- private withdrawal --/-- PUBLIC WITHDRAWAL --/-- private cancellation ----
                 */
                function publicWithdraw(bytes32 secret, Immutables calldata immutables)
                    external
                    onlyAccessTokenHolder()
                    onlyAfter(immutables.timelocks.get(TimelocksLib.Stage.DstPublicWithdrawal))
                    onlyBefore(immutables.timelocks.get(TimelocksLib.Stage.DstCancellation))
                {
                    _withdraw(secret, immutables);
                }
                /**
                 * @notice See {IBaseEscrow-cancel}.
                 * @dev The function works on the time interval highlighted with capital letters:
                 * ---- contract deployed --/-- finality --/-- private withdrawal --/-- public withdrawal --/-- PRIVATE CANCELLATION ----
                 */
                function cancel(Immutables calldata immutables)
                    external
                    onlyTaker(immutables)
                    onlyValidImmutables(immutables)
                    onlyAfter(immutables.timelocks.get(TimelocksLib.Stage.DstCancellation))
                {
                    _uniTransfer(immutables.token.get(), immutables.taker.get(), immutables.amount);
                    _ethTransfer(msg.sender, immutables.safetyDeposit);
                    emit EscrowCancelled();
                }
                /**
                 * @dev Transfers ERC20 (or native) tokens to the maker and native tokens to the caller.
                 * @param immutables The immutable values used to deploy the clone contract.
                 */
                function _withdraw(bytes32 secret, Immutables calldata immutables)
                    internal
                    onlyValidImmutables(immutables)
                    onlyValidSecret(secret, immutables)
                {
                    _uniTransfer(immutables.token.get(), immutables.maker.get(), immutables.amount);
                    _ethTransfer(msg.sender, immutables.safetyDeposit);
                    emit EscrowWithdrawal(secret);
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
            pragma solidity ^0.8.20;
            /**
             * @dev Interface of the ERC-20 standard as defined in the ERC.
             */
            interface IERC20 {
                /**
                 * @dev Emitted when `value` tokens are moved from one account (`from`) to
                 * another (`to`).
                 *
                 * Note that `value` may be zero.
                 */
                event Transfer(address indexed from, address indexed to, uint256 value);
                /**
                 * @dev Emitted when the allowance of a `spender` for an `owner` is set by
                 * a call to {approve}. `value` is the new allowance.
                 */
                event Approval(address indexed owner, address indexed spender, uint256 value);
                /**
                 * @dev Returns the value of tokens in existence.
                 */
                function totalSupply() external view returns (uint256);
                /**
                 * @dev Returns the value of tokens owned by `account`.
                 */
                function balanceOf(address account) external view returns (uint256);
                /**
                 * @dev Moves a `value` amount of tokens from the caller's account to `to`.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transfer(address to, uint256 value) external returns (bool);
                /**
                 * @dev Returns the remaining number of tokens that `spender` will be
                 * allowed to spend on behalf of `owner` through {transferFrom}. This is
                 * zero by default.
                 *
                 * This value changes when {approve} or {transferFrom} are called.
                 */
                function allowance(address owner, address spender) external view returns (uint256);
                /**
                 * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
                 * caller's tokens.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * IMPORTANT: Beware that changing an allowance with this method brings the risk
                 * that someone may use both the old and the new allowance by unfortunate
                 * transaction ordering. One possible solution to mitigate this race
                 * condition is to first reduce the spender's allowance to 0 and set the
                 * desired value afterwards:
                 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                 *
                 * Emits an {Approval} event.
                 */
                function approve(address spender, uint256 value) external returns (bool);
                /**
                 * @dev Moves a `value` amount of tokens from `from` to `to` using the
                 * allowance mechanism. `value` is then deducted from the caller's
                 * allowance.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transferFrom(address from, address to, uint256 value) external returns (bool);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
            import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
            import "../interfaces/IDaiLikePermit.sol";
            import "../interfaces/IPermit2.sol";
            import "../interfaces/IERC7597Permit.sol";
            import "../interfaces/IWETH.sol";
            import "../libraries/RevertReasonForwarder.sol";
            /**
             * @title Implements efficient safe methods for ERC20 interface.
             * @notice Compared to the standard ERC20, this implementation offers several enhancements:
             * 1. more gas-efficient, providing significant savings in transaction costs.
             * 2. support for different permit implementations
             * 3. forceApprove functionality
             * 4. support for WETH deposit and withdraw
             */
            library SafeERC20 {
                error SafeTransferFailed();
                error SafeTransferFromFailed();
                error ForceApproveFailed();
                error SafeIncreaseAllowanceFailed();
                error SafeDecreaseAllowanceFailed();
                error SafePermitBadLength();
                error Permit2TransferAmountTooHigh();
                // Uniswap Permit2 address
                address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
                bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857;  // SafePermitBadLength.selector
                uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
                /**
                 * @notice Fetches the balance of a specific ERC20 token held by an account.
                 * Consumes less gas then regular `ERC20.balanceOf`.
                 * @dev Note that the implementation does not perform dirty bits cleaning, so it is the
                 * responsibility of the caller to make sure that the higher 96 bits of the `account` parameter are clean.
                 * @param token The IERC20 token contract for which the balance will be fetched.
                 * @param account The address of the account whose token balance will be fetched.
                 * @return tokenBalance The balance of the specified ERC20 token held by the account.
                 */
                function safeBalanceOf(
                    IERC20 token,
                    address account
                ) internal view returns(uint256 tokenBalance) {
                    bytes4 selector = IERC20.balanceOf.selector;
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        mstore(0x00, selector)
                        mstore(0x04, account)
                        let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20)
                        tokenBalance := mload(0)
                        if or(iszero(success), lt(returndatasize(), 0x20)) {
                            let ptr := mload(0x40)
                            returndatacopy(ptr, 0, returndatasize())
                            revert(ptr, returndatasize())
                        }
                    }
                }
                /**
                 * @notice Attempts to safely transfer tokens from one address to another.
                 * @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom.
                 * Either requires `true` in return data, or requires target to be smart-contract and empty return data.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.
                 * @param token The IERC20 token contract from which the tokens will be transferred.
                 * @param from The address from which the tokens will be transferred.
                 * @param to The address to which the tokens will be transferred.
                 * @param amount The amount of tokens to transfer.
                 * @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom.
                 */
                function safeTransferFromUniversal(
                    IERC20 token,
                    address from,
                    address to,
                    uint256 amount,
                    bool permit2
                ) internal {
                    if (permit2) {
                        safeTransferFromPermit2(token, from, to, amount);
                    } else {
                        safeTransferFrom(token, from, to, amount);
                    }
                }
                /**
                 * @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard.
                 * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.
                 * @param token The IERC20 token contract from which the tokens will be transferred.
                 * @param from The address from which the tokens will be transferred.
                 * @param to The address to which the tokens will be transferred.
                 * @param amount The amount of tokens to transfer.
                 */
                function safeTransferFrom(
                    IERC20 token,
                    address from,
                    address to,
                    uint256 amount
                ) internal {
                    bytes4 selector = token.transferFrom.selector;
                    bool success;
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        let data := mload(0x40)
                        mstore(data, selector)
                        mstore(add(data, 0x04), from)
                        mstore(add(data, 0x24), to)
                        mstore(add(data, 0x44), amount)
                        success := call(gas(), token, 0, data, 100, 0x0, 0x20)
                        if success {
                            switch returndatasize()
                            case 0 {
                                success := gt(extcodesize(token), 0)
                            }
                            default {
                                success := and(gt(returndatasize(), 31), eq(mload(0), 1))
                            }
                        }
                    }
                    if (!success) revert SafeTransferFromFailed();
                }
                /**
                 * @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard.
                 * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.
                 * @param token The IERC20 token contract from which the tokens will be transferred.
                 * @param from The address from which the tokens will be transferred.
                 * @param to The address to which the tokens will be transferred.
                 * @param amount The amount of tokens to transfer.
                 */
                function safeTransferFromPermit2(
                    IERC20 token,
                    address from,
                    address to,
                    uint256 amount
                ) internal {
                    if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh();
                    bytes4 selector = IPermit2.transferFrom.selector;
                    bool success;
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        let data := mload(0x40)
                        mstore(data, selector)
                        mstore(add(data, 0x04), from)
                        mstore(add(data, 0x24), to)
                        mstore(add(data, 0x44), amount)
                        mstore(add(data, 0x64), token)
                        success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0)
                        if success {
                            success := gt(extcodesize(_PERMIT2), 0)
                        }
                    }
                    if (!success) revert SafeTransferFromFailed();
                }
                /**
                 * @notice Attempts to safely transfer tokens to another address.
                 * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `to` parameter are clean.
                 * @param token The IERC20 token contract from which the tokens will be transferred.
                 * @param to The address to which the tokens will be transferred.
                 * @param value The amount of tokens to transfer.
                 */
                function safeTransfer(
                    IERC20 token,
                    address to,
                    uint256 value
                ) internal {
                    if (!_makeCall(token, token.transfer.selector, to, value)) {
                        revert SafeTransferFailed();
                    }
                }
                /**
                 * @notice Attempts to approve a spender to spend a certain amount of tokens.
                 * @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `spender` parameter are clean.
                 * @param token The IERC20 token contract on which the call will be made.
                 * @param spender The address which will spend the funds.
                 * @param value The amount of tokens to be spent.
                 */
                function forceApprove(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    if (!_makeCall(token, token.approve.selector, spender, value)) {
                        if (
                            !_makeCall(token, token.approve.selector, spender, 0) ||
                            !_makeCall(token, token.approve.selector, spender, value)
                        ) {
                            revert ForceApproveFailed();
                        }
                    }
                }
                /**
                 * @notice Safely increases the allowance of a spender.
                 * @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction.
                 * Then uses `forceApprove` to increase the allowance.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `spender` parameter are clean.
                 * @param token The IERC20 token contract on which the call will be made.
                 * @param spender The address which will spend the funds.
                 * @param value The amount of tokens to increase the allowance by.
                 */
                function safeIncreaseAllowance(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    uint256 allowance = token.allowance(address(this), spender);
                    if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed();
                    forceApprove(token, spender, allowance + value);
                }
                /**
                 * @notice Safely decreases the allowance of a spender.
                 * @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction.
                 * Then uses `forceApprove` to increase the allowance.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `spender` parameter are clean.
                 * @param token The IERC20 token contract on which the call will be made.
                 * @param spender The address which will spend the funds.
                 * @param value The amount of tokens to decrease the allowance by.
                 */
                function safeDecreaseAllowance(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    uint256 allowance = token.allowance(address(this), spender);
                    if (value > allowance) revert SafeDecreaseAllowanceFailed();
                    forceApprove(token, spender, allowance - value);
                }
                /**
                 * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.
                 * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
                 * @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
                 * @param token The IERC20 token to execute the permit function on.
                 * @param permit The permit data to be used in the function call.
                 */
                function safePermit(IERC20 token, bytes calldata permit) internal {
                    if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert();
                }
                /**
                 * @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters.
                 * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
                 * @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean.
                 * @param token The IERC20 token to execute the permit function on.
                 * @param owner The owner of the tokens for which the permit is made.
                 * @param spender The spender allowed to spend the tokens by the permit.
                 * @param permit The permit data to be used in the function call.
                 */
                function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal {
                    if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert();
                }
                /**
                 * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.
                 * @dev Invokes `tryPermit` with sender as owner and contract as spender.
                 * @param token The IERC20 token to execute the permit function on.
                 * @param permit The permit data to be used in the function call.
                 * @return success Returns true if the permit function was successfully executed, false otherwise.
                 */
                function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) {
                    return tryPermit(token, msg.sender, address(this), permit);
                }
                /**
                 * @notice The function attempts to call the permit function on a given ERC20 token.
                 * @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, IERC7597Permit and IPermit2.
                 * It accommodates both Compact and Full formats of these permit types.
                 * Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter
                 * for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by
                 * gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and
                 * zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one
                 * before invocation for optimized performance.
                 * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
                 * the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean.
                 * @param token The address of the ERC20 token on which to call the permit function.
                 * @param owner The owner of the tokens. This address should have signed the off-chain permit.
                 * @param spender The address which will be approved for transfer of tokens.
                 * @param permit The off-chain permit data, containing different fields depending on the type of permit function.
                 * @return success A boolean indicating whether the permit call was successful.
                 */
                function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) {
                    // load function selectors for different permit standards
                    bytes4 permitSelector = IERC20Permit.permit.selector;
                    bytes4 daiPermitSelector = IDaiLikePermit.permit.selector;
                    bytes4 permit2Selector = IPermit2.permit.selector;
                    bytes4 erc7597PermitSelector = IERC7597Permit.permit.selector;
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        let ptr := mload(0x40)
                        // Switch case for different permit lengths, indicating different permit standards
                        switch permit.length
                        // Compact IERC20Permit
                        case 100 {
                            mstore(ptr, permitSelector)     // store selector
                            mstore(add(ptr, 0x04), owner)   // store owner
                            mstore(add(ptr, 0x24), spender) // store spender
                            // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)
                            {  // stack too deep
                                let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23
                                let vs := calldataload(add(permit.offset, 0x44))                 // loads permit.offset 0x44..0x63
                                calldatacopy(add(ptr, 0x44), permit.offset, 0x20)            // store value     = copy permit.offset 0x00..0x19
                                mstore(add(ptr, 0x64), sub(deadline, 1))                     // store deadline  = deadline - 1
                                mstore(add(ptr, 0x84), add(27, shr(255, vs)))                // store v         = most significant bit of vs + 27 (27 or 28)
                                calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r         = copy permit.offset 0x24..0x43
                                mstore(add(ptr, 0xc4), shr(1, shl(1, vs)))                   // store s         = vs without most significant bit
                            }
                            // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
                            success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
                        }
                        // Compact IDaiLikePermit
                        case 72 {
                            mstore(ptr, daiPermitSelector)  // store selector
                            mstore(add(ptr, 0x04), owner)   // store owner
                            mstore(add(ptr, 0x24), spender) // store spender
                            // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)
                            {  // stack too deep
                                let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07
                                let vs := calldataload(add(permit.offset, 0x28))               // loads permit.offset 0x28..0x47
                                mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce   = copy permit.offset 0x00..0x03
                                mstore(add(ptr, 0x64), sub(expiry, 1))                        // store expiry  = expiry - 1
                                mstore(add(ptr, 0x84), true)                                  // store allowed = true
                                mstore(add(ptr, 0xa4), add(27, shr(255, vs)))                 // store v       = most significant bit of vs + 27 (27 or 28)
                                calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20)  // store r       = copy permit.offset 0x08..0x27
                                mstore(add(ptr, 0xe4), shr(1, shl(1, vs)))                    // store s       = vs without most significant bit
                            }
                            // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
                            success := call(gas(), token, 0, ptr, 0x104, 0, 0)
                        }
                        // IERC20Permit
                        case 224 {
                            mstore(ptr, permitSelector)
                            calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
                            // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
                            success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
                        }
                        // IDaiLikePermit
                        case 256 {
                            mstore(ptr, daiPermitSelector)
                            calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
                            // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
                            success := call(gas(), token, 0, ptr, 0x104, 0, 0)
                        }
                        // Compact IPermit2
                        case 96 {
                            // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)
                            mstore(ptr, permit2Selector)  // store selector
                            mstore(add(ptr, 0x04), owner) // store owner
                            mstore(add(ptr, 0x24), token) // store token
                            calldatacopy(add(ptr, 0x50), permit.offset, 0x14)             // store amount = copy permit.offset 0x00..0x13
                            // and(0xffffffffffff, ...) - conversion to uint48
                            mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff)
                            mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b
                            mstore(add(ptr, 0xa4), spender)                               // store spender
                            // and(0xffffffffffff, ...) - conversion to uint48
                            mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff)
                            mstore(add(ptr, 0xe4), 0x100)                                 // store offset = 256
                            mstore(add(ptr, 0x104), 0x40)                                 // store length = 64
                            calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r      = copy permit.offset 0x20..0x3f
                            calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs     = copy permit.offset 0x40..0x5f
                            // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
                            success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
                        }
                        // IPermit2
                        case 352 {
                            mstore(ptr, permit2Selector)
                            calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
                            // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
                            success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
                        }
                        // Dynamic length
                        default {
                            mstore(ptr, erc7597PermitSelector)
                            calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
                            // IERC7597Permit.permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature)
                            success := call(gas(), token, 0, ptr, add(permit.length, 4), 0, 0)
                        }
                    }
                }
                /**
                 * @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns.
                 * @param token The IERC20 token contract on which the call will be made.
                 * @param selector The function signature that is to be called on the token contract.
                 * @param to The address to which the token amount will be transferred.
                 * @param amount The token amount to be transferred.
                 * @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure.
                 * In case of success but no returned data, validates that the contract code exists.
                 * In case of returned data, ensures that it's a boolean `true`.
                 */
                function _makeCall(
                    IERC20 token,
                    bytes4 selector,
                    address to,
                    uint256 amount
                ) private returns (bool success) {
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        let data := mload(0x40)
                        mstore(data, selector)
                        mstore(add(data, 0x04), to)
                        mstore(add(data, 0x24), amount)
                        success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)
                        if success {
                            switch returndatasize()
                            case 0 {
                                success := gt(extcodesize(token), 0)
                            }
                            default {
                                success := and(gt(returndatasize(), 31), eq(mload(0), 1))
                            }
                        }
                    }
                }
                /**
                 * @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`.
                 * @param weth The IWETH token contract.
                 * @param amount The amount of Ether to deposit into the IWETH contract.
                 */
                function safeDeposit(IWETH weth, uint256 amount) internal {
                    if (amount > 0) {
                        bytes4 selector = IWETH.deposit.selector;
                        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                            mstore(0, selector)
                            if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) {
                                let ptr := mload(0x40)
                                returndatacopy(ptr, 0, returndatasize())
                                revert(ptr, returndatasize())
                            }
                        }
                    }
                }
                /**
                 * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`.
                 * @dev Uses inline assembly to interact with the IWETH contract.
                 * @param weth The IWETH token contract.
                 * @param amount The amount of wrapped Ether to withdraw from the IWETH contract.
                 */
                function safeWithdraw(IWETH weth, uint256 amount) internal {
                    bytes4 selector = IWETH.withdraw.selector;
                    assembly ("memory-safe") {  // solhint-disable-line no-inline-assembly
                        mstore(0, selector)
                        mstore(4, amount)
                        if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) {
                            let ptr := mload(0x40)
                            returndatacopy(ptr, 0, returndatasize())
                            revert(ptr, returndatasize())
                        }
                    }
                }
                /**
                 * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient.
                 * Consumes less gas then regular `IWETH.withdraw`.
                 * @param weth The IWETH token contract.
                 * @param amount The amount of wrapped Ether to withdraw from the IWETH contract.
                 * @param to The recipient of the withdrawn Ether.
                 */
                function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal {
                    safeWithdraw(weth, amount);
                    if (to != address(this)) {
                        assembly ("memory-safe") {  // solhint-disable-line no-inline-assembly
                            if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) {
                                let ptr := mload(0x40)
                                returndatacopy(ptr, 0, returndatasize())
                                revert(ptr, returndatasize())
                            }
                        }
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            type Address is uint256;
            /**
            * @notice AddressLib
            * @notice Library for working with addresses encoded as uint256 values, which can include flags in the highest bits.
            */
            library AddressLib {
                uint256 private constant _LOW_160_BIT_MASK = (1 << 160) - 1;
                /**
                * @notice Returns the address representation of a uint256.
                * @param a The uint256 value to convert to an address.
                * @return The address representation of the provided uint256 value.
                */
                function get(Address a) internal pure returns (address) {
                    return address(uint160(Address.unwrap(a) & _LOW_160_BIT_MASK));
                }
                /**
                * @notice Checks if a given flag is set for the provided address.
                * @param a The address to check for the flag.
                * @param flag The flag to check for in the provided address.
                * @return True if the provided flag is set in the address, false otherwise.
                */
                function getFlag(Address a, uint256 flag) internal pure returns (bool) {
                    return (Address.unwrap(a) & flag) != 0;
                }
                /**
                * @notice Returns a uint32 value stored at a specific bit offset in the provided address.
                * @param a The address containing the uint32 value.
                * @param offset The bit offset at which the uint32 value is stored.
                * @return The uint32 value stored in the address at the specified bit offset.
                */
                function getUint32(Address a, uint256 offset) internal pure returns (uint32) {
                    return uint32(Address.unwrap(a) >> offset);
                }
                /**
                * @notice Returns a uint64 value stored at a specific bit offset in the provided address.
                * @param a The address containing the uint64 value.
                * @param offset The bit offset at which the uint64 value is stored.
                * @return The uint64 value stored in the address at the specified bit offset.
                */
                function getUint64(Address a, uint256 offset) internal pure returns (uint64) {
                    return uint64(Address.unwrap(a) >> offset);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.20;
            /**
             * @dev Timelocks for the source and the destination chains plus the deployment timestamp.
             * Timelocks store the number of seconds from the time the contract is deployed to the start of a specific period.
             * For illustrative purposes, it is possible to describe timelocks by two structures:
             * struct SrcTimelocks {
             *     uint256 withdrawal;
             *     uint256 publicWithdrawal;
             *     uint256 cancellation;
             *     uint256 publicCancellation;
             * }
             *
             * struct DstTimelocks {
             *     uint256 withdrawal;
             *     uint256 publicWithdrawal;
             *     uint256 cancellation;
             * }
             *
             * withdrawal: Period when only the taker with a secret can withdraw tokens for taker (source chain) or maker (destination chain).
             * publicWithdrawal: Period when anyone with a secret can withdraw tokens for taker (source chain) or maker (destination chain).
             * cancellation: Period when escrow can only be cancelled by the taker.
             * publicCancellation: Period when escrow can be cancelled by anyone.
             *
             * @custom:security-contact security@1inch.io
             */
            type Timelocks is uint256;
            /**
             * @title Timelocks library for compact storage of timelocks in a uint256.
             */
            library TimelocksLib {
                enum Stage {
                    SrcWithdrawal,
                    SrcPublicWithdrawal,
                    SrcCancellation,
                    SrcPublicCancellation,
                    DstWithdrawal,
                    DstPublicWithdrawal,
                    DstCancellation
                }
                uint256 private constant _DEPLOYED_AT_MASK = 0xffffffff00000000000000000000000000000000000000000000000000000000;
                uint256 private constant _DEPLOYED_AT_OFFSET = 224;
                /**
                 * @notice Sets the Escrow deployment timestamp.
                 * @param timelocks The timelocks to set the deployment timestamp to.
                 * @param value The new Escrow deployment timestamp.
                 * @return The timelocks with the deployment timestamp set.
                 */
                function setDeployedAt(Timelocks timelocks, uint256 value) internal pure returns (Timelocks) {
                    return Timelocks.wrap((Timelocks.unwrap(timelocks) & ~uint256(_DEPLOYED_AT_MASK)) | value << _DEPLOYED_AT_OFFSET);
                }
                /**
                 * @notice Returns the start of the rescue period.
                 * @param timelocks The timelocks to get the rescue delay from.
                 * @return The start of the rescue period.
                 */
                function rescueStart(Timelocks timelocks, uint256 rescueDelay) internal pure returns (uint256) {
                    unchecked {
                        return rescueDelay + (Timelocks.unwrap(timelocks) >> _DEPLOYED_AT_OFFSET);
                    }
                }
                /**
                 * @notice Returns the timelock value for the given stage.
                 * @param timelocks The timelocks to get the value from.
                 * @param stage The stage to get the value for.
                 * @return The timelock value for the given stage.
                 */
                function get(Timelocks timelocks, Stage stage) internal pure returns (uint256) {
                    uint256 data = Timelocks.unwrap(timelocks);
                    uint256 bitShift = uint256(stage) * 32;
                    // The maximum uint32 value will be reached in 2106.
                    return (data >> _DEPLOYED_AT_OFFSET) + uint32(data >> bitShift);
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import { IEscrow } from "./IEscrow.sol";
            /**
             * @title Destination Escrow interface for cross-chain atomic swap.
             * @notice Interface implies withdrawing funds initially and then unlocking them with verification of the secret presented.
             * @custom:security-contact security@1inch.io
             */
            interface IEscrowDst is IEscrow {
                /**
                 * @notice Withdraws funds to maker
                 * @dev Withdrawal can only be made during the withdrawal period and with secret with hash matches the hashlock.
                 * @param secret The secret that unlocks the escrow.
                 * @param immutables The immutables of the escrow contract.
                 */
                function publicWithdraw(bytes32 secret, IEscrow.Immutables calldata immutables) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.23;
            import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
            import { AddressLib, Address } from "solidity-utils/contracts/libraries/AddressLib.sol";
            import { SafeERC20 } from "solidity-utils/contracts/libraries/SafeERC20.sol";
            import { ImmutablesLib } from "./libraries/ImmutablesLib.sol";
            import { Timelocks, TimelocksLib } from "./libraries/TimelocksLib.sol";
            import { IBaseEscrow } from "./interfaces/IBaseEscrow.sol";
            /**
             * @title Base abstract Escrow contract for cross-chain atomic swap.
             * @dev {IBaseEscrow-withdraw}, {IBaseEscrow-cancel} and _validateImmutables functions must be implemented in the derived contracts.
             * @custom:security-contact security@1inch.io
             */
            abstract contract BaseEscrow is IBaseEscrow {
                using AddressLib for Address;
                using SafeERC20 for IERC20;
                using TimelocksLib for Timelocks;
                using ImmutablesLib for Immutables;
                // Token that is used to access public withdraw or cancel functions.
                IERC20 private immutable _ACCESS_TOKEN;
                /// @notice See {IBaseEscrow-RESCUE_DELAY}.
                uint256 public immutable RESCUE_DELAY;
                /// @notice See {IBaseEscrow-FACTORY}.
                address public immutable FACTORY = msg.sender;
                constructor(uint32 rescueDelay, IERC20 accessToken) {
                    RESCUE_DELAY = rescueDelay;
                    _ACCESS_TOKEN = accessToken;
                }
                modifier onlyTaker(Immutables calldata immutables) {
                    if (msg.sender != immutables.taker.get()) revert InvalidCaller();
                    _;
                }
                modifier onlyValidImmutables(Immutables calldata immutables) virtual {
                    _validateImmutables(immutables);
                    _;
                }
                modifier onlyValidSecret(bytes32 secret, Immutables calldata immutables) {
                    if (_keccakBytes32(secret) != immutables.hashlock) revert InvalidSecret();
                    _;
                }
                modifier onlyAfter(uint256 start) {
                    if (block.timestamp < start) revert InvalidTime();
                    _;
                }
                modifier onlyBefore(uint256 stop) {
                    if (block.timestamp >= stop) revert InvalidTime();
                    _;
                }
                modifier onlyAccessTokenHolder() {
                    if (_ACCESS_TOKEN.balanceOf(msg.sender) == 0) revert InvalidCaller();
                    _;
                }
                /**
                 * @notice See {IBaseEscrow-rescueFunds}.
                 */
                function rescueFunds(address token, uint256 amount, Immutables calldata immutables)
                    external
                    onlyTaker(immutables)
                    onlyValidImmutables(immutables)
                    onlyAfter(immutables.timelocks.rescueStart(RESCUE_DELAY))
                {
                    _uniTransfer(token, msg.sender, amount);
                    emit FundsRescued(token, amount);
                }
                /**
                 * @dev Transfers ERC20 or native tokens to the recipient.
                 */
                function _uniTransfer(address token, address to, uint256 amount) internal {
                    if (token == address(0)) {
                        _ethTransfer(to, amount);
                    } else {
                        IERC20(token).safeTransfer(to, amount);
                    }
                }
                /**
                 * @dev Transfers native tokens to the recipient.
                 */
                function _ethTransfer(address to, uint256 amount) internal {
                    (bool success,) = to.call{ value: amount }("");
                    if (!success) revert NativeTokenSendingFailure();
                }
                /**
                 * @dev Should verify that the computed escrow address matches the address of this contract.
                 */
                function _validateImmutables(Immutables calldata immutables) internal view virtual;
                /**
                 * @dev Computes the Keccak-256 hash of the secret.
                 * @param secret The secret that unlocks the escrow.
                 * @return ret The computed hash.
                 */
                function _keccakBytes32(bytes32 secret) private pure returns (bytes32 ret) {
                    assembly ("memory-safe") {
                        mstore(0, secret)
                        ret := keccak256(0, 0x20)
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity 0.8.23;
            import { Create2 } from "openzeppelin-contracts/contracts/utils/Create2.sol";
            import { ImmutablesLib } from "./libraries/ImmutablesLib.sol";
            import { ProxyHashLib } from "./libraries/ProxyHashLib.sol";
            import { IEscrow } from "./interfaces/IEscrow.sol";
            import { BaseEscrow } from "./BaseEscrow.sol";
            /**
             * @title Abstract Escrow contract for cross-chain atomic swap.
             * @dev {IBaseEscrow-withdraw} and {IBaseEscrow-cancel} functions must be implemented in the derived contracts.
             * @custom:security-contact security@1inch.io
             */
            abstract contract Escrow is BaseEscrow, IEscrow {
                using ImmutablesLib for Immutables;
                /// @notice See {IEscrow-PROXY_BYTECODE_HASH}.
                bytes32 public immutable PROXY_BYTECODE_HASH = ProxyHashLib.computeProxyBytecodeHash(address(this));
                /**
                 * @dev Verifies that the computed escrow address matches the address of this contract.
                 */
                function _validateImmutables(Immutables calldata immutables) internal view virtual override {
                    bytes32 salt = immutables.hash();
                    if (Create2.computeAddress(salt, PROXY_BYTECODE_HASH, FACTORY) != address(this)) {
                        revert InvalidImmutables();
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.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
            pragma solidity ^0.8.0;
            /**
             * @title IDaiLikePermit
             * @dev Interface for Dai-like permit function allowing token spending via signatures.
             */
            interface IDaiLikePermit {
                /**
                 * @notice Approves spending of tokens via off-chain signatures.
                 * @param holder Token holder's address.
                 * @param spender Spender's address.
                 * @param nonce Current nonce of the holder.
                 * @param expiry Time when the permit expires.
                 * @param allowed True to allow, false to disallow spending.
                 * @param v, r, s Signature components.
                 */
                function permit(
                    address holder,
                    address spender,
                    uint256 nonce,
                    uint256 expiry,
                    bool allowed,
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                ) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            /**
             * @title IPermit2
             * @dev Interface for a flexible permit system that extends ERC20 tokens to support permits in tokens lacking native permit functionality.
             */
            interface IPermit2 {
                /**
                 * @dev Struct for holding permit details.
                 * @param token ERC20 token address for which the permit is issued.
                 * @param amount The maximum amount allowed to spend.
                 * @param expiration Timestamp until which the permit is valid.
                 * @param nonce An incrementing value for each signature, unique per owner, token, and spender.
                 */
                struct PermitDetails {
                    address token;
                    uint160 amount;
                    uint48 expiration;
                    uint48 nonce;
                }
                /**
                 * @dev Struct for a single token allowance permit.
                 * @param details Permit details including token, amount, expiration, and nonce.
                 * @param spender Address authorized to spend the tokens.
                 * @param sigDeadline Deadline for the permit signature, ensuring timeliness of the permit.
                 */
                struct PermitSingle {
                    PermitDetails details;
                    address spender;
                    uint256 sigDeadline;
                }
                /**
                 * @dev Struct for packed allowance data to optimize storage.
                 * @param amount Amount allowed.
                 * @param expiration Permission expiry timestamp.
                 * @param nonce Unique incrementing value for tracking allowances.
                 */
                struct PackedAllowance {
                    uint160 amount;
                    uint48 expiration;
                    uint48 nonce;
                }
                /**
                 * @notice Executes a token transfer from one address to another.
                 * @param user The token owner's address.
                 * @param spender The address authorized to spend the tokens.
                 * @param amount The amount of tokens to transfer.
                 * @param token The address of the token being transferred.
                 */
                function transferFrom(address user, address spender, uint160 amount, address token) external;
                /**
                 * @notice Issues a permit for spending tokens via a signed authorization.
                 * @param owner The token owner's address.
                 * @param permitSingle Struct containing the permit details.
                 * @param signature The signature proving the owner authorized the permit.
                 */
                function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;
                /**
                 * @notice Retrieves the allowance details between a token owner and spender.
                 * @param user The token owner's address.
                 * @param token The token address.
                 * @param spender The spender's address.
                 * @return The packed allowance details.
                 */
                function allowance(address user, address token, address spender) external view returns (PackedAllowance memory);
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            /**
             * @title IERC7597Permit
             * @dev A new extension for ERC-2612 permit, which has already been added to USDC v2.2.
             */
            interface IERC7597Permit {
                /**
                 * @notice Update allowance with a signed permit.
                 * @dev Signature bytes can be used for both EOA wallets and contract wallets.
                 * @param owner Token owner's address (Authorizer).
                 * @param spender Spender's address.
                 * @param value Amount of allowance.
                 * @param deadline The time at which the signature expires (unixtime).
                 * @param signature Unstructured bytes signature signed by an EOA wallet or a contract wallet.
                 */
                function permit(
                    address owner,
                    address spender,
                    uint256 value,
                    uint256 deadline,
                    bytes memory signature
                ) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
            /**
             * @title IWETH
             * @dev Interface for wrapper as WETH-like token.
             */
            interface IWETH is IERC20 {
                /**
                 * @notice Emitted when Ether is deposited to get wrapper tokens.
                 */
                event Deposit(address indexed dst, uint256 wad);
                /**
                 * @notice Emitted when wrapper tokens is withdrawn as Ether.
                 */
                event Withdrawal(address indexed src, uint256 wad);
                /**
                 * @notice Deposit Ether to get wrapper tokens.
                 */
                function deposit() external payable;
                /**
                 * @notice Withdraw wrapped tokens as Ether.
                 * @param amount Amount of wrapped tokens to withdraw.
                 */
                function withdraw(uint256 amount) external;
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            /**
             * @title RevertReasonForwarder
             * @notice Provides utilities for forwarding and retrieving revert reasons from failed external calls.
             */
            library RevertReasonForwarder {
                /**
                 * @dev Forwards the revert reason from the latest external call.
                 * This method allows propagating the revert reason of a failed external call to the caller.
                 */
                function reRevert() internal pure {
                    // bubble up revert reason from latest external call
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        let ptr := mload(0x40)
                        returndatacopy(ptr, 0, returndatasize())
                        revert(ptr, returndatasize())
                    }
                }
                /**
                 * @dev Retrieves the revert reason from the latest external call.
                 * This method enables capturing the revert reason of a failed external call for inspection or processing.
                 * @return reason The latest external call revert reason.
                 */
                function reReason() internal pure returns (bytes memory reason) {
                    assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                        reason := mload(0x40)
                        let length := returndatasize()
                        mstore(reason, length)
                        returndatacopy(add(reason, 0x20), 0, length)
                        mstore(0x40, add(reason, add(0x20, length)))
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import { IBaseEscrow } from "./IBaseEscrow.sol";
            /**
             * @title Escrow interface for cross-chain atomic swap.
             * @notice Interface implies locking funds initially and then unlocking them with verification of the secret presented.
             * @custom:security-contact security@1inch.io
             */
            interface IEscrow is IBaseEscrow {
                /// @notice Returns the bytecode hash of the proxy contract.
                function PROXY_BYTECODE_HASH() external view returns (bytes32); // solhint-disable-line func-name-mixedcase
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.20;
            import { IBaseEscrow } from "../interfaces/IBaseEscrow.sol";
            /**
             * @title Library for escrow immutables.
             * @custom:security-contact security@1inch.io
             */
            library ImmutablesLib {
                uint256 internal constant ESCROW_IMMUTABLES_SIZE = 0x100;
                /**
                 * @notice Returns the hash of the immutables.
                 * @param immutables The immutables to hash.
                 * @return ret The computed hash.
                 */
                function hash(IBaseEscrow.Immutables calldata immutables) internal pure returns(bytes32 ret) {
                    assembly ("memory-safe") {
                        let ptr := mload(0x40)
                        calldatacopy(ptr, immutables, ESCROW_IMMUTABLES_SIZE)
                        ret := keccak256(ptr, ESCROW_IMMUTABLES_SIZE)
                    }
                }
                /**
                 * @notice Returns the hash of the immutables.
                 * @param immutables The immutables to hash.
                 * @return ret The computed hash.
                 */
                function hashMem(IBaseEscrow.Immutables memory immutables) internal pure returns(bytes32 ret) {
                    assembly ("memory-safe") {
                        ret := keccak256(immutables, ESCROW_IMMUTABLES_SIZE)
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.0;
            import { Address } from "solidity-utils/contracts/libraries/AddressLib.sol";
            import { Timelocks } from "../libraries/TimelocksLib.sol";
            /**
             * @title Base Escrow interface for cross-chain atomic swap.
             * @notice Interface implies locking funds initially and then unlocking them with verification of the secret presented.
             * @custom:security-contact security@1inch.io
             */
            interface IBaseEscrow {
                struct Immutables {
                    bytes32 orderHash;
                    bytes32 hashlock;  // Hash of the secret.
                    Address maker;
                    Address taker;
                    Address token;
                    uint256 amount;
                    uint256 safetyDeposit;
                    Timelocks timelocks;
                }
                /**
                 * @notice Emitted on escrow cancellation.
                 */
                event EscrowCancelled();
                /**
                 * @notice Emitted when funds are rescued.
                 * @param token The address of the token rescued. Zero address for native token.
                 * @param amount The amount of tokens rescued.
                 */
                event FundsRescued(address token, uint256 amount);
                /**
                 * @notice Emitted on successful withdrawal.
                 * @param secret The secret that unlocks the escrow.
                 */
                event EscrowWithdrawal(bytes32 secret);
                error InvalidCaller();
                error InvalidImmutables();
                error InvalidSecret();
                error InvalidTime();
                error NativeTokenSendingFailure();
                /* solhint-disable func-name-mixedcase */
                /// @notice Returns the delay for rescuing funds from the escrow.
                function RESCUE_DELAY() external view returns (uint256);
                /// @notice Returns the address of the factory that created the escrow.
                function FACTORY() external view returns (address);
                /* solhint-enable func-name-mixedcase */
                /**
                 * @notice Withdraws funds to a predetermined recipient.
                 * @dev Withdrawal can only be made during the withdrawal period and with secret with hash matches the hashlock.
                 * The safety deposit is sent to the caller.
                 * @param secret The secret that unlocks the escrow.
                 * @param immutables The immutables of the escrow contract.
                 */
                function withdraw(bytes32 secret, Immutables calldata immutables) external;
                /**
                 * @notice Cancels the escrow and returns tokens to a predetermined recipient.
                 * @dev The escrow can only be cancelled during the cancellation period.
                 * The safety deposit is sent to the caller.
                 * @param immutables The immutables of the escrow contract.
                 */
                function cancel(Immutables calldata immutables) external;
                /**
                 * @notice Rescues funds from the escrow.
                 * @dev Funds can only be rescued by the taker after the rescue delay.
                 * @param token The address of the token to rescue. Zero address for native token.
                 * @param amount The amount of tokens to rescue.
                 * @param immutables The immutables of the escrow contract.
                 */
                function rescueFunds(address token, uint256 amount, Immutables calldata immutables) external;
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v5.0.0) (utils/Create2.sol)
            pragma solidity ^0.8.20;
            import {Errors} from "./Errors.sol";
            /**
             * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
             * `CREATE2` can be used to compute in advance the address where a smart
             * contract will be deployed, which allows for interesting new mechanisms known
             * as 'counterfactual interactions'.
             *
             * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
             * information.
             */
            library Create2 {
                /**
                 * @dev There's no code to deploy.
                 */
                error Create2EmptyBytecode();
                /**
                 * @dev Deploys a contract using `CREATE2`. The address where the contract
                 * will be deployed can be known in advance via {computeAddress}.
                 *
                 * The bytecode for a contract can be obtained from Solidity with
                 * `type(contractName).creationCode`.
                 *
                 * Requirements:
                 *
                 * - `bytecode` must not be empty.
                 * - `salt` must have not been used for `bytecode` already.
                 * - the factory must have a balance of at least `amount`.
                 * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
                 */
                function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
                    if (address(this).balance < amount) {
                        revert Errors.InsufficientBalance(address(this).balance, amount);
                    }
                    if (bytecode.length == 0) {
                        revert Create2EmptyBytecode();
                    }
                    /// @solidity memory-safe-assembly
                    assembly {
                        addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
                    }
                    if (addr == address(0)) {
                        revert Errors.FailedDeployment();
                    }
                }
                /**
                 * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
                 * `bytecodeHash` or `salt` will result in a new destination address.
                 */
                function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
                    return computeAddress(salt, bytecodeHash, address(this));
                }
                /**
                 * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
                 * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
                 */
                function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
                    /// @solidity memory-safe-assembly
                    assembly {
                        let ptr := mload(0x40) // Get free memory pointer
                        // |                   | ↓ ptr ...  ↓ ptr + 0x0B (start) ...  ↓ ptr + 0x20 ...  ↓ ptr + 0x40 ...   |
                        // |-------------------|---------------------------------------------------------------------------|
                        // | bytecodeHash      |                                                        CCCCCCCCCCCCC...CC |
                        // | salt              |                                      BBBBBBBBBBBBB...BB                   |
                        // | deployer          | 000000...0000AAAAAAAAAAAAAAAAAAA...AA                                     |
                        // | 0xFF              |            FF                                                             |
                        // |-------------------|---------------------------------------------------------------------------|
                        // | memory            | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
                        // | keccak(start, 85) |            ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
                        mstore(add(ptr, 0x40), bytecodeHash)
                        mstore(add(ptr, 0x20), salt)
                        mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
                        let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
                        mstore8(start, 0xff)
                        addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            pragma solidity ^0.8.20;
            /**
             * @title Library to compute the hash of the proxy bytecode.
             * @custom:security-contact security@1inch.io
             */
            library ProxyHashLib {
                /**
                 * @notice Returns the hash of the proxy bytecode concatenated with the implementation address.
                 * @param implementation The address of the contract to clone.
                 * @return bytecodeHash The hash of the resulting bytecode.
                 */
                function computeProxyBytecodeHash(address implementation) internal pure returns (bytes32 bytecodeHash) {
                    assembly ("memory-safe") {
                        // Stores the bytecode after address
                        mstore(0x20, 0x5af43d82803e903d91602b57fd5bf3)
                        // implementation address
                        mstore(0x11, implementation)
                        // Packs the first 3 bytes of the `implementation` address with the bytecode before the address.
                        mstore(0x00, or(shr(0x88, implementation), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
                        bytecodeHash := keccak256(0x09, 0x37)
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            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.
             */
            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();
            }