Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PheasantNetworkSwap
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 30 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import "solmate/src/utils/SafeTransferLib.sol";
import "solmate/src/tokens/ERC20.sol";
import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { IPheasantNetworkSwapParameters } from "./IPheasantNetworkSwapParameters.sol";
import { EnumerableMap } from "../libraries/utils/EnumerableMap.sol";
import { Types } from "../libraries/types/Types.sol";
contract PheasantNetworkSwap is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable {
using BytesLib for bytes;
using EnumerableMap for EnumerableMap.Bytes32ToUintMap;
address constant ETH_ADDRESS = address(0);
// ========================= Struct =========================
struct BulkWithdraw {
address token;
uint256 fees;
}
// ========================= Events =========================
event SwapInitialized(address owner, address params);
event SwapUpdateParams(address params);
event SwapNewTrade(address indexed userAddress, address indexed token, Types.SwapTrade trade);
event SwapWithdrawTrade(
address indexed userAddress,
address indexed token,
bytes32 tradeHash,
uint256 amount,
bytes data
);
event SwapBulkWithdrawTrade(Types.SwapWithdraw[] withdraws);
event SwapRefundTrade(
address indexed userAddress,
address indexed token,
bytes32 tradeHash,
uint256 refunded,
uint256 fee,
bytes data
);
// ========================= Storage variables =========================
IPheasantNetworkSwapParameters internal params;
bool internal isActive;
EnumerableMap.Bytes32ToUintMap private feeByTrade;
mapping(address => uint256) public feeByToken;
// ========================= Initialize =========================
function initialize(address params_, address owner_) public initializer {
_transferOwnership(owner_);
__ReentrancyGuard_init();
params = IPheasantNetworkSwapParameters(params_);
isActive = true;
emit SwapInitialized(owner_, params_);
}
// ========================= Modifiers =========================
modifier onlyActiveContract() {
require(isActive, "PheasantNetworkSwap: Contract is not active");
_;
}
modifier refundExcessNative(address payable refundReceiver, address token) {
uint256 initialFee = feeByToken[token];
uint256 initialBalance = address(this).balance - msg.value;
_;
uint256 finalFee = feeByToken[token];
uint256 finalBalance = 0;
if (token != ETH_ADDRESS) {
finalBalance = address(this).balance;
} else {
finalBalance = address(this).balance - (finalFee - initialFee);
}
if (finalBalance > initialBalance) {
SafeTransferLib.safeTransferETH(refundReceiver, finalBalance - initialBalance);
}
}
// ========================= Functions =========================
function toggleContractActive() external onlyOwner {
isActive = !isActive;
}
function getContractStatus() external view returns (bool) {
return isActive;
}
function updateParams(IPheasantNetworkSwapParameters newParams) external onlyOwner {
params = newParams;
emit SwapUpdateParams(address(params));
}
function execute(
Types.TransactionRequest calldata request
) external payable onlyActiveContract nonReentrant refundExcessNative(payable(msg.sender), request.fromToken) {
uint256 value = request.value;
uint256 relayerFee = params.getRelayerFee(request.amount, request.quoteTimestamp);
feeByToken[request.fromToken] += relayerFee;
Types.SwapTrade memory trade = Types.SwapTrade(
request.toChainId,
request.swapToolIndex,
request.toolContract,
request.toToken,
request.amount,
relayerFee,
block.timestamp
);
bytes32 tradeKey = generateKey(msg.sender, request.fromToken, keccak256(abi.encode(trade)));
require(!feeByTrade.contains(tradeKey), "PheasantNetworkSwap: Same trade already exists");
if (request.fromToken != ETH_ADDRESS) {
SafeTransferLib.safeTransferFrom(ERC20(request.fromToken), msg.sender, address(this), request.amount);
SafeTransferLib.safeApprove(ERC20(request.fromToken), request.toolContract, request.amount - relayerFee);
} else {
require(msg.value == request.value, "PheasantNetworkSwap: Invalid value sent");
value = request.value - relayerFee;
}
// slither-disable-next-line low-level-calls,return-bomb
(bool success, bytes memory res) = request.toolContract.call{ gas: request.gas, value: value }(request.data);
if (!success) {
if (res.length > 4) {
string memory errorMessage = abi.decode(res.slice(4, res.length - 4), (string));
revert(errorMessage);
} else {
revert("Low-level call failed without revert message");
}
}
// Already checked the key absence
// slither-disable-next-line unused-return
feeByTrade.set(generateKey(msg.sender, request.fromToken, keccak256(abi.encode(trade))), relayerFee);
emit SwapNewTrade(msg.sender, request.fromToken, trade);
}
function withdraw(Types.SwapWithdrawRequest calldata request) public payable onlyOwner {
uint256 fee = _withdraw(request.userAddress, request.token, request.tradeHash);
tokenTransfer(request.token, owner(), fee);
emit SwapWithdrawTrade(request.userAddress, request.token, request.tradeHash, fee, request.data);
}
function bulkWithdraw(Types.SwapWithdrawRequest[] calldata requests) external payable onlyOwner {
uint256 length = requests.length;
require(length <= params.getMaxBulkWithdrawLength(), "PheasantNetworkSwap: Requests length too large");
Types.SwapWithdraw[] memory withdraws = new Types.SwapWithdraw[](length);
uint256 firstFee = _withdraw(requests[0].userAddress, requests[0].token, requests[0].tradeHash);
BulkWithdraw memory _bulkWithdraw = BulkWithdraw(requests[0].token, firstFee);
withdraws[0] = Types.SwapWithdraw(
requests[0].data,
requests[0].tradeHash,
requests[0].userAddress,
requests[0].token,
firstFee
);
for (uint256 i = 1; i < length; i++) {
Types.SwapWithdrawRequest calldata request = requests[i];
uint256 fee = _withdraw(request.userAddress, request.token, request.tradeHash);
withdraws[i] = Types.SwapWithdraw(request.data, request.tradeHash, request.userAddress, request.token, fee);
if (_bulkWithdraw.token != request.token) {
tokenTransfer(_bulkWithdraw.token, owner(), _bulkWithdraw.fees);
_bulkWithdraw = BulkWithdraw(request.token, fee);
} else {
_bulkWithdraw.fees += fee;
}
}
// Transfer last bulk
tokenTransfer(_bulkWithdraw.token, owner(), _bulkWithdraw.fees);
emit SwapBulkWithdrawTrade(withdraws);
}
function refund(
address userAddress,
address token,
bytes32 tradeHash,
bytes calldata data
) public payable onlyOwner {
uint256 fee = _withdraw(userAddress, token, tradeHash);
uint256 refundFee = params.getRefundFee(fee);
uint256 refundToUser = fee - refundFee;
tokenTransfer(token, userAddress, refundToUser);
tokenTransfer(token, owner(), refundFee);
emit SwapRefundTrade(userAddress, token, tradeHash, refundToUser, refundFee, data);
}
function hasTrade(bytes32 tradeKey) external view returns (bool) {
return feeByTrade.contains(tradeKey);
}
// Able to receive ether
receive() external payable {}
// ========================= Internal functions =========================
function _withdraw(address userAddress, address token, bytes32 tradeKey) internal returns (uint256) {
bytes32 key = generateKey(userAddress, token, tradeKey);
(bool keyExists, uint256 fee) = feeByTrade.tryGet(key);
require(keyExists, "PheasantNetworkSwap: Trade is not exists");
feeByToken[token] -= fee;
// Already checked the key absence
// slither-disable-next-line unused-return
feeByTrade.remove(key);
return fee;
}
function generateKey(address userAddress, address token, bytes32 trade) internal pure returns (bytes32) {
return keccak256(abi.encode(userAddress, token, trade));
}
function tokenTransfer(address token, address to, uint256 amount) internal {
if (token == ETH_ADDRESS) {
SafeTransferLib.safeTransferETH(to, amount);
} else {
SafeTransferLib.safeTransfer(ERC20(token), to, amount);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
/**
* @title Types
*/
library Types {
/***********
* Structs *
***********/
struct TradeParam {
uint256 tradeThreshold;
uint256 tradeMinimumAmount;
uint256 networkCode;
uint256 tradableBondRatio;
uint256 disputeDepositAmount;
}
struct UserTrade {
address userAddress;
uint256 index;
}
struct Trade {
uint256 index;
address user;
uint8 tokenTypeIndex;
uint256 amount;
uint256 timestamp;
address to;
address relayer;
uint8 status;
uint256 fee;
uint256 destCode;
}
struct UserCCTPTrade {
address userAddress;
uint256 index;
}
struct CCTPTrade {
uint256 index;
address user;
uint256 amount;
uint256 timestamp;
bytes32 to;
uint8 status;
uint256 fee;
uint32 destinationDomain;
}
struct CctpFeeUpdate {
uint64 executeAfter;
uint256 newFee;
}
struct Evidence {
uint256 blockNumber;
bytes32 blockHash;
bytes[] txReceiptProof;
bytes[] txProof;
bytes transaction;
uint8[] path;
bytes txReceipt;
bytes[] rawTx;
bytes[] rawBlockHeader;
uint8 txType;
}
struct Dispute {
address disputer;
uint8 tokenTypeIndex;
uint256 deposit;
uint256 disputedTimestamp;
}
struct FeeList {
uint256 high;
uint256 medium;
uint256 low;
uint256 gasPriceThresholdHigh;
uint256 gasPriceThresholdLow;
}
struct FeeListUpdate {
uint64 executeAfter;
uint256 networkCode;
uint8 tokenTypeIndex;
FeeList newFeeList;
}
struct TradeParamUpdate {
uint64 executeAfter;
uint8 operation;
uint256 networkCode;
uint8 tokenTypeIndex;
uint256 newValue;
}
struct TokenAddressUpdate {
uint64 executeAfter;
uint256[] networkCodes;
uint8[] tokenTypeIndices;
address[] tokenAddresses;
}
struct ManagerUpdate {
uint64 executeAfter;
uint8 operation;
address newManager;
}
struct NetworkSettingUpdate {
uint64 executeAfter;
uint8[] operations;
uint256[] networkCodes;
uint8[] tokenTypeIndices;
bool[] nativeIsNotETH;
}
struct TransactionRequest {
bytes data;
string toChainId;
uint16 swapToolIndex;
address toolContract;
address fromToken;
address toToken;
uint256 amount;
uint256 value;
uint256 gas;
uint256 quoteTimestamp;
}
struct SwapWithdrawRequest {
bytes data;
bytes32 tradeHash;
address userAddress;
address token;
}
struct SwapTrade {
string toChainId;
uint16 swapToolIndex;
address toolContract;
address toToken;
uint256 amount;
uint256 relayerFee;
uint256 timestamp;
}
struct SwapWithdraw {
bytes data;
bytes32 tradeHash;
address userAddress;
address token;
uint256 amount;
}
}// SPDX-License-Identifier: MIT
// NOTE: This file is used in part from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.1.0/contracts/utils/structs/EnumerableMap.sol
pragma solidity 0.8.18;
import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code repetition as possible, we write it in
// terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions,
// and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit in bytes32.
/**
* @dev Query for a nonexistent map key.
*/
error EnumerableMapNonexistentKey(bytes32 key);
struct Bytes32ToBytes32Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) {
bytes32 atKey = map._keys.at(index);
return (atKey, map._values[atKey]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool exists, bytes32 value) {
bytes32 val = map._values[key];
if (val == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, val);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
if (value == 0 && !contains(map, key)) {
revert EnumerableMapNonexistentKey(key);
}
return value;
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return map._keys.values();
}
// Bytes32ToUintMap
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32 key, uint256 value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (atKey, uint256(val));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool exists, uint256 value) {
(bool success, bytes32 val) = tryGet(map._inner, key);
return (success, uint256(val));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
// slither-disable-next-line assembly
assembly ("memory-safe") {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
interface IPheasantNetworkSwapParameters {
function relayerAddress() external view returns (address);
function getRelayerFee(uint256 amount) external view returns (uint256);
function getRelayerFee(uint256 amount, uint256 timestamp) external view returns (uint256);
function getRefundFee(uint256 amount) external view returns (uint256);
function getMaxBulkWithdrawLength() external view returns (uint256);
}// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equal_nonAligned(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let endMinusWord := add(_preBytes, length) let mc := add(_preBytes, 0x20) let cc := add(_postBytes, 0x20) for { // the next line is the loop condition: // while(uint256(mc < endWord) + cb == 2) } eq(add(lt(mc, endMinusWord), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } // Only if still successful // For <1 word tail bytes if gt(success, 0) { // Get the remainder of length/32 // length % 32 = AND(length, 32 - 1) let numTailBytes := and(length, 0x1f) let mcRem := mload(mc) let ccRem := mload(cc) for { let i := 0 // the next line is the loop condition: // while(uint256(i < numTailBytes) + cb == 2) } eq(add(lt(i, numTailBytes), cb), 2) { i := add(i, 1) } { if iszero(eq(byte(i, mcRem), byte(i, ccRem))) { // unsuccess: success := 0 cb := 0 } } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
success := call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data and token has code.
if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) {
success := iszero(or(iszero(extcodesize(token)), returndatasize()))
}
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
success := call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data and token has code.
if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) {
success := iszero(or(iszero(extcodesize(token)), returndatasize()))
}
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
success := call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data and token has code.
if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) {
success := iszero(or(iszero(extcodesize(token)), returndatasize()))
}
}
require(success, "APPROVE_FAILED");
}
}{
"viaIR": true,
"optimizer": {
"enabled": true,
"runs": 30,
"details": {
"yul": true
}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"tradeHash","type":"bytes32"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct Types.SwapWithdraw[]","name":"withdraws","type":"tuple[]"}],"name":"SwapBulkWithdrawTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"params","type":"address"}],"name":"SwapInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"components":[{"internalType":"string","name":"toChainId","type":"string"},{"internalType":"uint16","name":"swapToolIndex","type":"uint16"},{"internalType":"address","name":"toolContract","type":"address"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"relayerFee","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"indexed":false,"internalType":"struct Types.SwapTrade","name":"trade","type":"tuple"}],"name":"SwapNewTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes32","name":"tradeHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"refunded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"SwapRefundTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"params","type":"address"}],"name":"SwapUpdateParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes32","name":"tradeHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"SwapWithdrawTrade","type":"event"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"tradeHash","type":"bytes32"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct Types.SwapWithdrawRequest[]","name":"requests","type":"tuple[]"}],"name":"bulkWithdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"string","name":"toChainId","type":"string"},{"internalType":"uint16","name":"swapToolIndex","type":"uint16"},{"internalType":"address","name":"toolContract","type":"address"},{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"quoteTimestamp","type":"uint256"}],"internalType":"struct Types.TransactionRequest","name":"request","type":"tuple"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"feeByToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"tradeKey","type":"bytes32"}],"name":"hasTrade","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"params_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"tradeHash","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"refund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleContractActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPheasantNetworkSwapParameters","name":"newParams","type":"address"}],"name":"updateParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"tradeHash","type":"bytes32"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct Types.SwapWithdrawRequest","name":"request","type":"tuple"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6080806040523461001657611d78908161001c8239f35b600080fdfe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301c270c3146100eb57806307fe2e54146100e65780631385d24c146100e1578063485cc955146100dc5780636a372984146100d7578063715018a6146100d25780638da5cb5b146100cd5780639e84b6b5146100c8578063c032846b146100c3578063c35925e9146100be578063e37ba9b2146100b9578063ec150413146100b45763f2fde38b0361000e57610b30565b610afa565b610a13565b6108d1565b6108ab565b61086e565b610845565b6107e4565b610651565b610554565b610518565b6104a8565b602080600319360112610492576004356001600160401b03918282116104925736602383011215610492578160040135928311610492576024820191602436918560051b0101116104925761013e610bc1565b60975461015b906001600160a01b03165b6001600160a01b031690565b926004826040958651928380926321b3209160e01b82525afa801561048d5761019191600091610460575b5082949211156115d8565b61019a83611652565b926101af856101a983856116d4565b01610da7565b916101d76060936101c4856101a986866116d4565b866101cf86866116d4565b013591611802565b6101e5846101a985856116d4565b6101ff6101f0610eac565b6001600160a01b039092168252565b81868201529361028261021b61021586866116d4565b80610e6b565b91906102738961022b89896116d4565b013561023b8d6101a98b8b6116d4565b9061025e61024d886101a98d8d6116d4565b94610256610ecb565b973691610f24565b86528b8601526001600160a01b03168c850152565b6001600160a01b031682840152565b6080928382015261029288611711565b5261029c87611711565b506001935b80851061030b577f504c6b1ba9ab27e29ac0d69892254dd109829b156e18b746c56433be5b04e178610306898b6102fc8b8b6102e3815160018060a01b031690565b6033549092906001600160a01b03165b91015191611a17565b5191829182611741565b0390a1005b90919293948861031c8784886116ef565b916103636103a68385016103978c61033383610da7565b968a89019761035b6103546103478b610da7565b92858d0135938491611802565b9a80610e6b565b979095610da7565b926103816103708b610da7565b96610379610ecb565b993691610f24565b88528701526001600160a01b0390911690850152565b6001600160a01b031682880152565b83878201526103b5898c61171e565b526103c0888b61171e565b5080516001600160a01b03166103d861014f84610da7565b6001600160a01b039091161461044457805160335461043b9493610416939092610411926001600160a01b0391821692918e91166102f3565b610da7565b90610431610422610eac565b6001600160a01b039093168352565b8882015295611732565b939291906102a1565b96905061043b91610459898901918251610e5e565b9052611732565b6104809150843d8611610486575b6104788183610e01565b810190610e27565b38610186565b503d61046e565b610e36565b600080fd5b6001600160a01b0381160361049257565b34610492576020366003190112610492577fe2e42d7ae303ebbcb22266a6ebb41d9c9678628cd17a59589f3885d68eb2cd8360206004356104e881610497565b6104f0610bc1565b609780546001600160a01b0319166001600160a01b03929092169182179055604051908152a1005b3461049257600036600319011261049257610531610bc1565b6097805460ff60a01b19811660a091821c60ff161590911b60ff60a01b16179055005b346104925760403660031901126104925760043561057181610497565b6105c160243561058081610497565b600054926105a560ff8560081c161580958196610643575b8115610623575b50610c62565b836105b8600160ff196000541617600055565b61060a57610cc5565b6105c757005b6105d761ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498908060208101610306565b61061e61010061ff00196000541617600055565b610cc5565b303b15915081610635575b503861059f565b6001915060ff16143861062e565b600160ff8216109150610598565b60031960203682011261049257600435906001600160401b038211610492576101409082360301126104925760ff60975460a01c161561078b5760026065541461074657600260655560848101356106a881610497565b6001600160a01b0381166000818152609b6020526040902054916106f6906106dc6106d33447610dde565b95600401611175565b6001600160a01b03166000908152609b6020526040902090565b54901561072d575050475b818111610713575b6100196001606555565b6107269161072091610dde565b33611bc6565b3880610709565b61073b610741924792610dde565b90610dde565b610701565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b60405162461bcd60e51b815260206004820152602b60248201527f5068656173616e744e6574776f726b537761703a20436f6e747261637420697360448201526a206e6f742061637469766560a81b6064820152608490fd5b3461049257600080600319360112610842576107fe610bc1565b603380546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b34610492576000366003190112610492576033546040516001600160a01b039091168152602090f35b346104925760203660031901126104925760043561088b81610497565b60018060a01b0316600052609b6020526020604060002054604051908152f35b3461049257600036600319011261049257602060ff60975460a01c166040519015158152f35b6080366003190112610492576004356108e981610497565b6024356108f581610497565b604435606435916001600160401b0390818411610492573660238501121561049257836004013591821161049257366024838601011161049257610937610bc1565b610942838287611802565b609754604051632b383fc560e11b81526004810183905291946001600160a01b0394916020908490602490829089165afa801561048d577fa6cb6e08ad908f9d671a8ebbc0e7146756b08daf9d414bb21dbc891388f00000966109ea946000926109ef575b50816109b291610dde565b6109bd818b88611a17565b6033546109d59083906001600160a01b031688611a17565b602487604051988998169b16990192866117df565b0390a3005b6109b2919250610a0c9060203d8111610486576104788183610e01565b91906109a7565b60031960203682011261049257600435906001600160401b03821161049257608082600401918336030112610492577ffa2c40d0588b37c491b80ca87173fc8d840eb485adec24c45ee23d4289bfa6f4610ad591610a6f610bc1565b604484013593610a7e85610497565b6109ea6024606483013592610a9284610497565b013591610aa0838289611802565b93610aaa82610497565b60018060a01b03968791610ac387846033541686611a17565b610acc8a610497565b61021584610497565b97909260405196879687526020870152606060408701521697169560608401916115b7565b34610492576020366003190112610492576020610b266004356000526099602052604060002054151590565b6040519015158152f35b3461049257602036600319011261049257600435610b4d81610497565b610b55610bc1565b6001600160a01b03811615610b6d5761001990610c19565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b6033546001600160a01b03163303610bd557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b15610c6957565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b7fff5ca8663ed3b85e7db74cfe850fb10dffe51b162b7a365e56ae32558541497691604091610cf382610c19565b610d0d60ff60005460081c16610d0881610d47565b610d47565b6001606555609780546001600160a81b0319166001600160a01b03928316908117600160a01b1790915583519290911682526020820152a1565b15610d4e57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b35610db181610497565b90565b634e487b7160e01b600052601160045260246000fd5b600319810191908211610dd957565b610db4565b91908203918211610dd957565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610e2257604052565b610deb565b90816020910312610492575190565b6040513d6000823e3d90fd5b90601f8201809211610dd957565b6004019081600411610dd957565b91908201809211610dd957565b903590601e198136030182121561049257018035906001600160401b0382116104925760200191813603831361049257565b3561ffff811681036104925790565b60405190604082018281106001600160401b03821117610e2257604052565b6040519060a082018281106001600160401b03821117610e2257604052565b6040519060e082018281106001600160401b03821117610e2257604052565b6001600160401b038111610e2257601f01601f191660200190565b929192610f3082610f09565b91610f3e6040519384610e01565b829481845281830111610492578281602093846000960137010152565b60005b838110610f6e5750506000910152565b8181015183820152602001610f5e565b90602091610f9781518092818552858086019101610f5b565b601f01601f1916010190565b6020815260e060c0610fc18451836020860152610100850190610f7e565b9361ffff602082015116604085015260018060a01b038060408301511660608601526060820151166080850152608081015160a085015260a081015182850152015191015290565b1561101057565b60405162461bcd60e51b815260206004820152602e60248201527f5068656173616e744e6574776f726b537761703a2053616d652074726164652060448201526d616c72656164792065786973747360901b6064820152608490fd5b1561107357565b60405162461bcd60e51b815260206004820152602760248201527f5068656173616e744e6574776f726b537761703a20496e76616c69642076616c6044820152661d59481cd95b9d60ca1b6064820152608490fd5b908092918237016000815290565b3d15611101573d906110e782610f09565b916110f56040519384610e01565b82523d6000602084013e565b606090565b602081830312610492578051906001600160401b038211610492570181601f8201121561049257805161113881610f09565b926111466040519485610e01565b8184526020828401011161049257610db19160208085019101610f5b565b906020610db1928181520190610f7e565b60975460e082013590611190906001600160a01b031661014f565b60408051634364dd3b60e11b815260c0850135600482018190526101208601356024830152919460209490938590839060449082905afa91821561048d576000926114d7575b50608084019485936111e785610da7565b6001600160a01b03166000908152609b602052604090208481549061120b91610e5e565b905561121986830187610e6b565b9790966112278a8201610e9d565b9760608201986112368a610da7565b9061124360a08501610da7565b9261124c610eea565b9c369061125892610f24565b8c5261ffff16868c01526001600160a01b03168a8c01526001600160a01b031660608a01528260808a01528560a08a01524260c08a01528561129983610da7565b8b519690868801886112ab8e83610fa3565b0398601f19998a810182526112c09082610e01565b5190206112cd91336119d2565b6112e4906000526099602052604060002054151590565b156112ee90611009565b6001600160a01b03998a61130186610da7565b6000978897611372969193909216156114b557508161133d61014f83610411611357979661133461014f61041198610da7565b30903390611c11565b906113518d61134b86610da7565b92610dde565b91611cb1565b6101008d6113658680610e6b565b95909151809681936110c8565b03940135f161137f6110d6565b901561140957506113f5926113ea88886113d46113e089976113ef976113c67fd3c401dfdd079a8763e51394e4dbd6cdb508ae3474090c4d3aa61fe4195325039d9c610da7565b955193849182019586610fa3565b03908101835282610e01565b51902090336119d2565b6114f6565b50610da7565b16925180611404339482610fa3565b0390a3565b879250600481511160001461145c5761145892916114348261142e6114419451610dca565b90611b3b565b8051810182019101611106565b905162461bcd60e51b815291829160048301611164565b0390fd5b825162461bcd60e51b815260206004820152602c60248201527f4c6f772d6c6576656c2063616c6c206661696c656420776974686f757420726560448201526b76657274206d65737361676560a01b6064820152608490fd5b90506114d19150836114cc6113579495341461106c565b610dde565b91610da7565b6114ef919250853d8711610486576104788183610e01565b90386111d6565b610db19181600052609a602052604060002055611544565b634e487b7160e01b600052603260045260246000fd5b60985481101561153f57609860005260206000200190600090565b61150e565b6000818152609960205260408120546115b25760985490600160401b821015610e2257600182018060985582101561153f577f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d81490910182905560985491815260996020526040902055600190565b905090565b908060209392818452848401376000828201840152601f01601f1916010190565b156115df57565b60405162461bcd60e51b815260206004820152602e60248201527f5068656173616e744e6574776f726b537761703a205265717565737473206c6560448201526d6e67746820746f6f206c6172676560901b6064820152608490fd5b6001600160401b038111610e225760051b60200190565b9061165c8261163b565b604061166a81519283610e01565b838252819361167b601f199161163b565b019060005b82811061168d5750505050565b81519060a08201918083106001600160401b03841117610e225760209284526060808252600084918183850152818785015283015260006080830152828701015201611680565b901561153f57803590607e1981360301821215610492570190565b919081101561153f5760051b81013590607e1981360301821215610492570190565b80511561153f5760200190565b805182101561153f5760209160051b010190565b6000198114610dd95760010190565b602080820190808352835180925260409283810182858560051b8401019601946000925b858410611776575050505050505090565b909192939495968580600192603f198582030187528a51906117a0825160a0808452830190610f7e565b918381015184830152858060a01b0380898301511689840152606090818301511690830152608080910151910152990194019401929594939190611765565b9092608092610db1969483526020830152604082015281606082015201916115b7565b918161180e92936119d2565b611817816119a2565b92901561185e5760018060a01b0316600052609b6020526040600020908154838103908111610dd95761185a925580600052609a602052600060408120556118f6565b5090565b60405162461bcd60e51b815260206004820152602860248201527f5068656173616e744e6574776f726b537761703a205472616465206973206e6f604482015267742065786973747360c01b6064820152608490fd5b60985480156118e05760001981810191908183101561153f576000916098835260208320010155609855565b634e487b7160e01b600052603160045260246000fd5b600081815260996020526040902054801561199b576000199181830191808311610dd957609854938401938411610dd95783836119519460009603611957575b5050506119416118b4565b6000526099602052604060002090565b55600190565b6119416119799161196a61199294611524565b90549060031b1c928391611524565b90919082549060031b91821b91600019901b1916179055565b55388080611936565b5050600090565b600052609a60205260406000205480156000146119cd57506099602052604060002054151590600090565b600191565b909160405191602083019360018060a01b038092168552166040830152606082015260608152608081018181106001600160401b03821117610e225760405251902090565b6001600160a01b0390811692919083611a375750611a359250611bc6565b565b906044906020936000936040519263a9059cbb60e01b8452166004830152602482015282855af19081601f3d11600160005114161516611ab1575b5015611a7a57565b60405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606490fd5b3b153d1715905038611a72565b15611ac557565b60405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606490fd5b15611b0257565b60405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606490fd5b611b4f82611b4881610e42565b1015611abe565b611b648151611b5d84610e50565b1115611afb565b81611b7c575050604051600081526020810160405290565b60405191601f8116916004831560051b80858701019484860193010101905b808410611bb35750508252601f01601f191660405290565b9092835181526020809101930190611b9b565b600080809381935af115611bd657565b60405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606490fd5b6040516323b872dd60e01b81526001600160a01b039283166004820152929091166024830152604482019290925260209060009060649082855af19081601f3d11600160005114161516611ca4575b5015611c6857565b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b3b153d1715905038611c60565b60405163095ea7b360e01b81526001600160a01b039092166004830152602482019290925260209060009060449082855af19081601f3d11600160005114161516611d35575b5015611cff57565b60405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606490fd5b3b153d1715905038611cf756fea26469706673582212209294f563067c05aee6b90ddcc8ef03c55fd5474eb9b8bf7656b3b0f0f38d798064736f6c63430008120033
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301c270c3146100eb57806307fe2e54146100e65780631385d24c146100e1578063485cc955146100dc5780636a372984146100d7578063715018a6146100d25780638da5cb5b146100cd5780639e84b6b5146100c8578063c032846b146100c3578063c35925e9146100be578063e37ba9b2146100b9578063ec150413146100b45763f2fde38b0361000e57610b30565b610afa565b610a13565b6108d1565b6108ab565b61086e565b610845565b6107e4565b610651565b610554565b610518565b6104a8565b602080600319360112610492576004356001600160401b03918282116104925736602383011215610492578160040135928311610492576024820191602436918560051b0101116104925761013e610bc1565b60975461015b906001600160a01b03165b6001600160a01b031690565b926004826040958651928380926321b3209160e01b82525afa801561048d5761019191600091610460575b5082949211156115d8565b61019a83611652565b926101af856101a983856116d4565b01610da7565b916101d76060936101c4856101a986866116d4565b866101cf86866116d4565b013591611802565b6101e5846101a985856116d4565b6101ff6101f0610eac565b6001600160a01b039092168252565b81868201529361028261021b61021586866116d4565b80610e6b565b91906102738961022b89896116d4565b013561023b8d6101a98b8b6116d4565b9061025e61024d886101a98d8d6116d4565b94610256610ecb565b973691610f24565b86528b8601526001600160a01b03168c850152565b6001600160a01b031682840152565b6080928382015261029288611711565b5261029c87611711565b506001935b80851061030b577f504c6b1ba9ab27e29ac0d69892254dd109829b156e18b746c56433be5b04e178610306898b6102fc8b8b6102e3815160018060a01b031690565b6033549092906001600160a01b03165b91015191611a17565b5191829182611741565b0390a1005b90919293948861031c8784886116ef565b916103636103a68385016103978c61033383610da7565b968a89019761035b6103546103478b610da7565b92858d0135938491611802565b9a80610e6b565b979095610da7565b926103816103708b610da7565b96610379610ecb565b993691610f24565b88528701526001600160a01b0390911690850152565b6001600160a01b031682880152565b83878201526103b5898c61171e565b526103c0888b61171e565b5080516001600160a01b03166103d861014f84610da7565b6001600160a01b039091161461044457805160335461043b9493610416939092610411926001600160a01b0391821692918e91166102f3565b610da7565b90610431610422610eac565b6001600160a01b039093168352565b8882015295611732565b939291906102a1565b96905061043b91610459898901918251610e5e565b9052611732565b6104809150843d8611610486575b6104788183610e01565b810190610e27565b38610186565b503d61046e565b610e36565b600080fd5b6001600160a01b0381160361049257565b34610492576020366003190112610492577fe2e42d7ae303ebbcb22266a6ebb41d9c9678628cd17a59589f3885d68eb2cd8360206004356104e881610497565b6104f0610bc1565b609780546001600160a01b0319166001600160a01b03929092169182179055604051908152a1005b3461049257600036600319011261049257610531610bc1565b6097805460ff60a01b19811660a091821c60ff161590911b60ff60a01b16179055005b346104925760403660031901126104925760043561057181610497565b6105c160243561058081610497565b600054926105a560ff8560081c161580958196610643575b8115610623575b50610c62565b836105b8600160ff196000541617600055565b61060a57610cc5565b6105c757005b6105d761ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498908060208101610306565b61061e61010061ff00196000541617600055565b610cc5565b303b15915081610635575b503861059f565b6001915060ff16143861062e565b600160ff8216109150610598565b60031960203682011261049257600435906001600160401b038211610492576101409082360301126104925760ff60975460a01c161561078b5760026065541461074657600260655560848101356106a881610497565b6001600160a01b0381166000818152609b6020526040902054916106f6906106dc6106d33447610dde565b95600401611175565b6001600160a01b03166000908152609b6020526040902090565b54901561072d575050475b818111610713575b6100196001606555565b6107269161072091610dde565b33611bc6565b3880610709565b61073b610741924792610dde565b90610dde565b610701565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b60405162461bcd60e51b815260206004820152602b60248201527f5068656173616e744e6574776f726b537761703a20436f6e747261637420697360448201526a206e6f742061637469766560a81b6064820152608490fd5b3461049257600080600319360112610842576107fe610bc1565b603380546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b34610492576000366003190112610492576033546040516001600160a01b039091168152602090f35b346104925760203660031901126104925760043561088b81610497565b60018060a01b0316600052609b6020526020604060002054604051908152f35b3461049257600036600319011261049257602060ff60975460a01c166040519015158152f35b6080366003190112610492576004356108e981610497565b6024356108f581610497565b604435606435916001600160401b0390818411610492573660238501121561049257836004013591821161049257366024838601011161049257610937610bc1565b610942838287611802565b609754604051632b383fc560e11b81526004810183905291946001600160a01b0394916020908490602490829089165afa801561048d577fa6cb6e08ad908f9d671a8ebbc0e7146756b08daf9d414bb21dbc891388f00000966109ea946000926109ef575b50816109b291610dde565b6109bd818b88611a17565b6033546109d59083906001600160a01b031688611a17565b602487604051988998169b16990192866117df565b0390a3005b6109b2919250610a0c9060203d8111610486576104788183610e01565b91906109a7565b60031960203682011261049257600435906001600160401b03821161049257608082600401918336030112610492577ffa2c40d0588b37c491b80ca87173fc8d840eb485adec24c45ee23d4289bfa6f4610ad591610a6f610bc1565b604484013593610a7e85610497565b6109ea6024606483013592610a9284610497565b013591610aa0838289611802565b93610aaa82610497565b60018060a01b03968791610ac387846033541686611a17565b610acc8a610497565b61021584610497565b97909260405196879687526020870152606060408701521697169560608401916115b7565b34610492576020366003190112610492576020610b266004356000526099602052604060002054151590565b6040519015158152f35b3461049257602036600319011261049257600435610b4d81610497565b610b55610bc1565b6001600160a01b03811615610b6d5761001990610c19565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b6033546001600160a01b03163303610bd557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b15610c6957565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b7fff5ca8663ed3b85e7db74cfe850fb10dffe51b162b7a365e56ae32558541497691604091610cf382610c19565b610d0d60ff60005460081c16610d0881610d47565b610d47565b6001606555609780546001600160a81b0319166001600160a01b03928316908117600160a01b1790915583519290911682526020820152a1565b15610d4e57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b35610db181610497565b90565b634e487b7160e01b600052601160045260246000fd5b600319810191908211610dd957565b610db4565b91908203918211610dd957565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b03821117610e2257604052565b610deb565b90816020910312610492575190565b6040513d6000823e3d90fd5b90601f8201809211610dd957565b6004019081600411610dd957565b91908201809211610dd957565b903590601e198136030182121561049257018035906001600160401b0382116104925760200191813603831361049257565b3561ffff811681036104925790565b60405190604082018281106001600160401b03821117610e2257604052565b6040519060a082018281106001600160401b03821117610e2257604052565b6040519060e082018281106001600160401b03821117610e2257604052565b6001600160401b038111610e2257601f01601f191660200190565b929192610f3082610f09565b91610f3e6040519384610e01565b829481845281830111610492578281602093846000960137010152565b60005b838110610f6e5750506000910152565b8181015183820152602001610f5e565b90602091610f9781518092818552858086019101610f5b565b601f01601f1916010190565b6020815260e060c0610fc18451836020860152610100850190610f7e565b9361ffff602082015116604085015260018060a01b038060408301511660608601526060820151166080850152608081015160a085015260a081015182850152015191015290565b1561101057565b60405162461bcd60e51b815260206004820152602e60248201527f5068656173616e744e6574776f726b537761703a2053616d652074726164652060448201526d616c72656164792065786973747360901b6064820152608490fd5b1561107357565b60405162461bcd60e51b815260206004820152602760248201527f5068656173616e744e6574776f726b537761703a20496e76616c69642076616c6044820152661d59481cd95b9d60ca1b6064820152608490fd5b908092918237016000815290565b3d15611101573d906110e782610f09565b916110f56040519384610e01565b82523d6000602084013e565b606090565b602081830312610492578051906001600160401b038211610492570181601f8201121561049257805161113881610f09565b926111466040519485610e01565b8184526020828401011161049257610db19160208085019101610f5b565b906020610db1928181520190610f7e565b60975460e082013590611190906001600160a01b031661014f565b60408051634364dd3b60e11b815260c0850135600482018190526101208601356024830152919460209490938590839060449082905afa91821561048d576000926114d7575b50608084019485936111e785610da7565b6001600160a01b03166000908152609b602052604090208481549061120b91610e5e565b905561121986830187610e6b565b9790966112278a8201610e9d565b9760608201986112368a610da7565b9061124360a08501610da7565b9261124c610eea565b9c369061125892610f24565b8c5261ffff16868c01526001600160a01b03168a8c01526001600160a01b031660608a01528260808a01528560a08a01524260c08a01528561129983610da7565b8b519690868801886112ab8e83610fa3565b0398601f19998a810182526112c09082610e01565b5190206112cd91336119d2565b6112e4906000526099602052604060002054151590565b156112ee90611009565b6001600160a01b03998a61130186610da7565b6000978897611372969193909216156114b557508161133d61014f83610411611357979661133461014f61041198610da7565b30903390611c11565b906113518d61134b86610da7565b92610dde565b91611cb1565b6101008d6113658680610e6b565b95909151809681936110c8565b03940135f161137f6110d6565b901561140957506113f5926113ea88886113d46113e089976113ef976113c67fd3c401dfdd079a8763e51394e4dbd6cdb508ae3474090c4d3aa61fe4195325039d9c610da7565b955193849182019586610fa3565b03908101835282610e01565b51902090336119d2565b6114f6565b50610da7565b16925180611404339482610fa3565b0390a3565b879250600481511160001461145c5761145892916114348261142e6114419451610dca565b90611b3b565b8051810182019101611106565b905162461bcd60e51b815291829160048301611164565b0390fd5b825162461bcd60e51b815260206004820152602c60248201527f4c6f772d6c6576656c2063616c6c206661696c656420776974686f757420726560448201526b76657274206d65737361676560a01b6064820152608490fd5b90506114d19150836114cc6113579495341461106c565b610dde565b91610da7565b6114ef919250853d8711610486576104788183610e01565b90386111d6565b610db19181600052609a602052604060002055611544565b634e487b7160e01b600052603260045260246000fd5b60985481101561153f57609860005260206000200190600090565b61150e565b6000818152609960205260408120546115b25760985490600160401b821015610e2257600182018060985582101561153f577f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d81490910182905560985491815260996020526040902055600190565b905090565b908060209392818452848401376000828201840152601f01601f1916010190565b156115df57565b60405162461bcd60e51b815260206004820152602e60248201527f5068656173616e744e6574776f726b537761703a205265717565737473206c6560448201526d6e67746820746f6f206c6172676560901b6064820152608490fd5b6001600160401b038111610e225760051b60200190565b9061165c8261163b565b604061166a81519283610e01565b838252819361167b601f199161163b565b019060005b82811061168d5750505050565b81519060a08201918083106001600160401b03841117610e225760209284526060808252600084918183850152818785015283015260006080830152828701015201611680565b901561153f57803590607e1981360301821215610492570190565b919081101561153f5760051b81013590607e1981360301821215610492570190565b80511561153f5760200190565b805182101561153f5760209160051b010190565b6000198114610dd95760010190565b602080820190808352835180925260409283810182858560051b8401019601946000925b858410611776575050505050505090565b909192939495968580600192603f198582030187528a51906117a0825160a0808452830190610f7e565b918381015184830152858060a01b0380898301511689840152606090818301511690830152608080910151910152990194019401929594939190611765565b9092608092610db1969483526020830152604082015281606082015201916115b7565b918161180e92936119d2565b611817816119a2565b92901561185e5760018060a01b0316600052609b6020526040600020908154838103908111610dd95761185a925580600052609a602052600060408120556118f6565b5090565b60405162461bcd60e51b815260206004820152602860248201527f5068656173616e744e6574776f726b537761703a205472616465206973206e6f604482015267742065786973747360c01b6064820152608490fd5b60985480156118e05760001981810191908183101561153f576000916098835260208320010155609855565b634e487b7160e01b600052603160045260246000fd5b600081815260996020526040902054801561199b576000199181830191808311610dd957609854938401938411610dd95783836119519460009603611957575b5050506119416118b4565b6000526099602052604060002090565b55600190565b6119416119799161196a61199294611524565b90549060031b1c928391611524565b90919082549060031b91821b91600019901b1916179055565b55388080611936565b5050600090565b600052609a60205260406000205480156000146119cd57506099602052604060002054151590600090565b600191565b909160405191602083019360018060a01b038092168552166040830152606082015260608152608081018181106001600160401b03821117610e225760405251902090565b6001600160a01b0390811692919083611a375750611a359250611bc6565b565b906044906020936000936040519263a9059cbb60e01b8452166004830152602482015282855af19081601f3d11600160005114161516611ab1575b5015611a7a57565b60405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606490fd5b3b153d1715905038611a72565b15611ac557565b60405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606490fd5b15611b0257565b60405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606490fd5b611b4f82611b4881610e42565b1015611abe565b611b648151611b5d84610e50565b1115611afb565b81611b7c575050604051600081526020810160405290565b60405191601f8116916004831560051b80858701019484860193010101905b808410611bb35750508252601f01601f191660405290565b9092835181526020809101930190611b9b565b600080809381935af115611bd657565b60405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606490fd5b6040516323b872dd60e01b81526001600160a01b039283166004820152929091166024830152604482019290925260209060009060649082855af19081601f3d11600160005114161516611ca4575b5015611c6857565b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b3b153d1715905038611c60565b60405163095ea7b360e01b81526001600160a01b039092166004830152602482019290925260209060009060449082855af19081601f3d11600160005114161516611d35575b5015611cff57565b60405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606490fd5b3b153d1715905038611cf756fea26469706673582212209294f563067c05aee6b90ddcc8ef03c55fd5474eb9b8bf7656b3b0f0f38d798064736f6c63430008120033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Token Allocations
FRAX
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| FRAXTAL | 100.00% | $0.84177 | 0.000000000838 | <$0.000001 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.