Latest 25 from a total of 117,742 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap | 342879565 | 168 days ago | IN | 0 ETH | 0.00000231 | ||||
| Swap | 338119822 | 182 days ago | IN | 0 ETH | 0.00000186 | ||||
| Swap | 338119417 | 182 days ago | IN | 0 ETH | 0.00000228 | ||||
| Swap | 338119370 | 182 days ago | IN | 0 ETH | 0.0000021 | ||||
| Swap | 338109917 | 182 days ago | IN | 0 ETH | 0.00000539 | ||||
| Swap | 338106871 | 182 days ago | IN | 0 ETH | 0.00000384 | ||||
| Swap | 335188353 | 191 days ago | IN | 0 ETH | 0.00000253 | ||||
| Swap Multi | 335187634 | 191 days ago | IN | 0 ETH | 0.00000703 | ||||
| Swap | 335187497 | 191 days ago | IN | 0 ETH | 0.00000493 | ||||
| Swap | 334965568 | 191 days ago | IN | 0 ETH | 0.00000212 | ||||
| Swap | 334965514 | 191 days ago | IN | 0.00021562 ETH | 0.00000215 | ||||
| Swap | 334920091 | 192 days ago | IN | 0.001 ETH | 0.00001234 | ||||
| Swap | 334817498 | 192 days ago | IN | 0.00019553 ETH | 0.00002206 | ||||
| Swap | 334648155 | 192 days ago | IN | 0.0095 ETH | 0.0000032 | ||||
| Swap Multi | 334632030 | 192 days ago | IN | 0.077 ETH | 0.0000033 | ||||
| Swap | 334600120 | 192 days ago | IN | 0 ETH | 0.00000348 | ||||
| Swap Multi | 334573179 | 193 days ago | IN | 0 ETH | 0.00001681 | ||||
| Swap Multi | 334527825 | 193 days ago | IN | 0 ETH | 0.00000301 | ||||
| Swap | 334136158 | 194 days ago | IN | 0.006 ETH | 0.00000178 | ||||
| Swap | 334135899 | 194 days ago | IN | 0.0065 ETH | 0.00000167 | ||||
| Swap | 333952194 | 194 days ago | IN | 0 ETH | 0.00000204 | ||||
| Swap | 333939131 | 194 days ago | IN | 0 ETH | 0.00000575 | ||||
| Swap Multi | 333922359 | 194 days ago | IN | 0.01751211 ETH | 0.00000278 | ||||
| Swap Multi | 333918673 | 194 days ago | IN | 0 ETH | 0.00000314 | ||||
| Swap | 333847017 | 195 days ago | IN | 0 ETH | 0.00000235 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 335188353 | 191 days ago | 0.0004618 ETH | ||||
| 335188353 | 191 days ago | 0.0004618 ETH | ||||
| 335187634 | 191 days ago | 0.00192068 ETH | ||||
| 335187634 | 191 days ago | 0.00192068 ETH | ||||
| 335187497 | 191 days ago | 0.00054138 ETH | ||||
| 335187497 | 191 days ago | 0.00054138 ETH | ||||
| 334965568 | 191 days ago | 0.00021433 ETH | ||||
| 334965568 | 191 days ago | 0.00021433 ETH | ||||
| 334965514 | 191 days ago | 0.00021562 ETH | ||||
| 334920091 | 192 days ago | 0.001 ETH | ||||
| 334817498 | 192 days ago | 0.00019553 ETH | ||||
| 334648155 | 192 days ago | 0.0095 ETH | ||||
| 334632030 | 192 days ago | 0.077 ETH | ||||
| 334600120 | 192 days ago | 0.00048689 ETH | ||||
| 334600120 | 192 days ago | 0.00048689 ETH | ||||
| 334136158 | 194 days ago | 0.006 ETH | ||||
| 334135899 | 194 days ago | 0.0065 ETH | ||||
| 333952194 | 194 days ago | 0.0007493 ETH | ||||
| 333952194 | 194 days ago | 0.0007493 ETH | ||||
| 333939131 | 194 days ago | 0.00701407 ETH | ||||
| 333939131 | 194 days ago | 0.00701407 ETH | ||||
| 333922359 | 194 days ago | 0.01751211 ETH | ||||
| 333847017 | 195 days ago | 0.0077291 ETH | ||||
| 333847017 | 195 days ago | 0.0077291 ETH | ||||
| 333585697 | 195 days ago | 0.00274098 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ArbswapSmartRouter
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./interfaces/IStableSwap.sol";
import "./interfaces/IStableSwapFactory.sol";
import "./interfaces/IArbswapV2Factory.sol";
import "./interfaces/IWETH02.sol";
import "./libraries/UniERC20.sol";
import "./libraries/SafeERC20.sol";
import "./libraries/ArbswapV2ExchangeLib.sol";
contract ArbswapSmartRouter is Ownable, ReentrancyGuard {
using UniERC20 for IERC20;
using SafeERC20 for IERC20;
using ArbswapV2ExchangeLib for IArbswapV2Exchange;
enum FLAG {
STABLE_SWAP,
V2_EXACT_IN
}
IWETH02 public immutable weth;
address public immutable arbswapV2;
address public stableswapFactory;
event NewStableSwapFactory(address indexed sender, address indexed factory);
event SwapMulti(
address indexed sender,
address indexed srcTokenAddr,
address indexed dstTokenAddr,
uint256 srcAmount
);
event Swap(
address indexed sender,
address indexed srcTokenAddr,
address indexed dstTokenAddr,
uint256 srcAmount
);
fallback() external {}
receive() external payable {}
/*
* @notice Constructor
* @param _WETHAddress: address of the WETH contract
* @param _arbswapV2: address of the ArbswapFactory
* @param _stableswapFactory: address of the StableSwapFactory
*/
constructor(
address _WETHAddress,
address _arbswapV2,
address _stableswapFactory
) {
weth = IWETH02(_WETHAddress);
arbswapV2 = _arbswapV2;
stableswapFactory = _stableswapFactory;
}
/**
* @notice Sets treasury address
* @dev Only callable by the contract owner.
*/
function setStableSwapFactory(address _factory) external onlyOwner {
require(
_factory != address(0),
"StableSwap factory cannot be zero address"
);
stableswapFactory = _factory;
emit NewStableSwapFactory(msg.sender, stableswapFactory);
}
function swapMulti(
IERC20[] calldata tokens,
uint256 amount,
uint256 minReturn,
FLAG[] calldata flags
) public payable nonReentrant returns (uint256 returnAmount) {
require(tokens.length == flags.length + 1, "swapMulti: wrong length");
IERC20 srcToken = tokens[0];
IERC20 dstToken = tokens[tokens.length - 1];
if (srcToken == dstToken) {
return amount;
}
srcToken.uniTransferFrom(payable(msg.sender), address(this), amount);
uint256 receivedAmount = srcToken.uniBalanceOf(address(this));
for (uint256 i = 1; i < tokens.length; i++) {
if (tokens[i - 1] == tokens[i]) {
continue;
}
if (flags[i - 1] == FLAG.STABLE_SWAP) {
_swapOnStableSwap(
tokens[i - 1],
tokens[i],
tokens[i - 1].uniBalanceOf(address(this))
);
} else if (flags[i - 1] == FLAG.V2_EXACT_IN) {
_swapOnV2ExactIn(
tokens[i - 1],
tokens[i],
tokens[i - 1].uniBalanceOf(address(this))
);
}
}
returnAmount = dstToken.uniBalanceOf(address(this));
require(
returnAmount >= minReturn,
"swapMulti: return amount is less than minReturn"
);
uint256 inRefund = srcToken.uniBalanceOf(address(this));
emit SwapMulti(
msg.sender,
address(srcToken),
address(dstToken),
receivedAmount - inRefund
);
uint256 userBalanceBefore = dstToken.uniBalanceOf(msg.sender);
dstToken.uniTransfer(payable(msg.sender), returnAmount);
require(
dstToken.uniBalanceOf(msg.sender) - userBalanceBefore >= minReturn,
"swapMulti: incorrect user balance"
);
srcToken.uniTransfer(payable(msg.sender), inRefund);
}
function swap(
IERC20 srcToken,
IERC20 dstToken,
uint256 amount,
uint256 minReturn,
FLAG flag
) public payable nonReentrant returns (uint256 returnAmount) {
if (srcToken == dstToken) {
return amount;
}
srcToken.uniTransferFrom(payable(msg.sender), address(this), amount);
uint256 receivedAmount = srcToken.uniBalanceOf(address(this));
if (flag == FLAG.STABLE_SWAP) {
_swapOnStableSwap(srcToken, dstToken, receivedAmount);
} else if (flag == FLAG.V2_EXACT_IN) {
_swapOnV2ExactIn(srcToken, dstToken, receivedAmount);
}
returnAmount = dstToken.uniBalanceOf(address(this));
require(
returnAmount >= minReturn,
"swap: return amount is less than minReturn"
);
uint256 inRefund = srcToken.uniBalanceOf(address(this));
emit Swap(
msg.sender,
address(srcToken),
address(dstToken),
receivedAmount - inRefund
);
uint256 userBalanceBefore = dstToken.uniBalanceOf(msg.sender);
dstToken.uniTransfer(payable(msg.sender), returnAmount);
require(
dstToken.uniBalanceOf(msg.sender) - userBalanceBefore >= minReturn,
"swap: incorrect user balance"
);
srcToken.uniTransfer(payable(msg.sender), inRefund);
}
// Swap helpers
function _swapOnStableSwap(
IERC20 srcToken,
IERC20 dstToken,
uint256 amount
) internal {
require(
stableswapFactory != address(0),
"StableSwap factory cannot be zero address"
);
if (srcToken.isETH()) {
weth.deposit{value: amount}();
}
IERC20 srcTokenReal = srcToken.isETH() ? weth : srcToken;
IERC20 dstTokenReal = dstToken.isETH() ? weth : dstToken;
IStableSwapFactory.StableSwapPairInfo memory info = IStableSwapFactory(
stableswapFactory
).getPairInfo(address(srcTokenReal), address(dstTokenReal));
if (info.swapContract == address(0)) {
return;
}
IStableSwap stableSwap = IStableSwap(info.swapContract);
IERC20[] memory tokens = new IERC20[](2);
tokens[0] = IERC20(stableSwap.coins(uint256(0)));
tokens[1] = IERC20(stableSwap.coins(uint256(1)));
uint256 i = (srcTokenReal == tokens[0] ? 1 : 0) +
(srcTokenReal == tokens[1] ? 2 : 0);
uint256 j = (dstTokenReal == tokens[0] ? 1 : 0) +
(dstTokenReal == tokens[1] ? 2 : 0);
srcTokenReal.uniApprove(address(stableSwap), amount);
stableSwap.exchange(i - 1, j - 1, amount, 0);
if (dstToken.isETH()) {
weth.withdraw(weth.balanceOf(address(this)));
}
}
function _swapOnV2ExactIn(
IERC20 srcToken,
IERC20 dstToken,
uint256 amount
) internal returns (uint256 returnAmount) {
if (srcToken.isETH()) {
weth.deposit{value: amount}();
}
IERC20 srcTokenReal = srcToken.isETH() ? weth : srcToken;
IERC20 dstTokenReal = dstToken.isETH() ? weth : dstToken;
IArbswapV2Exchange exchange = IArbswapV2Factory(arbswapV2).getPair(
srcTokenReal,
dstTokenReal
);
srcTokenReal.safeTransfer(address(exchange), amount);
bool needSync;
(returnAmount, needSync) = exchange.getReturn(
srcTokenReal,
dstTokenReal,
amount
);
if (needSync) {
exchange.sync();
}
if (srcTokenReal < dstTokenReal) {
exchange.swap(0, returnAmount, address(this), "");
} else {
exchange.swap(returnAmount, 0, address(this), "");
}
if (dstToken.isETH()) {
weth.withdraw(weth.balanceOf(address(this)));
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IArbswapV2Exchange {
function getReserves()
external
view
returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function skim(address to) external;
function sync() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IArbswapV2Exchange.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IArbswapV2Factory {
function getPair(
IERC20 tokenA,
IERC20 tokenB
) external view returns (IArbswapV2Exchange pair);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
interface IDaiLikePermit {
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
interface IERC20MetadataUppercase {
function NAME() external view returns (string memory); // solhint-disable-line func-name-mixedcase
function SYMBOL() external view returns (string memory); // solhint-disable-line func-name-mixedcase
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStableSwap {
// solium-disable-next-line mixedcase
function get_dy(
uint256 i,
uint256 j,
uint256 dx
) external view returns (uint256 dy);
// solium-disable-next-line mixedcase
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 minDy
) external payable;
// solium-disable-next-line mixedcase
function coins(uint256 i) external view returns (address);
// solium-disable-next-line mixedcase
function balances(uint256 i) external view returns (uint256);
// solium-disable-next-line mixedcase
function A() external view returns (uint256);
// solium-disable-next-line mixedcase
function fee() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStableSwapFactory {
struct StableSwapPairInfo {
address swapContract;
address token0;
address token1;
address LPContract;
}
// solium-disable-next-line mixedcase
function pairLength() external view returns (uint256);
// solium-disable-next-line mixedcase
function getPairInfo(
address _tokenA,
address _tokenB
) external view returns (StableSwapPairInfo memory info);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH02 is IERC20 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../interfaces/IArbswapV2Factory.sol";
import "../interfaces/IArbswapV2Exchange.sol";
import "./UniERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
library ArbswapV2ExchangeLib {
using Math for uint256;
using UniERC20 for IERC20;
function getReturn(
IArbswapV2Exchange exchange,
IERC20 srcToken,
IERC20 dstToken,
uint256 amountIn
) internal view returns (uint256 result, bool needSync) {
uint256 reserveIn = srcToken.uniBalanceOf(address(exchange));
uint256 reserveOut = dstToken.uniBalanceOf(address(exchange));
(uint112 reserve0, uint112 reserve1, ) = exchange.getReserves();
if (srcToken > dstToken) {
(reserve0, reserve1) = (reserve1, reserve0);
}
amountIn = reserveIn - reserve0;
needSync = (reserveIn < reserve0 || reserveOut < reserve1);
uint256 amountInWithFee = amountIn * 997;
uint256 numerator = amountInWithFee * Math.min(reserveOut, reserve1);
uint256 denominator = Math.min(reserveIn, reserve0) *
1000 +
amountInWithFee;
result = (denominator == 0) ? 0 : numerator / denominator;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
/// @title Revert reason forwarder.
library RevertReasonForwarder {
/// @dev Forwards latest externall call revert.
function reRevert() internal pure {
// bubble up revert reason from latest external call
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "../interfaces/IDaiLikePermit.sol";
import "./RevertReasonForwarder.sol";
/// @title Implements efficient safe methods for ERC20 interface.
library SafeERC20 {
error SafeTransferFailed();
error SafeTransferFromFailed();
error ForceApproveFailed();
error SafeIncreaseAllowanceFailed();
error SafeDecreaseAllowanceFailed();
error SafePermitBadLength();
/// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
bytes4 selector = token.transferFrom.selector;
bool success;
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), from)
mstore(add(data, 0x24), to)
mstore(add(data, 0x44), amount)
success := call(gas(), token, 0, data, 100, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
if (!success) revert SafeTransferFromFailed();
}
/// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_makeCall(token, token.transfer.selector, to, value)) {
revert SafeTransferFailed();
}
}
/// @dev If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry.
function forceApprove(
IERC20 token,
address spender,
uint256 value
) internal {
if (!_makeCall(token, token.approve.selector, spender, value)) {
if (
!_makeCall(token, token.approve.selector, spender, 0) ||
!_makeCall(token, token.approve.selector, spender, value)
) {
revert ForceApproveFailed();
}
}
}
/// @dev Allowance increase with safe math check.
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > type(uint256).max - allowance)
revert SafeIncreaseAllowanceFailed();
forceApprove(token, spender, allowance + value);
}
/// @dev Allowance decrease with safe math check.
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > allowance) revert SafeDecreaseAllowanceFailed();
forceApprove(token, spender, allowance - value);
}
/// @dev Calls either ERC20 or Dai `permit` for `token`, if unsuccessful forwards revert from external call.
function safePermit(IERC20 token, bytes calldata permit) internal {
if (!tryPermit(token, permit)) RevertReasonForwarder.reRevert();
}
function tryPermit(
IERC20 token,
bytes calldata permit
) internal returns (bool) {
if (permit.length == 32 * 7) {
return
_makeCalldataCall(token, IERC20Permit.permit.selector, permit);
}
if (permit.length == 32 * 8) {
return
_makeCalldataCall(
token,
IDaiLikePermit.permit.selector,
permit
);
}
revert SafePermitBadLength();
}
function _makeCall(
IERC20 token,
bytes4 selector,
address to,
uint256 amount
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), to)
mstore(add(data, 0x24), amount)
success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
function _makeCalldataCall(
IERC20 token,
bytes4 selector,
bytes calldata args
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let len := add(4, args.length)
let data := mload(0x40)
mstore(data, selector)
calldatacopy(add(data, 0x04), args.offset, args.length)
success := call(gas(), token, 0, data, len, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
/// @title Library with gas-efficient string operations
library StringUtil {
function toHex(uint256 value) internal pure returns (string memory) {
return toHex(abi.encodePacked(value));
}
function toHex(address value) internal pure returns (string memory) {
return toHex(abi.encodePacked(value));
}
/// @dev this is the assembly adaptation of highly optimized toHex16 code from Mikhail Vladimirov
/// https://stackoverflow.com/a/69266989
function toHex(
bytes memory data
) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
function _toHex16(input) -> output {
output := or(
and(
input,
0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000
),
shr(
64,
and(
input,
0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000
)
)
)
output := or(
and(
output,
0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000
),
shr(
32,
and(
output,
0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000
)
)
)
output := or(
and(
output,
0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000
),
shr(
16,
and(
output,
0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000
)
)
)
output := or(
and(
output,
0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
),
shr(
8,
and(
output,
0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000
)
)
)
output := or(
shr(
4,
and(
output,
0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000
)
),
shr(
8,
and(
output,
0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00
)
)
)
output := add(
add(
0x3030303030303030303030303030303030303030303030303030303030303030,
output
),
mul(
and(
shr(
4,
add(
output,
0x0606060606060606060606060606060606060606060606060606060606060606
)
),
0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
),
7 // Change 7 to 39 for lower case output
)
)
}
result := mload(0x40)
let length := mload(data)
let resultLength := shl(1, length)
let toPtr := add(result, 0x22) // 32 bytes for length + 2 bytes for '0x'
mstore(0x40, add(toPtr, resultLength)) // move free memory pointer
mstore(add(result, 2), 0x3078) // 0x3078 is right aligned so we write to `result + 2`
// to store the last 2 bytes in the beginning of the string
mstore(result, add(resultLength, 2)) // extra 2 bytes for '0x'
for {
let fromPtr := add(data, 0x20)
let endPtr := add(fromPtr, length)
} lt(fromPtr, endPtr) {
fromPtr := add(fromPtr, 0x20)
} {
let rawData := mload(fromPtr)
let hexData := _toHex16(rawData)
mstore(toPtr, hexData)
toPtr := add(toPtr, 0x20)
hexData := _toHex16(shl(128, rawData))
mstore(toPtr, hexData)
toPtr := add(toPtr, 0x20)
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v1;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "../interfaces/IERC20MetadataUppercase.sol";
import "./SafeERC20.sol";
import "./StringUtil.sol";
/// @title Library, which allows usage of ETH as ERC20 and ERC20 itself. Uses SafeERC20 library for ERC20 interface.
library UniERC20 {
using SafeERC20 for IERC20;
error InsufficientBalance();
error ApproveCalledOnETH();
error NotEnoughValue();
error FromIsNotSender();
error ToIsNotThis();
error ETHTransferFailed();
uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
IERC20 private constant _ETH_ADDRESS =
IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
IERC20 private constant _ZERO_ADDRESS = IERC20(address(0));
/// @dev Returns true if `token` is ETH.
function isETH(IERC20 token) internal pure returns (bool) {
return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS);
}
/// @dev Returns `account` ERC20 `token` balance.
function uniBalanceOf(
IERC20 token,
address account
) internal view returns (uint256) {
if (isETH(token)) {
return account.balance;
} else {
return token.balanceOf(account);
}
}
/// @dev `token` transfer `to` `amount`.
/// Note that this function does nothing in case of zero amount.
function uniTransfer(
IERC20 token,
address payable to,
uint256 amount
) internal {
if (amount > 0) {
if (isETH(token)) {
if (address(this).balance < amount)
revert InsufficientBalance();
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = to.call{
value: amount,
gas: _RAW_CALL_GAS_LIMIT
}("");
if (!success) revert ETHTransferFailed();
} else {
token.safeTransfer(to, amount);
}
}
}
/// @dev `token` transfer `from` `to` `amount`.
/// Note that this function does nothing in case of zero amount.
function uniTransferFrom(
IERC20 token,
address payable from,
address to,
uint256 amount
) internal {
if (amount > 0) {
if (isETH(token)) {
if (msg.value < amount) revert NotEnoughValue();
if (from != msg.sender) revert FromIsNotSender();
if (to != address(this)) revert ToIsNotThis();
if (msg.value > amount) {
// Return remainder if exist
unchecked {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = from.call{
value: msg.value - amount,
gas: _RAW_CALL_GAS_LIMIT
}("");
if (!success) revert ETHTransferFailed();
}
}
} else {
token.safeTransferFrom(from, to, amount);
}
}
}
/// @dev Returns `token` symbol from ERC20 metadata.
function uniSymbol(IERC20 token) internal view returns (string memory) {
return
_uniDecode(
token,
IERC20Metadata.symbol.selector,
IERC20MetadataUppercase.SYMBOL.selector
);
}
/// @dev Returns `token` name from ERC20 metadata.
function uniName(IERC20 token) internal view returns (string memory) {
return
_uniDecode(
token,
IERC20Metadata.name.selector,
IERC20MetadataUppercase.NAME.selector
);
}
/// @dev Reverts if `token` is ETH, otherwise performs ERC20 forceApprove.
function uniApprove(IERC20 token, address to, uint256 amount) internal {
if (isETH(token)) revert ApproveCalledOnETH();
token.forceApprove(to, amount);
}
/// @dev 20K gas is provided to account for possible implementations of name/symbol
/// (token implementation might be behind proxy or store the value in storage)
function _uniDecode(
IERC20 token,
bytes4 lowerCaseSelector,
bytes4 upperCaseSelector
) private view returns (string memory result) {
if (isETH(token)) {
return "ETH";
}
(bool success, bytes memory data) = address(token).staticcall{
gas: 20000
}(abi.encodeWithSelector(lowerCaseSelector));
if (!success) {
(success, data) = address(token).staticcall{gas: 20000}(
abi.encodeWithSelector(upperCaseSelector)
);
}
if (success && data.length >= 0x40) {
(uint256 offset, uint256 len) = abi.decode(
data,
(uint256, uint256)
);
/*
return data is padded up to 32 bytes with ABI encoder also sometimes
there is extra 32 bytes of zeros padded in the end:
https://github.com/ethereum/solidity/issues/10170
because of that we can't check for equality and instead check
that overall data length is greater or equal than string length + extra 64 bytes
*/
if (offset == 0x20 && data.length >= 0x40 + len) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
result := add(data, 0x40)
}
return result;
}
}
if (success && data.length == 32) {
uint256 len = 0;
while (
len < data.length && data[len] >= 0x20 && data[len] <= 0x7E
) {
unchecked {
len++;
}
}
if (len > 0) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
mstore(data, len)
}
return string(data);
}
}
return StringUtil.toHex(address(token));
}
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_WETHAddress","type":"address"},{"internalType":"address","name":"_arbswapV2","type":"address"},{"internalType":"address","name":"_stableswapFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApproveCalledOnETH","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"ForceApproveFailed","type":"error"},{"inputs":[],"name":"FromIsNotSender","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"NotEnoughValue","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"SafeTransferFromFailed","type":"error"},{"inputs":[],"name":"ToIsNotThis","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"factory","type":"address"}],"name":"NewStableSwapFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"srcTokenAddr","type":"address"},{"indexed":true,"internalType":"address","name":"dstTokenAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcAmount","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"srcTokenAddr","type":"address"},{"indexed":true,"internalType":"address","name":"dstTokenAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcAmount","type":"uint256"}],"name":"SwapMulti","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"arbswapV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"setStableSwapFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stableswapFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"srcToken","type":"address"},{"internalType":"contract IERC20","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"enum ArbswapSmartRouter.FLAG","name":"flag","type":"uint8"}],"name":"swap","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"enum ArbswapSmartRouter.FLAG[]","name":"flags","type":"uint8[]"}],"name":"swapMulti","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c06040523480156200001157600080fd5b50604051620038ff380380620038ff833981810160405281019062000037919062000246565b620000576200004b6200011060201b60201c565b6200011860201b60201c565b600180819055508273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050620002a2565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200020e82620001e1565b9050919050565b620002208162000201565b81146200022c57600080fd5b50565b600081519050620002408162000215565b92915050565b600080600060608486031215620002625762000261620001dc565b5b600062000272868287016200022f565b935050602062000285868287016200022f565b925050604062000298868287016200022f565b9150509250925092565b60805160a0516135ea62000315600039600081816102770152611c20015260008181610216015281816113600152818161140d0152818161145c015281816119a6015281816119e201528181611afe01528181611bab01528181611bfa01528181611ec50152611f0101526135ea6000f3fe60806040526004361061008a5760003560e01c8063a6cbf41711610059578063a6cbf41714610137578063ca24fde814610167578063d5f5911614610197578063e449d77c146101c2578063f2fde38b146101eb57610091565b80633fc8cef31461009f578063715018a6146100ca5780638da5cb5b146100e15780639686e9ec1461010c57610091565b3661009157005b34801561009d57600080fd5b005b3480156100ab57600080fd5b506100b4610214565b6040516100c19190612682565b60405180910390f35b3480156100d657600080fd5b506100df610238565b005b3480156100ed57600080fd5b506100f661024c565b60405161010391906126be565b60405180910390f35b34801561011857600080fd5b50610121610275565b60405161012e91906126be565b60405180910390f35b610151600480360381019061014c9190612786565b610299565b60405161015e9190612810565b60405180910390f35b610181600480360381019061017c91906128e6565b6105dd565b60405161018e9190612810565b60405180910390f35b3480156101a357600080fd5b506101ac610c67565b6040516101b991906126be565b60405180910390f35b3480156101ce57600080fd5b506101e960048036038101906101e491906129b9565b610c8d565b005b3480156101f757600080fd5b50610212600480360381019061020d91906129b9565b610dc4565b005b7f000000000000000000000000000000000000000000000000000000000000000081565b610240610e47565b61024a6000610ec5565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006102a3610f89565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16036102de578390506105cc565b61030b3330868973ffffffffffffffffffffffffffffffffffffffff16610fd8909392919063ffffffff16565b6000610336308873ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90506000600181111561034c5761034b6129e6565b5b83600181111561035f5761035e6129e6565b5b036103745761036f8787836112a9565b6103ad565b600180811115610387576103866129e6565b5b83600181111561039a576103996129e6565b5b036103ac576103aa878783611ad6565b505b5b6103d6308773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b91508382101561041b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041290612a98565b60405180910390fd5b6000610446308973ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fffebebfb273923089a3ed6bac0fd4686ac740307859becadeb82f998e30db61484866104ba9190612ae7565b6040516104c79190612810565b60405180910390a460006104fa338973ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b905061052733858a73ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b8581610552338b73ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b61055c9190612ae7565b101561059d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059490612b67565b60405180910390fd5b6105c833838b73ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b5050505b6105d4612121565b95945050505050565b60006105e7610f89565b6001838390506105f79190612b87565b878790501461063b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063290612c07565b60405180910390fd5b60008787600081811061065157610650612c27565b5b90506020020160208101906106669190612c56565b90506000888860018b8b905061067c9190612ae7565b81811061068c5761068b612c27565b5b90506020020160208101906106a19190612c56565b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106e0578692505050610c55565b61070d3330898573ffffffffffffffffffffffffffffffffffffffff16610fd8909392919063ffffffff16565b6000610738308473ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90506000600190505b8a8a9050811015610a33578a8a8281811061075f5761075e612c27565b5b90506020020160208101906107749190612c56565b73ffffffffffffffffffffffffffffffffffffffff168b8b6001846107999190612ae7565b8181106107a9576107a8612c27565b5b90506020020160208101906107be9190612c56565b73ffffffffffffffffffffffffffffffffffffffff160315610a2057600060018111156107ee576107ed6129e6565b5b87876001846107fd9190612ae7565b81811061080d5761080c612c27565b5b90506020020160208101906108229190612c83565b6001811115610834576108336129e6565b5b036108fe576108f98b8b60018461084b9190612ae7565b81811061085b5761085a612c27565b5b90506020020160208101906108709190612c56565b8c8c8481811061088357610882612c27565b5b90506020020160208101906108989190612c56565b6108f4308f8f6001886108ab9190612ae7565b8181106108bb576108ba612c27565b5b90506020020160208101906108d09190612c56565b73ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b6112a9565b610a1f565b600180811115610911576109106129e6565b5b87876001846109209190612ae7565b8181106109305761092f612c27565b5b90506020020160208101906109459190612c83565b6001811115610957576109566129e6565b5b03610a1e57610a1c8b8b60018461096e9190612ae7565b81811061097e5761097d612c27565b5b90506020020160208101906109939190612c56565b8c8c848181106109a6576109a5612c27565b5b90506020020160208101906109bb9190612c56565b610a17308f8f6001886109ce9190612ae7565b8181106109de576109dd612c27565b5b90506020020160208101906109f39190612c56565b73ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b611ad6565b505b5b5b8080610a2b90612cb0565b915050610741565b50610a5d308373ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b935086841015610aa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9990612d6a565b60405180910390fd5b6000610acd308573ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe8b92af316c53d808857f3a3735b431e5fd03fb223bfb8a397af9c179974bed48486610b419190612ae7565b604051610b4e9190612810565b60405180910390a46000610b81338573ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b9050610bae33878673ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b8881610bd9338773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b610be39190612ae7565b1015610c24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1b90612dfc565b60405180910390fd5b610c4f33838773ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b50505050505b610c5d612121565b9695505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c95610e47565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cfb90612e8e565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff09c33b4a1bf40cbb338d09d6de033e08e296d62f61d55e9f72ea9c8a9d4173860405160405180910390a350565b610dcc610e47565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3290612f20565b60405180910390fd5b610e4481610ec5565b50565b610e4f61212a565b73ffffffffffffffffffffffffffffffffffffffff16610e6d61024c565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90612f8c565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600260015403610fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc590612ff8565b60405180910390fd5b6002600181905550565b60008111156111d857610fea84612132565b156111a95780341015611029576040517fe2f844a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461108e576040517f2a9c363d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146110f3576040517f57ca390a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803411156111a45760008373ffffffffffffffffffffffffffffffffffffffff1682340361138890604051806000019050600060405180830381858888f193505050503d8060008114611162576040519150601f19603f3d011682016040523d82523d6000602084013e611167565b606091505b50509050806111a2576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6111d7565b6111d68383838773ffffffffffffffffffffffffffffffffffffffff166121b4909392919063ffffffff16565b5b5b50505050565b60006111e983612132565b1561120d578173ffffffffffffffffffffffffffffffffffffffff163190506112a3565b8273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381865afa158015611279573d6000803e3d6000fd5b505050506040513d602081101561128f57600080fd5b810190808051906020019092919050505090505b92915050565b600073ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612e8e565b60405180910390fd5b6113598373ffffffffffffffffffffffffffffffffffffffff16612132565b156113e0577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156113c657600080fd5b505af11580156113da573d6000803e3d6000fd5b50505050505b60006114018473ffffffffffffffffffffffffffffffffffffffff16612132565b61140b578361142d565b7f00000000000000000000000000000000000000000000000000000000000000005b905060006114508473ffffffffffffffffffffffffffffffffffffffff16612132565b61145a578361147c565b7f00000000000000000000000000000000000000000000000000000000000000005b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663400f7a1e84846040518363ffffffff1660e01b81526004016114dd929190613018565b608060405180830381865afa1580156114fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151e919061315f565b9050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff160361156057505050611ad1565b6000816000015190506000600267ffffffffffffffff81111561158657611585613057565b5b6040519080825280602002602001820160405280156115b45781602001602082028036833780820191505090505b5090508173ffffffffffffffffffffffffffffffffffffffff1663c661065760006040518263ffffffff1660e01b81526004016115f19190612810565b602060405180830381865afa15801561160e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611632919061318c565b8160008151811061164657611645612c27565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1663c661065760016040518263ffffffff1660e01b81526004016116ba9190612810565b602060405180830381865afa1580156116d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fb919061318c565b8160018151811061170f5761170e612c27565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008160018151811061175f5761175e612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146117a05760006117a3565b60025b826000815181106117b7576117b6612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16146117f85760006117fb565b60015b61180591906131c6565b60ff1690506000826001815181106118205761181f612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611861576000611864565b60025b8360008151811061187857611877612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16146118b95760006118bc565b60015b6118c691906131c6565b60ff1690506118f684898973ffffffffffffffffffffffffffffffffffffffff166122539092919063ffffffff16565b8373ffffffffffffffffffffffffffffffffffffffff16635b41b90860018461191f9190612ae7565b60018461192c9190612ae7565b8b60006040518563ffffffff1660e01b815260040161194e9493929190613236565b600060405180830381600087803b15801561196857600080fd5b505af115801561197c573d6000803e3d6000fd5b5050505061199f8973ffffffffffffffffffffffffffffffffffffffff16612132565b15611ac9577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611a3991906126be565b602060405180830381865afa158015611a56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7a9190613290565b6040518263ffffffff1660e01b8152600401611a969190612810565b600060405180830381600087803b158015611ab057600080fd5b505af1158015611ac4573d6000803e3d6000fd5b505050505b505050505050505b505050565b6000611af78473ffffffffffffffffffffffffffffffffffffffff16612132565b15611b7e577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b6457600080fd5b505af1158015611b78573d6000803e3d6000fd5b50505050505b6000611b9f8573ffffffffffffffffffffffffffffffffffffffff16612132565b611ba95784611bcb565b7f00000000000000000000000000000000000000000000000000000000000000005b90506000611bee8573ffffffffffffffffffffffffffffffffffffffff16612132565b611bf85784611c1a565b7f00000000000000000000000000000000000000000000000000000000000000005b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e6a4390584846040518363ffffffff1660e01b8152600401611c799291906132de565b602060405180830381865afa158015611c96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cba9190613345565b9050611ce781868573ffffffffffffffffffffffffffffffffffffffff166122c39092919063ffffffff16565b6000611d168484888573ffffffffffffffffffffffffffffffffffffffff16612311909392919063ffffffff16565b80925081965050508015611d85578173ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050505b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161015611e2e578173ffffffffffffffffffffffffffffffffffffffff1663022c0d9f600087306040518463ffffffff1660e01b8152600401611df7939291906133a9565b600060405180830381600087803b158015611e1157600080fd5b505af1158015611e25573d6000803e3d6000fd5b50505050611e9f565b8173ffffffffffffffffffffffffffffffffffffffff1663022c0d9f866000306040518463ffffffff1660e01b8152600401611e6c939291906133f3565b600060405180830381600087803b158015611e8657600080fd5b505af1158015611e9a573d6000803e3d6000fd5b505050505b611ebe8773ffffffffffffffffffffffffffffffffffffffff16612132565b15611fe8577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611f5891906126be565b602060405180830381865afa158015611f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f999190613290565b6040518263ffffffff1660e01b8152600401611fb59190612810565b600060405180830381600087803b158015611fcf57600080fd5b505af1158015611fe3573d6000803e3d6000fd5b505050505b505050509392505050565b600081111561211c5761200583612132565b156120ef5780471015612044576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168261138890604051806000019050600060405180830381858888f193505050503d80600081146120a9576040519150601f19603f3d011682016040523d82523d6000602084013e6120ae565b606091505b50509050806120e9576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5061211b565b61211a82828573ffffffffffffffffffffffffffffffffffffffff166122c39092919063ffffffff16565b5b5b505050565b60018081905550565b600033905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806121ad575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af191508115612213573d6000811461220957600160005114601f3d11169250612211565b6000883b1192505b505b508061224b576040517ff405907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b61225c83612132565b15612293576040517f4ca17a9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122be82828573ffffffffffffffffffffffffffffffffffffffff166125109092919063ffffffff16565b505050565b6122d68363a9059cbb60e01b8484612594565b61230c576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b600080600061233f878773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b9050600061236c888773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90506000808973ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156123bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e091906134bf565b50915091508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16111561242457808280925081935050505b816dffffffffffffffffffffffffffff16846124409190612ae7565b9650816dffffffffffffffffffffffffffff1684108061246f5750806dffffffffffffffffffffffffffff1683105b945060006103e5886124819190613512565b9050600061249f85846dffffffffffffffffffffffffffff166125ea565b826124aa9190613512565b90506000826103e86124cc89886dffffffffffffffffffffffffffff166125ea565b6124d69190613512565b6124e09190612b87565b9050600081146124fb5780826124f69190613583565b6124fe565b60005b98505050505050505094509492505050565b6125238363095ea7b360e01b8484612594565b61258f5761253b8363095ea7b360e01b846000612594565b158061255757506125558363095ea7b360e01b8484612594565b155b1561258e576040517f19be9a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b505050565b60006040518481528360048201528260248201526020600060448360008a5af1915081156125e1573d600081146125d757600160005114601f3d111692506125df565b6000873b1192505b505b50949350505050565b60008183106125f957816125fb565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061264861264361263e84612603565b612623565b612603565b9050919050565b600061265a8261262d565b9050919050565b600061266c8261264f565b9050919050565b61267c81612661565b82525050565b60006020820190506126976000830184612673565b92915050565b60006126a882612603565b9050919050565b6126b88161269d565b82525050565b60006020820190506126d360008301846126af565b92915050565b6000604051905090565b600080fd5b600080fd5b60006126f88261269d565b9050919050565b612708816126ed565b811461271357600080fd5b50565b600081359050612725816126ff565b92915050565b6000819050919050565b61273e8161272b565b811461274957600080fd5b50565b60008135905061275b81612735565b92915050565b6002811061276e57600080fd5b50565b60008135905061278081612761565b92915050565b600080600080600060a086880312156127a2576127a16126e3565b5b60006127b088828901612716565b95505060206127c188828901612716565b94505060406127d28882890161274c565b93505060606127e38882890161274c565b92505060806127f488828901612771565b9150509295509295909350565b61280a8161272b565b82525050565b60006020820190506128256000830184612801565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126128505761284f61282b565b5b8235905067ffffffffffffffff81111561286d5761286c612830565b5b60208301915083602082028301111561288957612888612835565b5b9250929050565b60008083601f8401126128a6576128a561282b565b5b8235905067ffffffffffffffff8111156128c3576128c2612830565b5b6020830191508360208202830111156128df576128de612835565b5b9250929050565b60008060008060008060808789031215612903576129026126e3565b5b600087013567ffffffffffffffff811115612921576129206126e8565b5b61292d89828a0161283a565b9650965050602061294089828a0161274c565b945050604061295189828a0161274c565b935050606087013567ffffffffffffffff811115612972576129716126e8565b5b61297e89828a01612890565b92509250509295509295509295565b6129968161269d565b81146129a157600080fd5b50565b6000813590506129b38161298d565b92915050565b6000602082840312156129cf576129ce6126e3565b5b60006129dd848285016129a4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600082825260208201905092915050565b7f737761703a2072657475726e20616d6f756e74206973206c657373207468616e60008201527f206d696e52657475726e00000000000000000000000000000000000000000000602082015250565b6000612a82602a83612a15565b9150612a8d82612a26565b604082019050919050565b60006020820190508181036000830152612ab181612a75565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612af28261272b565b9150612afd8361272b565b9250828203905081811115612b1557612b14612ab8565b5b92915050565b7f737761703a20696e636f727265637420757365722062616c616e636500000000600082015250565b6000612b51601c83612a15565b9150612b5c82612b1b565b602082019050919050565b60006020820190508181036000830152612b8081612b44565b9050919050565b6000612b928261272b565b9150612b9d8361272b565b9250828201905080821115612bb557612bb4612ab8565b5b92915050565b7f737761704d756c74693a2077726f6e67206c656e677468000000000000000000600082015250565b6000612bf1601783612a15565b9150612bfc82612bbb565b602082019050919050565b60006020820190508181036000830152612c2081612be4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612c6c57612c6b6126e3565b5b6000612c7a84828501612716565b91505092915050565b600060208284031215612c9957612c986126e3565b5b6000612ca784828501612771565b91505092915050565b6000612cbb8261272b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612ced57612cec612ab8565b5b600182019050919050565b7f737761704d756c74693a2072657475726e20616d6f756e74206973206c65737360008201527f207468616e206d696e52657475726e0000000000000000000000000000000000602082015250565b6000612d54602f83612a15565b9150612d5f82612cf8565b604082019050919050565b60006020820190508181036000830152612d8381612d47565b9050919050565b7f737761704d756c74693a20696e636f727265637420757365722062616c616e6360008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000612de6602183612a15565b9150612df182612d8a565b604082019050919050565b60006020820190508181036000830152612e1581612dd9565b9050919050565b7f537461626c655377617020666163746f72792063616e6e6f74206265207a657260008201527f6f20616464726573730000000000000000000000000000000000000000000000602082015250565b6000612e78602983612a15565b9150612e8382612e1c565b604082019050919050565b60006020820190508181036000830152612ea781612e6b565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612f0a602683612a15565b9150612f1582612eae565b604082019050919050565b60006020820190508181036000830152612f3981612efd565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612f76602083612a15565b9150612f8182612f40565b602082019050919050565b60006020820190508181036000830152612fa581612f69565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612fe2601f83612a15565b9150612fed82612fac565b602082019050919050565b6000602082019050818103600083015261301181612fd5565b9050919050565b600060408201905061302d60008301856126af565b61303a60208301846126af565b9392505050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61308f82613046565b810181811067ffffffffffffffff821117156130ae576130ad613057565b5b80604052505050565b60006130c16126d9565b90506130cd8282613086565b919050565b6000815190506130e18161298d565b92915050565b6000608082840312156130fd576130fc613041565b5b61310760806130b7565b90506000613117848285016130d2565b600083015250602061312b848285016130d2565b602083015250604061313f848285016130d2565b6040830152506060613153848285016130d2565b60608301525092915050565b600060808284031215613175576131746126e3565b5b6000613183848285016130e7565b91505092915050565b6000602082840312156131a2576131a16126e3565b5b60006131b0848285016130d2565b91505092915050565b600060ff82169050919050565b60006131d1826131b9565b91506131dc836131b9565b9250828201905060ff8111156131f5576131f4612ab8565b5b92915050565b6000819050919050565b600061322061321b613216846131fb565b612623565b61272b565b9050919050565b61323081613205565b82525050565b600060808201905061324b6000830187612801565b6132586020830186612801565b6132656040830185612801565b6132726060830184613227565b95945050505050565b60008151905061328a81612735565b92915050565b6000602082840312156132a6576132a56126e3565b5b60006132b48482850161327b565b91505092915050565b60006132c88261264f565b9050919050565b6132d8816132bd565b82525050565b60006040820190506132f360008301856132cf565b61330060208301846132cf565b9392505050565b60006133128261269d565b9050919050565b61332281613307565b811461332d57600080fd5b50565b60008151905061333f81613319565b92915050565b60006020828403121561335b5761335a6126e3565b5b600061336984828501613330565b91505092915050565b600082825260208201905092915050565b50565b6000613393600083613372565b915061339e82613383565b600082019050919050565b60006080820190506133be6000830186613227565b6133cb6020830185612801565b6133d860408301846126af565b81810360608301526133e981613386565b9050949350505050565b60006080820190506134086000830186612801565b6134156020830185613227565b61342260408301846126af565b818103606083015261343381613386565b9050949350505050565b60006dffffffffffffffffffffffffffff82169050919050565b6134608161343d565b811461346b57600080fd5b50565b60008151905061347d81613457565b92915050565b600063ffffffff82169050919050565b61349c81613483565b81146134a757600080fd5b50565b6000815190506134b981613493565b92915050565b6000806000606084860312156134d8576134d76126e3565b5b60006134e68682870161346e565b93505060206134f78682870161346e565b9250506040613508868287016134aa565b9150509250925092565b600061351d8261272b565b91506135288361272b565b92508282026135368161272b565b9150828204841483151761354d5761354c612ab8565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061358e8261272b565b91506135998361272b565b9250826135a9576135a8613554565b5b82820490509291505056fea2646970667358221220c1a913a6f89b510d8ae1fd44b42845a832bcd9e244351caeb56727f440c1d4c964736f6c6343000812003300000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000d394e9cc20f43d2651293756f8d320668e850f1b0000000000000000000000003a52e9200ed7403d9d21664fdee540c2d02c099d
Deployed Bytecode
0x60806040526004361061008a5760003560e01c8063a6cbf41711610059578063a6cbf41714610137578063ca24fde814610167578063d5f5911614610197578063e449d77c146101c2578063f2fde38b146101eb57610091565b80633fc8cef31461009f578063715018a6146100ca5780638da5cb5b146100e15780639686e9ec1461010c57610091565b3661009157005b34801561009d57600080fd5b005b3480156100ab57600080fd5b506100b4610214565b6040516100c19190612682565b60405180910390f35b3480156100d657600080fd5b506100df610238565b005b3480156100ed57600080fd5b506100f661024c565b60405161010391906126be565b60405180910390f35b34801561011857600080fd5b50610121610275565b60405161012e91906126be565b60405180910390f35b610151600480360381019061014c9190612786565b610299565b60405161015e9190612810565b60405180910390f35b610181600480360381019061017c91906128e6565b6105dd565b60405161018e9190612810565b60405180910390f35b3480156101a357600080fd5b506101ac610c67565b6040516101b991906126be565b60405180910390f35b3480156101ce57600080fd5b506101e960048036038101906101e491906129b9565b610c8d565b005b3480156101f757600080fd5b50610212600480360381019061020d91906129b9565b610dc4565b005b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab181565b610240610e47565b61024a6000610ec5565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000d394e9cc20f43d2651293756f8d320668e850f1b81565b60006102a3610f89565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16036102de578390506105cc565b61030b3330868973ffffffffffffffffffffffffffffffffffffffff16610fd8909392919063ffffffff16565b6000610336308873ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90506000600181111561034c5761034b6129e6565b5b83600181111561035f5761035e6129e6565b5b036103745761036f8787836112a9565b6103ad565b600180811115610387576103866129e6565b5b83600181111561039a576103996129e6565b5b036103ac576103aa878783611ad6565b505b5b6103d6308773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b91508382101561041b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041290612a98565b60405180910390fd5b6000610446308973ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fffebebfb273923089a3ed6bac0fd4686ac740307859becadeb82f998e30db61484866104ba9190612ae7565b6040516104c79190612810565b60405180910390a460006104fa338973ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b905061052733858a73ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b8581610552338b73ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b61055c9190612ae7565b101561059d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059490612b67565b60405180910390fd5b6105c833838b73ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b5050505b6105d4612121565b95945050505050565b60006105e7610f89565b6001838390506105f79190612b87565b878790501461063b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063290612c07565b60405180910390fd5b60008787600081811061065157610650612c27565b5b90506020020160208101906106669190612c56565b90506000888860018b8b905061067c9190612ae7565b81811061068c5761068b612c27565b5b90506020020160208101906106a19190612c56565b90508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106e0578692505050610c55565b61070d3330898573ffffffffffffffffffffffffffffffffffffffff16610fd8909392919063ffffffff16565b6000610738308473ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90506000600190505b8a8a9050811015610a33578a8a8281811061075f5761075e612c27565b5b90506020020160208101906107749190612c56565b73ffffffffffffffffffffffffffffffffffffffff168b8b6001846107999190612ae7565b8181106107a9576107a8612c27565b5b90506020020160208101906107be9190612c56565b73ffffffffffffffffffffffffffffffffffffffff160315610a2057600060018111156107ee576107ed6129e6565b5b87876001846107fd9190612ae7565b81811061080d5761080c612c27565b5b90506020020160208101906108229190612c83565b6001811115610834576108336129e6565b5b036108fe576108f98b8b60018461084b9190612ae7565b81811061085b5761085a612c27565b5b90506020020160208101906108709190612c56565b8c8c8481811061088357610882612c27565b5b90506020020160208101906108989190612c56565b6108f4308f8f6001886108ab9190612ae7565b8181106108bb576108ba612c27565b5b90506020020160208101906108d09190612c56565b73ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b6112a9565b610a1f565b600180811115610911576109106129e6565b5b87876001846109209190612ae7565b8181106109305761092f612c27565b5b90506020020160208101906109459190612c83565b6001811115610957576109566129e6565b5b03610a1e57610a1c8b8b60018461096e9190612ae7565b81811061097e5761097d612c27565b5b90506020020160208101906109939190612c56565b8c8c848181106109a6576109a5612c27565b5b90506020020160208101906109bb9190612c56565b610a17308f8f6001886109ce9190612ae7565b8181106109de576109dd612c27565b5b90506020020160208101906109f39190612c56565b73ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b611ad6565b505b5b5b8080610a2b90612cb0565b915050610741565b50610a5d308373ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b935086841015610aa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9990612d6a565b60405180910390fd5b6000610acd308573ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe8b92af316c53d808857f3a3735b431e5fd03fb223bfb8a397af9c179974bed48486610b419190612ae7565b604051610b4e9190612810565b60405180910390a46000610b81338573ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b9050610bae33878673ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b8881610bd9338773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b610be39190612ae7565b1015610c24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1b90612dfc565b60405180910390fd5b610c4f33838773ffffffffffffffffffffffffffffffffffffffff16611ff39092919063ffffffff16565b50505050505b610c5d612121565b9695505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c95610e47565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cfb90612e8e565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff09c33b4a1bf40cbb338d09d6de033e08e296d62f61d55e9f72ea9c8a9d4173860405160405180910390a350565b610dcc610e47565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3290612f20565b60405180910390fd5b610e4481610ec5565b50565b610e4f61212a565b73ffffffffffffffffffffffffffffffffffffffff16610e6d61024c565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90612f8c565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600260015403610fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc590612ff8565b60405180910390fd5b6002600181905550565b60008111156111d857610fea84612132565b156111a95780341015611029576040517fe2f844a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461108e576040517f2a9c363d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146110f3576040517f57ca390a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803411156111a45760008373ffffffffffffffffffffffffffffffffffffffff1682340361138890604051806000019050600060405180830381858888f193505050503d8060008114611162576040519150601f19603f3d011682016040523d82523d6000602084013e611167565b606091505b50509050806111a2576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6111d7565b6111d68383838773ffffffffffffffffffffffffffffffffffffffff166121b4909392919063ffffffff16565b5b5b50505050565b60006111e983612132565b1561120d578173ffffffffffffffffffffffffffffffffffffffff163190506112a3565b8273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381865afa158015611279573d6000803e3d6000fd5b505050506040513d602081101561128f57600080fd5b810190808051906020019092919050505090505b92915050565b600073ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161133190612e8e565b60405180910390fd5b6113598373ffffffffffffffffffffffffffffffffffffffff16612132565b156113e0577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156113c657600080fd5b505af11580156113da573d6000803e3d6000fd5b50505050505b60006114018473ffffffffffffffffffffffffffffffffffffffff16612132565b61140b578361142d565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab15b905060006114508473ffffffffffffffffffffffffffffffffffffffff16612132565b61145a578361147c565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab15b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663400f7a1e84846040518363ffffffff1660e01b81526004016114dd929190613018565b608060405180830381865afa1580156114fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151e919061315f565b9050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff160361156057505050611ad1565b6000816000015190506000600267ffffffffffffffff81111561158657611585613057565b5b6040519080825280602002602001820160405280156115b45781602001602082028036833780820191505090505b5090508173ffffffffffffffffffffffffffffffffffffffff1663c661065760006040518263ffffffff1660e01b81526004016115f19190612810565b602060405180830381865afa15801561160e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611632919061318c565b8160008151811061164657611645612c27565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1663c661065760016040518263ffffffff1660e01b81526004016116ba9190612810565b602060405180830381865afa1580156116d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fb919061318c565b8160018151811061170f5761170e612c27565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008160018151811061175f5761175e612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146117a05760006117a3565b60025b826000815181106117b7576117b6612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16146117f85760006117fb565b60015b61180591906131c6565b60ff1690506000826001815181106118205761181f612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611861576000611864565b60025b8360008151811061187857611877612c27565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16146118b95760006118bc565b60015b6118c691906131c6565b60ff1690506118f684898973ffffffffffffffffffffffffffffffffffffffff166122539092919063ffffffff16565b8373ffffffffffffffffffffffffffffffffffffffff16635b41b90860018461191f9190612ae7565b60018461192c9190612ae7565b8b60006040518563ffffffff1660e01b815260040161194e9493929190613236565b600060405180830381600087803b15801561196857600080fd5b505af115801561197c573d6000803e3d6000fd5b5050505061199f8973ffffffffffffffffffffffffffffffffffffffff16612132565b15611ac9577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab173ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611a3991906126be565b602060405180830381865afa158015611a56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7a9190613290565b6040518263ffffffff1660e01b8152600401611a969190612810565b600060405180830381600087803b158015611ab057600080fd5b505af1158015611ac4573d6000803e3d6000fd5b505050505b505050505050505b505050565b6000611af78473ffffffffffffffffffffffffffffffffffffffff16612132565b15611b7e577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b6457600080fd5b505af1158015611b78573d6000803e3d6000fd5b50505050505b6000611b9f8573ffffffffffffffffffffffffffffffffffffffff16612132565b611ba95784611bcb565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab15b90506000611bee8573ffffffffffffffffffffffffffffffffffffffff16612132565b611bf85784611c1a565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab15b905060007f000000000000000000000000d394e9cc20f43d2651293756f8d320668e850f1b73ffffffffffffffffffffffffffffffffffffffff1663e6a4390584846040518363ffffffff1660e01b8152600401611c799291906132de565b602060405180830381865afa158015611c96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cba9190613345565b9050611ce781868573ffffffffffffffffffffffffffffffffffffffff166122c39092919063ffffffff16565b6000611d168484888573ffffffffffffffffffffffffffffffffffffffff16612311909392919063ffffffff16565b80925081965050508015611d85578173ffffffffffffffffffffffffffffffffffffffff1663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611d6c57600080fd5b505af1158015611d80573d6000803e3d6000fd5b505050505b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161015611e2e578173ffffffffffffffffffffffffffffffffffffffff1663022c0d9f600087306040518463ffffffff1660e01b8152600401611df7939291906133a9565b600060405180830381600087803b158015611e1157600080fd5b505af1158015611e25573d6000803e3d6000fd5b50505050611e9f565b8173ffffffffffffffffffffffffffffffffffffffff1663022c0d9f866000306040518463ffffffff1660e01b8152600401611e6c939291906133f3565b600060405180830381600087803b158015611e8657600080fd5b505af1158015611e9a573d6000803e3d6000fd5b505050505b611ebe8773ffffffffffffffffffffffffffffffffffffffff16612132565b15611fe8577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab173ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611f5891906126be565b602060405180830381865afa158015611f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f999190613290565b6040518263ffffffff1660e01b8152600401611fb59190612810565b600060405180830381600087803b158015611fcf57600080fd5b505af1158015611fe3573d6000803e3d6000fd5b505050505b505050509392505050565b600081111561211c5761200583612132565b156120ef5780471015612044576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168261138890604051806000019050600060405180830381858888f193505050503d80600081146120a9576040519150601f19603f3d011682016040523d82523d6000602084013e6120ae565b606091505b50509050806120e9576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5061211b565b61211a82828573ffffffffffffffffffffffffffffffffffffffff166122c39092919063ffffffff16565b5b5b505050565b60018081905550565b600033905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806121ad575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af191508115612213573d6000811461220957600160005114601f3d11169250612211565b6000883b1192505b505b508061224b576040517ff405907100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b61225c83612132565b15612293576040517f4ca17a9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122be82828573ffffffffffffffffffffffffffffffffffffffff166125109092919063ffffffff16565b505050565b6122d68363a9059cbb60e01b8484612594565b61230c576040517ffb7f507900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b600080600061233f878773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b9050600061236c888773ffffffffffffffffffffffffffffffffffffffff166111de90919063ffffffff16565b90506000808973ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156123bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e091906134bf565b50915091508773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16111561242457808280925081935050505b816dffffffffffffffffffffffffffff16846124409190612ae7565b9650816dffffffffffffffffffffffffffff1684108061246f5750806dffffffffffffffffffffffffffff1683105b945060006103e5886124819190613512565b9050600061249f85846dffffffffffffffffffffffffffff166125ea565b826124aa9190613512565b90506000826103e86124cc89886dffffffffffffffffffffffffffff166125ea565b6124d69190613512565b6124e09190612b87565b9050600081146124fb5780826124f69190613583565b6124fe565b60005b98505050505050505094509492505050565b6125238363095ea7b360e01b8484612594565b61258f5761253b8363095ea7b360e01b846000612594565b158061255757506125558363095ea7b360e01b8484612594565b155b1561258e576040517f19be9a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b505050565b60006040518481528360048201528260248201526020600060448360008a5af1915081156125e1573d600081146125d757600160005114601f3d111692506125df565b6000873b1192505b505b50949350505050565b60008183106125f957816125fb565b825b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061264861264361263e84612603565b612623565b612603565b9050919050565b600061265a8261262d565b9050919050565b600061266c8261264f565b9050919050565b61267c81612661565b82525050565b60006020820190506126976000830184612673565b92915050565b60006126a882612603565b9050919050565b6126b88161269d565b82525050565b60006020820190506126d360008301846126af565b92915050565b6000604051905090565b600080fd5b600080fd5b60006126f88261269d565b9050919050565b612708816126ed565b811461271357600080fd5b50565b600081359050612725816126ff565b92915050565b6000819050919050565b61273e8161272b565b811461274957600080fd5b50565b60008135905061275b81612735565b92915050565b6002811061276e57600080fd5b50565b60008135905061278081612761565b92915050565b600080600080600060a086880312156127a2576127a16126e3565b5b60006127b088828901612716565b95505060206127c188828901612716565b94505060406127d28882890161274c565b93505060606127e38882890161274c565b92505060806127f488828901612771565b9150509295509295909350565b61280a8161272b565b82525050565b60006020820190506128256000830184612801565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126128505761284f61282b565b5b8235905067ffffffffffffffff81111561286d5761286c612830565b5b60208301915083602082028301111561288957612888612835565b5b9250929050565b60008083601f8401126128a6576128a561282b565b5b8235905067ffffffffffffffff8111156128c3576128c2612830565b5b6020830191508360208202830111156128df576128de612835565b5b9250929050565b60008060008060008060808789031215612903576129026126e3565b5b600087013567ffffffffffffffff811115612921576129206126e8565b5b61292d89828a0161283a565b9650965050602061294089828a0161274c565b945050604061295189828a0161274c565b935050606087013567ffffffffffffffff811115612972576129716126e8565b5b61297e89828a01612890565b92509250509295509295509295565b6129968161269d565b81146129a157600080fd5b50565b6000813590506129b38161298d565b92915050565b6000602082840312156129cf576129ce6126e3565b5b60006129dd848285016129a4565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600082825260208201905092915050565b7f737761703a2072657475726e20616d6f756e74206973206c657373207468616e60008201527f206d696e52657475726e00000000000000000000000000000000000000000000602082015250565b6000612a82602a83612a15565b9150612a8d82612a26565b604082019050919050565b60006020820190508181036000830152612ab181612a75565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612af28261272b565b9150612afd8361272b565b9250828203905081811115612b1557612b14612ab8565b5b92915050565b7f737761703a20696e636f727265637420757365722062616c616e636500000000600082015250565b6000612b51601c83612a15565b9150612b5c82612b1b565b602082019050919050565b60006020820190508181036000830152612b8081612b44565b9050919050565b6000612b928261272b565b9150612b9d8361272b565b9250828201905080821115612bb557612bb4612ab8565b5b92915050565b7f737761704d756c74693a2077726f6e67206c656e677468000000000000000000600082015250565b6000612bf1601783612a15565b9150612bfc82612bbb565b602082019050919050565b60006020820190508181036000830152612c2081612be4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612c6c57612c6b6126e3565b5b6000612c7a84828501612716565b91505092915050565b600060208284031215612c9957612c986126e3565b5b6000612ca784828501612771565b91505092915050565b6000612cbb8261272b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612ced57612cec612ab8565b5b600182019050919050565b7f737761704d756c74693a2072657475726e20616d6f756e74206973206c65737360008201527f207468616e206d696e52657475726e0000000000000000000000000000000000602082015250565b6000612d54602f83612a15565b9150612d5f82612cf8565b604082019050919050565b60006020820190508181036000830152612d8381612d47565b9050919050565b7f737761704d756c74693a20696e636f727265637420757365722062616c616e6360008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000612de6602183612a15565b9150612df182612d8a565b604082019050919050565b60006020820190508181036000830152612e1581612dd9565b9050919050565b7f537461626c655377617020666163746f72792063616e6e6f74206265207a657260008201527f6f20616464726573730000000000000000000000000000000000000000000000602082015250565b6000612e78602983612a15565b9150612e8382612e1c565b604082019050919050565b60006020820190508181036000830152612ea781612e6b565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000612f0a602683612a15565b9150612f1582612eae565b604082019050919050565b60006020820190508181036000830152612f3981612efd565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612f76602083612a15565b9150612f8182612f40565b602082019050919050565b60006020820190508181036000830152612fa581612f69565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000612fe2601f83612a15565b9150612fed82612fac565b602082019050919050565b6000602082019050818103600083015261301181612fd5565b9050919050565b600060408201905061302d60008301856126af565b61303a60208301846126af565b9392505050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61308f82613046565b810181811067ffffffffffffffff821117156130ae576130ad613057565b5b80604052505050565b60006130c16126d9565b90506130cd8282613086565b919050565b6000815190506130e18161298d565b92915050565b6000608082840312156130fd576130fc613041565b5b61310760806130b7565b90506000613117848285016130d2565b600083015250602061312b848285016130d2565b602083015250604061313f848285016130d2565b6040830152506060613153848285016130d2565b60608301525092915050565b600060808284031215613175576131746126e3565b5b6000613183848285016130e7565b91505092915050565b6000602082840312156131a2576131a16126e3565b5b60006131b0848285016130d2565b91505092915050565b600060ff82169050919050565b60006131d1826131b9565b91506131dc836131b9565b9250828201905060ff8111156131f5576131f4612ab8565b5b92915050565b6000819050919050565b600061322061321b613216846131fb565b612623565b61272b565b9050919050565b61323081613205565b82525050565b600060808201905061324b6000830187612801565b6132586020830186612801565b6132656040830185612801565b6132726060830184613227565b95945050505050565b60008151905061328a81612735565b92915050565b6000602082840312156132a6576132a56126e3565b5b60006132b48482850161327b565b91505092915050565b60006132c88261264f565b9050919050565b6132d8816132bd565b82525050565b60006040820190506132f360008301856132cf565b61330060208301846132cf565b9392505050565b60006133128261269d565b9050919050565b61332281613307565b811461332d57600080fd5b50565b60008151905061333f81613319565b92915050565b60006020828403121561335b5761335a6126e3565b5b600061336984828501613330565b91505092915050565b600082825260208201905092915050565b50565b6000613393600083613372565b915061339e82613383565b600082019050919050565b60006080820190506133be6000830186613227565b6133cb6020830185612801565b6133d860408301846126af565b81810360608301526133e981613386565b9050949350505050565b60006080820190506134086000830186612801565b6134156020830185613227565b61342260408301846126af565b818103606083015261343381613386565b9050949350505050565b60006dffffffffffffffffffffffffffff82169050919050565b6134608161343d565b811461346b57600080fd5b50565b60008151905061347d81613457565b92915050565b600063ffffffff82169050919050565b61349c81613483565b81146134a757600080fd5b50565b6000815190506134b981613493565b92915050565b6000806000606084860312156134d8576134d76126e3565b5b60006134e68682870161346e565b93505060206134f78682870161346e565b9250506040613508868287016134aa565b9150509250925092565b600061351d8261272b565b91506135288361272b565b92508282026135368161272b565b9150828204841483151761354d5761354c612ab8565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061358e8261272b565b91506135998361272b565b9250826135a9576135a8613554565b5b82820490509291505056fea2646970667358221220c1a913a6f89b510d8ae1fd44b42845a832bcd9e244351caeb56727f440c1d4c964736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000d394e9cc20f43d2651293756f8d320668e850f1b0000000000000000000000003a52e9200ed7403d9d21664fdee540c2d02c099d
-----Decoded View---------------
Arg [0] : _WETHAddress (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
Arg [1] : _arbswapV2 (address): 0xd394E9CC20f43d2651293756F8D320668E850F1b
Arg [2] : _stableswapFactory (address): 0x3a52e9200Ed7403D9d21664fDee540C2d02c099d
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [1] : 000000000000000000000000d394e9cc20f43d2651293756f8d320668e850f1b
Arg [2] : 0000000000000000000000003a52e9200ed7403d9d21664fdee540c2d02c099d
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.