Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ParaswapAggregatorTraderV2
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2022 Dolomite.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.8.9;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IDolomiteMarginExchangeWrapper } from "../../protocol/interfaces/IDolomiteMarginExchangeWrapper.sol";
import { Require } from "../../protocol/lib/Require.sol";
import { OnlyDolomiteMargin } from "../helpers/OnlyDolomiteMargin.sol";
import { IParaswapAugustusRouter } from "../interfaces/traders/IParaswapAugustusRouter.sol";
import { ERC20Lib } from "../lib/ERC20Lib.sol";
/**
* @title ParaswapAggregatorTraderV2
* @author Dolomite
*
* Contract for performing an external trade with Paraswap using typesafe decoding of the function calls.
*/
contract ParaswapAggregatorTraderV2 is OnlyDolomiteMargin, IDolomiteMarginExchangeWrapper {
using SafeERC20 for IERC20;
// ============ Constants ============
bytes32 private constant _FILE = "ParaswapAggregatorTraderV2";
uint256 private constant _SCALE_AMOUNT = 1e36;
bytes4 public constant MEGA_SWAP_SELECTOR = IParaswapAugustusRouter.megaSwap.selector; // 0x46c67b6d
bytes4 public constant MULTI_SWAP_SELECTOR = IParaswapAugustusRouter.multiSwap.selector; // 0xa94e78ef
bytes4 public constant SIMPLE_SWAP_SELECTOR = IParaswapAugustusRouter.simpleSwap.selector; // 0x54e3f31b
// ============ Storage ============
IParaswapAugustusRouter immutable public PARASWAP_AUGUSTUS_ROUTER; // solhint-disable-line
address immutable public PARASWAP_TRANSFER_PROXY; // solhint-disable-line
// ============ Constructor ============
constructor(
address _paraswapAugustusRouter,
address _paraswapTransferProxy,
address _dolomiteMargin
)
OnlyDolomiteMargin(_dolomiteMargin)
{
PARASWAP_AUGUSTUS_ROUTER = IParaswapAugustusRouter(_paraswapAugustusRouter);
PARASWAP_TRANSFER_PROXY = _paraswapTransferProxy;
}
// ============ Public Functions ============
function exchange(
address /* _tradeOriginator */,
address _receiver,
address _outputToken,
address _inputToken,
uint256 _inputAmount,
bytes calldata _minAmountOutAndOrderData
)
external
onlyDolomiteMargin(msg.sender)
returns (uint256) {
ERC20Lib.resetAllowanceIfNeededAndApprove(IERC20(_inputToken), PARASWAP_TRANSFER_PROXY, _inputAmount);
(
uint256 minAmountOutWei,
bytes memory orderData
) = abi.decode(_minAmountOutAndOrderData, (uint256, bytes));
(
bytes4 paraswapFunctionSelector,
bytes memory paraswapCallData
) = abi.decode(orderData, (bytes4, bytes));
_overwriteInputAmountAndCall(_inputAmount, paraswapFunctionSelector, paraswapCallData);
uint256 outputAmount = IERC20(_outputToken).balanceOf(address(this));
Require.that(
outputAmount >= minAmountOutWei,
_FILE,
"Insufficient output amount",
outputAmount,
minAmountOutWei
);
IERC20(_outputToken).safeApprove(_receiver, outputAmount);
return outputAmount;
}
function getExchangeCost(
address,
address,
uint256,
bytes calldata
)
external
pure
returns (uint256) {
revert(string(abi.encodePacked(Require.stringifyTruncated(_FILE), ": getExchangeCost not implemented")));
}
// ============ Private Functions ============
function _overwriteInputAmountAndCall(
uint256 _inputAmount,
bytes4 _paraswapFunctionSelector,
bytes memory _paraswapCallData
) internal {
if (_paraswapFunctionSelector == MEGA_SWAP_SELECTOR) {
IParaswapAugustusRouter.MegaSwapSellData memory data = abi.decode(
_paraswapCallData,
(IParaswapAugustusRouter.MegaSwapSellData)
);
data.expectedAmount = _getScaledExpectedOutputAmount(data.fromAmount, _inputAmount, data.expectedAmount);
data.fromAmount = _inputAmount;
PARASWAP_AUGUSTUS_ROUTER.megaSwap(data);
} else if (_paraswapFunctionSelector == MULTI_SWAP_SELECTOR) {
IParaswapAugustusRouter.MultiSwapSellData memory data = abi.decode(
_paraswapCallData,
(IParaswapAugustusRouter.MultiSwapSellData)
);
data.expectedAmount = _getScaledExpectedOutputAmount(data.fromAmount, _inputAmount, data.expectedAmount);
data.fromAmount = _inputAmount;
PARASWAP_AUGUSTUS_ROUTER.multiSwap(data);
} else if (_paraswapFunctionSelector == SIMPLE_SWAP_SELECTOR) {
IParaswapAugustusRouter.SimpleSwapSellData memory data = abi.decode(
_paraswapCallData,
(IParaswapAugustusRouter.SimpleSwapSellData)
);
data.expectedAmount = _getScaledExpectedOutputAmount(data.fromAmount, _inputAmount, data.expectedAmount);
data.fromAmount = _inputAmount;
PARASWAP_AUGUSTUS_ROUTER.simpleSwap(data);
} else {
revert(string(abi.encodePacked(
Require.stringifyTruncated(_FILE),
": Invalid Paraswap function selector <",
Require.stringifyFunctionSelector(_paraswapFunctionSelector),
">"
)));
}
}
function _getScaledExpectedOutputAmount(
uint256 _originalInputAmount,
uint256 _actualInputAmount,
uint256 _expectedOutputAmount
) private pure returns (uint256) {
if (_originalInputAmount >= _actualInputAmount) {
return _expectedOutputAmount;
} else {
// The amount inputted to the Paraswap API was less than what we're actually trading. Scale up the expected
// amount out, so the user doesn't pay unnecessary positive slippage
uint256 percentageUp = _actualInputAmount * _SCALE_AMOUNT / _originalInputAmount;
return _expectedOutputAmount * percentageUp / _SCALE_AMOUNT;
}
}
}// 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 (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 (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { OnlyDolomiteMarginForUpgradeable } from "./OnlyDolomiteMarginForUpgradeable.sol";
import { IDolomiteMargin } from "../../protocol/interfaces/IDolomiteMargin.sol";
/**
* @title OnlyDolomiteMargin
* @author Dolomite
*
* @notice Inheritable contract that restricts the calling of certain functions to `DolomiteMargin`, the owner of
* `DolomiteMargin` or a `DolomiteMargin` global operator
*/
abstract contract OnlyDolomiteMargin is OnlyDolomiteMarginForUpgradeable {
// ============ Constants ============
bytes32 private constant _FILE = "OnlyDolomiteMargin";
// ============ Storage ============
IDolomiteMargin private immutable _DOLOMITE_MARGIN; // solhint-disable-line var-name-mixedcase
// ============ Constructor ============
constructor (address _dolomiteMargin)
{
_DOLOMITE_MARGIN = IDolomiteMargin(_dolomiteMargin);
}
// ============ Functions ============
function DOLOMITE_MARGIN() public override view returns (IDolomiteMargin) {
return _DOLOMITE_MARGIN;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { ProxyContractHelpers } from "./ProxyContractHelpers.sol";
import { IDolomiteMargin } from "../../protocol/interfaces/IDolomiteMargin.sol";
import { Require } from "../../protocol/lib/Require.sol";
import { IOnlyDolomiteMargin } from "../interfaces/IOnlyDolomiteMargin.sol";
/**
* @title OnlyDolomiteMarginForUpgradeable
* @author Dolomite
*
* @notice Inheritable contract that restricts the calling of certain functions to `DolomiteMargin`, the owner of
* `DolomiteMargin` or a `DolomiteMargin` global operator
*/
abstract contract OnlyDolomiteMarginForUpgradeable is IOnlyDolomiteMargin, ProxyContractHelpers {
// ============ Constants ============
bytes32 private constant _FILE = "OnlyDolomiteMargin";
bytes32 private constant _DOLOMITE_MARGIN_SLOT = bytes32(uint256(keccak256("eip1967.proxy.dolomiteMargin")) - 1);
// ============ Modifiers ============
modifier onlyDolomiteMargin(address _from) {
Require.that(
_from == address(DOLOMITE_MARGIN()),
_FILE,
"Only Dolomite can call function",
_from
);
_;
}
modifier onlyDolomiteMarginOwner(address _from) {
Require.that(
_from == DOLOMITE_MARGIN().owner(),
_FILE,
"Caller is not owner of Dolomite",
_from
);
_;
}
modifier onlyDolomiteMarginGlobalOperator(address _from) {
Require.that(
DOLOMITE_MARGIN().getIsGlobalOperator(_from),
_FILE,
"Caller is not a global operator",
_from
);
_;
}
// ============ Functions ============
function DOLOMITE_MARGIN() public virtual view returns (IDolomiteMargin) {
return IDolomiteMargin(_getAddress(_DOLOMITE_MARGIN_SLOT));
}
function _setDolomiteMarginViaSlot(address _dolomiteMargin) internal {
_setAddress(_DOLOMITE_MARGIN_SLOT, _dolomiteMargin);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
/**
* @title ProxyContractHelpers
* @author Dolomite
*
* @notice Helper functions for upgradeable proxy contracts to use
*/
abstract contract ProxyContractHelpers {
// ================ Internal Functions ==================
function _callImplementation(address _implementation) internal {
// solhint-disable-next-line no-inline-assembly
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
function _setAddress(bytes32 slot, address _value) internal {
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, _value)
}
}
function _setUint256(bytes32 slot, uint256 _value) internal {
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, _value)
}
}
function _getAddress(bytes32 slot) internal view returns (address value) {
// solhint-disable-next-line no-inline-assembly
assembly {
value := sload(slot)
}
}
function _getUint256(bytes32 slot) internal view returns (uint256 value) {
// solhint-disable-next-line no-inline-assembly
assembly {
value := sload(slot)
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { IDolomiteMargin } from "../../protocol/interfaces/IDolomiteMargin.sol";
/**
* @title IOnlyDolomiteMargin
* @author Dolomite
*
* @notice This interface is for contracts that need to add modifiers for only DolomiteMargin / Owner caller.
*/
interface IOnlyDolomiteMargin {
function DOLOMITE_MARGIN() external view returns (IDolomiteMargin);
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
/**
* @title IParaswapAugustusRouter
* @author Dolomite
*
* @notice Interface for executing trades via Paraswap
*/
interface IParaswapAugustusRouter {
// ============= Structs =============
struct Adapter {
address payable adapter;
uint256 percent;
uint256 networkFee;
Route[] route;
}
struct MegaSwapPath {
uint256 fromAmountPercent;
Path[] path;
}
struct MegaSwapSellData {
address fromToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address payable beneficiary;
MegaSwapPath[] path;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
struct MultiSwapSellData {
address fromToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address payable beneficiary;
Path[] path;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
struct Path {
address to;
uint256 totalNetworkFee; //Network fee is associated with 0xv3 trades
Adapter[] adapters;
}
struct Route {
uint256 index; //Adapter at which index needs to be used
address targetExchange;
uint percent;
bytes payload;
uint256 networkFee; //Network fee is associated with 0xv3 trades
}
struct SimpleSwapSellData {
address fromToken;
address toToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address[] callees;
bytes exchangeData;
uint256[] startIndexes;
uint256[] values;
address payable beneficiary;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}
// ============ Functions ============
function megaSwap(
MegaSwapSellData calldata _data
)
external
payable
returns (uint256 receivedAmount);
function multiSwap(
MultiSwapSellData calldata _data
)
external
payable
returns (uint256 receivedAmount);
function simpleSwap(
SimpleSwapSellData calldata data
)
external
payable
returns (uint256 receivedAmount);
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title ERC20Lib
* @author Dolomite
*
* @notice Library contract that adds additional functionality to ERC20 tokens.
*/
library ERC20Lib {
using SafeERC20 for IERC20;
// ============ Constants ============
bytes32 private constant _FILE = "ERC20Lib";
// ============ Functions ============
function resetAllowanceIfNeededAndApprove(
IERC20 _token,
address _spender,
uint256 _value
) internal {
if (_token.allowance(address(this), _spender) > 0) {
// If the allowance is already set, set it to 0 first
_token.safeApprove(_spender, 0);
}
_token.safeApprove(_spender, _value);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
/**
* @title IDolomiteInterestSetter
* @author Dolomite
*
* @notice This interface defines the functions that for an interest setter that can be used to determine the interest
* rate of a market.
*/
interface IDolomiteInterestSetter {
// ============ Enum ============
enum InterestSetterType {
None,
Linear,
DoubleExponential,
Other
}
// ============ Structs ============
struct InterestRate {
uint256 value;
}
// ============ Functions ============
/**
* Get the interest rate of a token given some borrowed and supplied amounts
*
* @param token The address of the ERC20 token for the market
* @param borrowWei The total borrowed token amount for the market
* @param supplyWei The total supplied token amount for the market
* @return The interest rate per second
*/
function getInterestRate(
address token,
uint256 borrowWei,
uint256 supplyWei
)
external
view
returns (InterestRate memory);
function interestSetterType() external pure returns (InterestSetterType);
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { IDolomiteInterestSetter } from "./IDolomiteInterestSetter.sol";
import { IDolomiteMarginAdmin } from "./IDolomiteMarginAdmin.sol";
import { IDolomitePriceOracle } from "./IDolomitePriceOracle.sol";
/**
* @title IDolomiteMargin
* @author Dolomite
*
* @notice The interface for interacting with the main entry-point to DolomiteMargin
*/
interface IDolomiteMargin is IDolomiteMarginAdmin {
// ==================================================
// ================= Write Functions ================
// ==================================================
/**
* The main entry-point to DolomiteMargin that allows users and contracts to manage accounts.
* Take one or more actions on one or more accounts. The msg.sender must be the owner or
* operator of all accounts except for those being liquidated, vaporized, or traded with.
* One call to operate() is considered a singular "operation". Account collateralization is
* ensured only after the completion of the entire operation.
*
* @param accounts A list of all accounts that will be used in this operation. Cannot contain
* duplicates. In each action, the relevant account will be referred-to by its
* index in the list.
* @param actions An ordered list of all actions that will be taken in this operation. The
* actions will be processed in order.
*/
function operate(
AccountInfo[] calldata accounts,
ActionArgs[] calldata actions
) external;
/**
* Approves/disapproves any number of operators. An operator is an external address that has the
* same permissions to manipulate an account as the owner of the account. Operators are simply
* addresses and therefore may either be externally-owned Ethereum accounts OR smart contracts.
*
* Operators are also able to act as AutoTrader contracts on behalf of the account owner if the
* operator is a smart contract and implements the IAutoTrader interface.
*
* @param args A list of OperatorArgs which have an address and a boolean. The boolean value
* denotes whether to approve (true) or revoke approval (false) for that address.
*/
function setOperators(
OperatorArg[] calldata args
) external;
// ==================================================
// ================= Read Functions ================
// ==================================================
// ============ Getters for Markets ============
/**
* Get the ERC20 token address for a market.
*
* @param token The token to query
* @return The token's marketId if the token is valid
*/
function getMarketIdByTokenAddress(
address token
) external view returns (uint256);
/**
* Get the ERC20 token address for a market.
*
* @param marketId The market to query
* @return The token address
*/
function getMarketTokenAddress(
uint256 marketId
) external view returns (address);
/**
* Return true if a particular market is in closing mode. Additional borrows cannot be taken
* from a market that is closing.
*
* @param marketId The market to query
* @return True if the market is closing
*/
function getMarketIsClosing(
uint256 marketId
)
external
view
returns (bool);
/**
* Get the price of the token for a market.
*
* @param marketId The market to query
* @return The price of each atomic unit of the token
*/
function getMarketPrice(
uint256 marketId
) external view returns (MonetaryPrice memory);
/**
* Get the total number of markets.
*
* @return The number of markets
*/
function getNumMarkets() external view returns (uint256);
/**
* Get the total principal amounts (borrowed and supplied) for a market.
*
* @param marketId The market to query
* @return The total principal amounts
*/
function getMarketTotalPar(
uint256 marketId
) external view returns (TotalPar memory);
/**
* Get the most recently cached interest index for a market.
*
* @param marketId The market to query
* @return The most recent index
*/
function getMarketCachedIndex(
uint256 marketId
) external view returns (InterestIndex memory);
/**
* Get the interest index for a market if it were to be updated right now.
*
* @param marketId The market to query
* @return The estimated current index
*/
function getMarketCurrentIndex(
uint256 marketId
) external view returns (InterestIndex memory);
/**
* Get the price oracle address for a market.
*
* @param marketId The market to query
* @return The price oracle address
*/
function getMarketPriceOracle(
uint256 marketId
) external view returns (IDolomitePriceOracle);
/**
* Get the interest-setter address for a market.
*
* @param marketId The market to query
* @return The interest-setter address
*/
function getMarketInterestSetter(
uint256 marketId
) external view returns (IDolomiteInterestSetter);
/**
* Get the margin premium for a market. A margin premium makes it so that any positions that
* include the market require a higher collateralization to avoid being liquidated.
*
* @param marketId The market to query
* @return The market's margin premium
*/
function getMarketMarginPremium(
uint256 marketId
) external view returns (Decimal memory);
/**
* Get the spread premium for a market. A spread premium makes it so that any liquidations
* that include the market have a higher spread than the global default.
*
* @param marketId The market to query
* @return The market's spread premium
*/
function getMarketSpreadPremium(
uint256 marketId
) external view returns (Decimal memory);
/**
* Return true if this market can be removed and its ID can be recycled and reused
*
* @param marketId The market to query
* @return True if the market is recyclable
*/
function getMarketIsRecyclable(
uint256 marketId
) external view returns (bool);
/**
* Gets the recyclable markets, up to `n` length. If `n` is greater than the length of the list, 0's are returned
* for the empty slots.
*
* @param n The number of markets to get, bounded by the linked list being smaller than `n`
* @return The list of recyclable markets, in the same order held by the linked list
*/
function getRecyclableMarkets(
uint256 n
) external view returns (uint[] memory);
/**
* Get the current borrower interest rate for a market.
*
* @param marketId The market to query
* @return The current interest rate
*/
function getMarketInterestRate(
uint256 marketId
) external view returns (IDolomiteInterestSetter.InterestRate memory);
/**
* Get basic information about a particular market.
*
* @param marketId The market to query
* @return A Market struct with the current state of the market
*/
function getMarket(
uint256 marketId
) external view returns (Market memory);
/**
* Get comprehensive information about a particular market.
*
* @param marketId The market to query
* @return A tuple containing the values:
* - A Market struct with the current state of the market
* - The current estimated interest index
* - The current token price
* - The current market interest rate
*/
function getMarketWithInfo(
uint256 marketId
)
external
view
returns (
Market memory,
InterestIndex memory,
MonetaryPrice memory,
IDolomiteInterestSetter.InterestRate memory
);
/**
* Get the number of excess tokens for a market. The number of excess tokens is calculated by taking the current
* number of tokens held in DolomiteMargin, adding the number of tokens owed to DolomiteMargin by borrowers, and
* subtracting the number of tokens owed to suppliers by DolomiteMargin.
*
* @param marketId The market to query
* @return The number of excess tokens
*/
function getNumExcessTokens(
uint256 marketId
) external view returns (Wei memory);
// ============ Getters for Accounts ============
/**
* Get the principal value for a particular account and market.
*
* @param account The account to query
* @param marketId The market to query
* @return The principal value
*/
function getAccountPar(
AccountInfo calldata account,
uint256 marketId
) external view returns (Par memory);
/**
* Get the principal value for a particular account and market, with no check the market is valid. Meaning, markets
* that don't exist return 0.
*
* @param account The account to query
* @param marketId The market to query
* @return The principal value
*/
function getAccountParNoMarketCheck(
AccountInfo calldata account,
uint256 marketId
) external view returns (Par memory);
/**
* Get the token balance for a particular account and market.
*
* @param account The account to query
* @param marketId The market to query
* @return The token amount
*/
function getAccountWei(
AccountInfo calldata account,
uint256 marketId
) external view returns (Wei memory);
/**
* Get the status of an account (Normal, Liquidating, or Vaporizing).
*
* @param account The account to query
* @return The account's status
*/
function getAccountStatus(
AccountInfo calldata account
) external view returns (AccountStatus);
/**
* Get a list of markets that have a non-zero balance for an account
*
* @param account The account to query
* @return The non-sorted marketIds with non-zero balance for the account.
*/
function getAccountMarketsWithBalances(
AccountInfo calldata account
) external view returns (uint256[] memory);
/**
* Get the number of markets that have a non-zero balance for an account
*
* @param account The account to query
* @return The non-sorted marketIds with non-zero balance for the account.
*/
function getAccountNumberOfMarketsWithBalances(
AccountInfo calldata account
) external view returns (uint256);
/**
* Get the marketId for an account's market with a non-zero balance at the given index
*
* @param account The account to query
* @return The non-sorted marketIds with non-zero balance for the account.
*/
function getAccountMarketWithBalanceAtIndex(
AccountInfo calldata account,
uint256 index
) external view returns (uint256);
/**
* Get the number of markets with which an account has a negative balance.
*
* @param account The account to query
* @return The non-sorted marketIds with non-zero balance for the account.
*/
function getAccountNumberOfMarketsWithDebt(
AccountInfo calldata account
) external view returns (uint256);
/**
* Get the total supplied and total borrowed value of an account.
*
* @param account The account to query
* @return The following values:
* - The supplied value of the account
* - The borrowed value of the account
*/
function getAccountValues(
AccountInfo calldata account
) external view returns (MonetaryValue memory, MonetaryValue memory);
/**
* Get the total supplied and total borrowed values of an account adjusted by the marginPremium
* of each market. Supplied values are divided by (1 + marginPremium) for each market and
* borrowed values are multiplied by (1 + marginPremium) for each market. Comparing these
* adjusted values gives the margin-ratio of the account which will be compared to the global
* margin-ratio when determining if the account can be liquidated.
*
* @param account The account to query
* @return The following values:
* - The supplied value of the account (adjusted for marginPremium)
* - The borrowed value of the account (adjusted for marginPremium)
*/
function getAdjustedAccountValues(
AccountInfo calldata account
) external view returns (MonetaryValue memory, MonetaryValue memory);
/**
* Get an account's summary for each market.
*
* @param account The account to query
* @return The following values:
* - The market IDs for each market
* - The ERC20 token address for each market
* - The account's principal value for each market
* - The account's (supplied or borrowed) number of tokens for each market
*/
function getAccountBalances(
AccountInfo calldata account
) external view returns (uint[] memory, address[] memory, Par[] memory, Wei[] memory);
// ============ Getters for Account Permissions ============
/**
* Return true if a particular address is approved as an operator for an owner's accounts.
* Approved operators can act on the accounts of the owner as if it were the operator's own.
*
* @param owner The owner of the accounts
* @param operator The possible operator
* @return True if operator is approved for owner's accounts
*/
function getIsLocalOperator(
address owner,
address operator
) external view returns (bool);
/**
* Return true if a particular address is approved as a global operator. Such an address can
* act on any account as if it were the operator's own.
*
* @param operator The address to query
* @return True if operator is a global operator
*/
function getIsGlobalOperator(
address operator
) external view returns (bool);
/**
* Checks if the autoTrader can only be called invoked by a global operator
*
* @param autoTrader The trader that should be checked for special call privileges.
*/
function getIsAutoTraderSpecial(address autoTrader) external view returns (bool);
/**
* @return The address that owns the DolomiteMargin protocol
*/
function owner() external view returns (address);
// ============ Getters for Risk Params ============
/**
* Get the global minimum margin-ratio that every position must maintain to prevent being
* liquidated.
*
* @return The global margin-ratio
*/
function getMarginRatio() external view returns (Decimal memory);
/**
* Get the global liquidation spread. This is the spread between oracle prices that incentivizes
* the liquidation of risky positions.
*
* @return The global liquidation spread
*/
function getLiquidationSpread() external view returns (Decimal memory);
/**
* Get the adjusted liquidation spread for some market pair. This is equal to the global
* liquidation spread multiplied by (1 + spreadPremium) for each of the two markets.
*
* @param heldMarketId The market for which the account has collateral
* @param owedMarketId The market for which the account has borrowed tokens
* @return The adjusted liquidation spread
*/
function getLiquidationSpreadForPair(
uint256 heldMarketId,
uint256 owedMarketId
) external view returns (Decimal memory);
/**
* Get the global earnings-rate variable that determines what percentage of the interest paid
* by borrowers gets passed-on to suppliers.
*
* @return The global earnings rate
*/
function getEarningsRate() external view returns (Decimal memory);
/**
* Get the global minimum-borrow value which is the minimum value of any new borrow on DolomiteMargin.
*
* @return The global minimum borrow value
*/
function getMinBorrowedValue() external view returns (MonetaryValue memory);
/**
* Get all risk parameters in a single struct.
*
* @return All global risk parameters
*/
function getRiskParams() external view returns (RiskParams memory);
/**
* Get all risk parameter limits in a single struct. These are the maximum limits at which the
* risk parameters can be set by the admin of DolomiteMargin.
*
* @return All global risk parameter limits
*/
function getRiskLimits() external view returns (RiskLimits memory);
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { IDolomiteInterestSetter } from "./IDolomiteInterestSetter.sol";
import { IDolomitePriceOracle } from "./IDolomitePriceOracle.sol";
import { IDolomiteStructs } from "./IDolomiteStructs.sol";
/**
* @title IDolomiteMarginAdmin
* @author Dolomite
*
* @notice This interface defines the functions that can be called by the owner of DolomiteMargin.
*/
interface IDolomiteMarginAdmin is IDolomiteStructs {
// ============ Token Functions ============
/**
* Withdraw an ERC20 token for which there is an associated market. Only excess tokens can be withdrawn. The number
* of excess tokens is calculated by taking the current number of tokens held in DolomiteMargin, adding the number
* of tokens owed to DolomiteMargin by borrowers, and subtracting the number of tokens owed to suppliers by
* DolomiteMargin.
*/
function ownerWithdrawExcessTokens(
uint256 marketId,
address recipient
)
external
returns (uint256);
/**
* Withdraw an ERC20 token for which there is no associated market.
*/
function ownerWithdrawUnsupportedTokens(
address token,
address recipient
)
external
returns (uint256);
// ============ Market Functions ============
/**
* Sets the number of non-zero balances an account may have within the same `accountIndex`. This ensures a user
* cannot DOS the system by filling their account with non-zero balances (which linearly increases gas costs when
* checking collateralization) and disallowing themselves to close the position, because the number of gas units
* needed to process their transaction exceed the block's gas limit. In turn, this would prevent the user from also
* being liquidated, causing the all of the capital to be "stuck" in the position.
*
* Lowering this number does not "freeze" user accounts that have more than the new limit of balances, because this
* variable is enforced by checking the users number of non-zero balances against the max or if it sizes down before
* each transaction finishes.
*/
function ownerSetAccountMaxNumberOfMarketsWithBalances(
uint256 accountMaxNumberOfMarketsWithBalances
)
external;
/**
* Add a new market to DolomiteMargin. Must be for a previously-unsupported ERC20 token.
*/
function ownerAddMarket(
address token,
IDolomitePriceOracle priceOracle,
IDolomiteInterestSetter interestSetter,
Decimal calldata marginPremium,
Decimal calldata spreadPremium,
uint256 maxWei,
bool isClosing,
bool isRecyclable
)
external;
/**
* Removes a market from DolomiteMargin, sends any remaining tokens in this contract to `salvager` and invokes the
* recyclable callback
*/
function ownerRemoveMarkets(
uint[] calldata marketIds,
address salvager
)
external;
/**
* Set (or unset) the status of a market to "closing". The borrowedValue of a market cannot increase while its
* status is "closing".
*/
function ownerSetIsClosing(
uint256 marketId,
bool isClosing
)
external;
/**
* Set the price oracle for a market.
*/
function ownerSetPriceOracle(
uint256 marketId,
IDolomitePriceOracle priceOracle
)
external;
/**
* Set the interest-setter for a market.
*/
function ownerSetInterestSetter(
uint256 marketId,
IDolomiteInterestSetter interestSetter
)
external;
/**
* Set a premium on the minimum margin-ratio for a market. This makes it so that any positions that include this
* market require a higher collateralization to avoid being liquidated.
*/
function ownerSetMarginPremium(
uint256 marketId,
Decimal calldata marginPremium
)
external;
function ownerSetMaxWei(
uint256 marketId,
uint256 maxWei
)
external;
/**
* Set a premium on the liquidation spread for a market. This makes it so that any liquidations that include this
* market have a higher spread than the global default.
*/
function ownerSetSpreadPremium(
uint256 marketId,
Decimal calldata spreadPremium
)
external;
// ============ Risk Functions ============
/**
* Set the global minimum margin-ratio that every position must maintain to prevent being liquidated.
*/
function ownerSetMarginRatio(
Decimal calldata ratio
)
external;
/**
* Set the global liquidation spread. This is the spread between oracle prices that incentivizes the liquidation of
* risky positions.
*/
function ownerSetLiquidationSpread(
Decimal calldata spread
)
external;
/**
* Set the global earnings-rate variable that determines what percentage of the interest paid by borrowers gets
* passed-on to suppliers.
*/
function ownerSetEarningsRate(
Decimal calldata earningsRate
)
external;
/**
* Set the global minimum-borrow value which is the minimum value of any new borrow on DolomiteMargin.
*/
function ownerSetMinBorrowedValue(
MonetaryValue calldata minBorrowedValue
)
external;
// ============ Global Operator Functions ============
/**
* Approve (or disapprove) an address that is permissioned to be an operator for all accounts in DolomiteMargin.
* Intended only to approve smart-contracts.
*/
function ownerSetGlobalOperator(
address operator,
bool approved
)
external;
/**
* Approve (or disapprove) an auto trader that can only be called by a global operator. IE for expirations
*/
function ownerSetAutoTraderSpecial(
address autoTrader,
bool special
)
external;
}// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2019 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.8.9;
/**
* @title IDolomiteMarginExchangeWrapper
* @author dYdX
*
* @notice Interface that Exchange Wrappers for DolomiteMargin must implement in order to trade ERC20 tokens with
* external protocols.
*/
interface IDolomiteMarginExchangeWrapper {
// ============ Public Functions ============
/**
* Exchange some amount of inputToken for outputToken.
*
* @param _tradeOriginator Address of the initiator of the trade (however, this value cannot always be trusted as
* it is set at the discretion of the msg.sender)
* @param _receiver Address to set allowance on once the trade has completed
* @param _outputToken The token to receive (target asset; IE path[path.length - 1])
* @param _inputToken The token to pay (originator asset; IE path[0])
* @param _inputAmount Amount of `inputToken` being paid to this wrapper
* @param _orderData Arbitrary bytes data for any information to pass to the exchange
* @return The amount of outputToken to be received by DolomiteMargin
*/
function exchange(
address _tradeOriginator,
address _receiver,
address _outputToken,
address _inputToken,
uint256 _inputAmount,
bytes calldata _orderData
)
external
returns (uint256);
/**
* Get amount of `inputToken` required to buy a certain amount of `outputToken` for a given trade.
* Should match the `inputToken` amount used in exchangeForAmount. If the order cannot provide
* exactly `_desiredOutputToken`, then it must return the price to buy the minimum amount greater
* than `_desiredOutputToken`
*
* @param _inputToken The token to pay to this contract (originator asset; IE path[0])
* @param _outputToken The token to receive by DolomiteMargin (target asset; IE path[path.length - 1])
* @param _desiredInputAmount Amount of `_inputToken` requested
* @param _orderData Arbitrary bytes data for any information to pass to the exchange
* @return Amount of `_inputToken` the needed to complete the exchange
*/
function getExchangeCost(
address _inputToken,
address _outputToken,
uint256 _desiredInputAmount,
bytes calldata _orderData
)
external
view
returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { IDolomiteStructs } from "./IDolomiteStructs.sol";
/**
* @title IDolomitePriceOracle
* @author Dolomite
*
* @notice Interface that Price Oracles for DolomiteMargin must implement in order to report prices.
*/
interface IDolomitePriceOracle {
// ============ Public Functions ============
/**
* Get the price of a token
*
* @param token The ERC20 token address of the market
* @return The USD price of a base unit of the token, then multiplied by 10^(36 - decimals).
* So a USD-stable coin with 6 decimal places would return `price * 10^30`.
* This is the price of the base unit rather than the price of a "human-readable"
* token amount. Every ERC20 may have a different number of decimals.
*/
function getPrice(
address token
)
external
view
returns (IDolomiteStructs.MonetaryPrice memory);
}// SPDX-License-Identifier: GPL-3.0-or-later
/*
Copyright 2023 Dolomite
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
pragma solidity ^0.8.9;
import { IDolomiteInterestSetter } from "./IDolomiteInterestSetter.sol";
import { IDolomitePriceOracle } from "./IDolomitePriceOracle.sol";
/**
* @title IDolomiteStructs
* @author Dolomite
*
* @notice This interface defines the structs used by DolomiteMargin
*/
interface IDolomiteStructs {
// ========================= Enums =========================
enum ActionType {
Deposit, // supply tokens
Withdraw, // borrow tokens
Transfer, // transfer balance between accounts
Buy, // buy an amount of some token (externally)
Sell, // sell an amount of some token (externally)
Trade, // trade tokens against another account
Liquidate, // liquidate an undercollateralized or expiring account
Vaporize, // use excess tokens to zero-out a completely negative account
Call // send arbitrary data to an address
}
enum AssetDenomination {
Wei, // the amount is denominated in wei
Par // the amount is denominated in par
}
enum AssetReference {
Delta, // the amount is given as a delta from the current value
Target // the amount is given as an exact number to end up at
}
// ========================= Structs =========================
struct AccountInfo {
address owner; // The address that owns the account
uint256 number; // A nonce that allows a single address to control many accounts
}
/**
* Most-recently-cached account status.
*
* Normal: Can only be liquidated if the account values are violating the global margin-ratio.
* Liquid: Can be liquidated no matter the account values.
* Can be vaporized if there are no more positive account values.
* Vapor: Has only negative (or zeroed) account values. Can be vaporized.
*
*/
enum AccountStatus {
Normal,
Liquid,
Vapor
}
/*
* Arguments that are passed to DolomiteMargin in an ordered list as part of a single operation.
* Each ActionArgs has an actionType which specifies which action struct that this data will be
* parsed into before being processed.
*/
struct ActionArgs {
ActionType actionType;
uint256 accountId;
AssetAmount amount;
uint256 primaryMarketId;
uint256 secondaryMarketId;
address otherAddress;
uint256 otherAccountId;
bytes data;
}
struct AssetAmount {
bool sign; // true if positive
AssetDenomination denomination;
AssetReference ref;
uint256 value;
}
struct Decimal {
uint256 value;
}
struct InterestIndex {
uint96 borrow;
uint96 supply;
uint32 lastUpdate;
}
struct Market {
address token;
// Whether additional borrows are allowed for this market
bool isClosing;
// Whether this market can be removed and its ID can be recycled and reused
bool isRecyclable;
// Total aggregated supply and borrow amount of the entire market
TotalPar totalPar;
// Interest index of the market
InterestIndex index;
// Contract address of the price oracle for this market
IDolomitePriceOracle priceOracle;
// Contract address of the interest setter for this market
IDolomiteInterestSetter interestSetter;
// Multiplier on the marginRatio for this market, IE 5% (0.05 * 1e18). This number increases the market's
// required collateralization by: reducing the user's supplied value (in terms of dollars) for this market and
// increasing its borrowed value. This is done through the following operation:
// `suppliedWei = suppliedWei + (assetValueForThisMarket / (1 + marginPremium))`
// This number increases the user's borrowed wei by multiplying it by:
// `borrowedWei = borrowedWei + (assetValueForThisMarket * (1 + marginPremium))`
Decimal marginPremium;
// Multiplier on the liquidationSpread for this market, IE 20% (0.2 * 1e18). This number increases the
// `liquidationSpread` using the following formula:
// `liquidationSpread = liquidationSpread * (1 + spreadPremium)`
// NOTE: This formula is applied up to two times - one for each market whose spreadPremium is greater than 0
// (when performing a liquidation between two markets)
Decimal spreadPremium;
// The maximum amount that can be held by the external. This allows the external to cap any additional risk
// that is inferred by allowing borrowing against low-cap or assets with increased volatility. Setting this
// value to 0 is analogous to having no limit. This value can never be below 0.
Wei maxWei;
}
/*
* The price of a base-unit of an asset. Has `36 - token.decimals` decimals
*/
struct MonetaryPrice {
uint256 value;
}
struct MonetaryValue {
uint256 value;
}
struct OperatorArg {
address operator;
bool trusted;
}
struct Par {
bool sign;
uint256 value;
}
struct RiskLimits {
// The highest that the ratio can be for liquidating under-water accounts
uint64 marginRatioMax;
// The highest that the liquidation rewards can be when a liquidator liquidates an account
uint64 liquidationSpreadMax;
// The highest that the supply APR can be for a market, as a proportion of the borrow rate. Meaning, a rate of
// 100% (1e18) would give suppliers all of the interest that borrowers are paying. A rate of 90% would give
// suppliers 90% of the interest that borrowers pay.
uint64 earningsRateMax;
// The highest min margin ratio premium that can be applied to a particular market. Meaning, a value of 100%
// (1e18) would require borrowers to maintain an extra 100% collateral to maintain a healthy margin ratio. This
// value works by increasing the debt owed and decreasing the supply held for the particular market by this
// amount, plus 1e18 (since a value of 10% needs to be applied as `decimal.plusOne`)
uint64 marginPremiumMax;
// The highest liquidation reward that can be applied to a particular market. This percentage is applied
// in addition to the liquidation spread in `RiskParams`. Meaning a value of 1e18 is 100%. It is calculated as:
// `liquidationSpread * Decimal.onePlus(spreadPremium)`
uint64 spreadPremiumMax;
uint128 minBorrowedValueMax;
}
struct RiskParams {
// Required ratio of over-collateralization
Decimal marginRatio;
// Percentage penalty incurred by liquidated accounts
Decimal liquidationSpread;
// Percentage of the borrower's interest fee that gets passed to the suppliers
Decimal earningsRate;
// The minimum absolute borrow value of an account
// There must be sufficient incentivize to liquidate undercollateralized accounts
MonetaryValue minBorrowedValue;
// The maximum number of markets a user can have a non-zero balance for a given account.
uint256 accountMaxNumberOfMarketsWithBalances;
}
struct TotalPar {
uint128 borrow;
uint128 supply;
}
struct Wei {
bool sign;
uint256 value;
}
}// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2019 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.8.9;
/**
* @title Require
* @author dYdX
*
* @notice Stringifies parameters to pretty-print revert messages. Costs more gas than regular require()
*/
library Require {
// ============ Constants ============
uint256 private constant _ASCII_ZERO = 48; // '0'
uint256 private constant _ASCII_RELATIVE_ZERO = 87; // 'a' - 10
uint256 private constant _ASCII_LOWER_EX = 120; // 'x'
bytes2 private constant _COLON = 0x3a20; // ': '
bytes2 private constant _COMMA = 0x2c20; // ', '
bytes2 private constant _LPAREN = 0x203c; // ' <'
bytes1 private constant _RPAREN = 0x3e; // '>'
uint256 private constant _FOUR_BIT_MASK = 0xf;
// ============ Library Functions ============
function that(
bool must,
bytes32 file,
bytes32 reason
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason)
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
uint256 payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
uint256 payloadA,
uint256 payloadB
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_COMMA,
_stringify(payloadB),
_RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA,
uint256 payloadB
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_COMMA,
_stringify(payloadB),
_RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA,
uint256 payloadB,
uint256 payloadC
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_COMMA,
_stringify(payloadB),
_COMMA,
_stringify(payloadC),
_RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
bytes32 payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
bytes32 payloadA,
uint256 payloadB,
uint256 payloadC
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
_COLON,
stringifyTruncated(reason),
_LPAREN,
_stringify(payloadA),
_COMMA,
_stringify(payloadB),
_COMMA,
_stringify(payloadC),
_RPAREN
)
)
);
}
}
// ============ Private Functions ============
function stringifyTruncated(
bytes32 input
)
internal
pure
returns (bytes memory)
{
// put the input bytes into the result
bytes memory result = abi.encodePacked(input);
// determine the length of the input by finding the location of the last non-zero byte
for (uint256 i = 32; i > 0; ) {
// reverse-for-loops with unsigned integer
i--;
// find the last non-zero byte in order to determine the length
if (result[i] != 0) {
uint256 length = i + 1;
/* solhint-disable-next-line no-inline-assembly */
assembly {
mstore(result, length) // r.length = length;
}
return result;
}
}
// all bytes are zero
return new bytes(0);
}
function stringifyFunctionSelector(
bytes4 input
)
internal
pure
returns (bytes memory)
{
uint256 z = uint256(bytes32(input) >> 224);
// bytes4 are "0x" followed by 4 bytes of data which take up 2 characters each
bytes memory result = new bytes(10);
// populate the result with "0x"
result[0] = bytes1(uint8(_ASCII_ZERO));
result[1] = bytes1(uint8(_ASCII_LOWER_EX));
// for each byte (starting from the lowest byte), populate the result with two characters
for (uint256 i = 0; i < 4; i++) {
// each byte takes two characters
uint256 shift = i * 2;
// populate the least-significant character
result[9 - shift] = _char(z & _FOUR_BIT_MASK);
z = z >> 4;
// populate the most-significant character
result[8 - shift] = _char(z & _FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function _stringify(
uint256 input
)
private
pure
returns (bytes memory)
{
if (input == 0) {
return "0";
}
// get the final string length
uint256 j = input;
uint256 length;
while (j != 0) {
length++;
j /= 10;
}
// allocate the string
bytes memory bstr = new bytes(length);
// populate the string starting with the least-significant character
j = input;
for (uint256 i = length; i > 0; ) {
// reverse-for-loops with unsigned integer
i--;
// take last decimal digit
bstr[i] = bytes1(uint8(_ASCII_ZERO + (j % 10)));
// remove the last decimal digit
j /= 10;
}
return bstr;
}
function _stringify(
address input
)
private
pure
returns (bytes memory)
{
uint256 z = uint256(uint160(input));
// addresses are "0x" followed by 20 bytes of data which take up 2 characters each
bytes memory result = new bytes(42);
// populate the result with "0x"
result[0] = bytes1(uint8(_ASCII_ZERO));
result[1] = bytes1(uint8(_ASCII_LOWER_EX));
// for each byte (starting from the lowest byte), populate the result with two characters
for (uint256 i = 0; i < 20; i++) {
// each byte takes two characters
uint256 shift = i * 2;
// populate the least-significant character
result[41 - shift] = _char(z & _FOUR_BIT_MASK);
z = z >> 4;
// populate the most-significant character
result[40 - shift] = _char(z & _FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function _stringify(
bytes32 input
)
private
pure
returns (bytes memory)
{
uint256 z = uint256(input);
// bytes32 are "0x" followed by 32 bytes of data which take up 2 characters each
bytes memory result = new bytes(66);
// populate the result with "0x"
result[0] = bytes1(uint8(_ASCII_ZERO));
result[1] = bytes1(uint8(_ASCII_LOWER_EX));
// for each byte (starting from the lowest byte), populate the result with two characters
for (uint256 i = 0; i < 32; i++) {
// each byte takes two characters
uint256 shift = i * 2;
// populate the least-significant character
result[65 - shift] = _char(z & _FOUR_BIT_MASK);
z = z >> 4;
// populate the most-significant character
result[64 - shift] = _char(z & _FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function _char(
uint256 input
)
private
pure
returns (bytes1)
{
// return ASCII digit (0-9)
if (input < 10) {
return bytes1(uint8(input + _ASCII_ZERO));
}
// return ASCII letter (a-f)
return bytes1(uint8(input + _ASCII_RELATIVE_ZERO));
}
}{
"optimizer": {
"enabled": true,
"runs": 10000,
"details": {
"yul": false
}
},
"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":"_paraswapAugustusRouter","type":"address"},{"internalType":"address","name":"_paraswapTransferProxy","type":"address"},{"internalType":"address","name":"_dolomiteMargin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DOLOMITE_MARGIN","outputs":[{"internalType":"contract IDolomiteMargin","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MEGA_SWAP_SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MULTI_SWAP_SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PARASWAP_AUGUSTUS_ROUTER","outputs":[{"internalType":"contract IParaswapAugustusRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PARASWAP_TRANSFER_PROXY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIMPLE_SWAP_SELECTOR","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_outputToken","type":"address"},{"internalType":"address","name":"_inputToken","type":"address"},{"internalType":"uint256","name":"_inputAmount","type":"uint256"},{"internalType":"bytes","name":"_minAmountOutAndOrderData","type":"bytes"}],"name":"exchange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"getExchangeCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
60e06040523480156200001157600080fd5b50604051620030dd380380620030dd83398101604081905262000034916200008c565b6001600160a01b0390811660805291821660a0521660c052620000e4565b60006001600160a01b0382165b92915050565b620000708162000052565b81146200007c57600080fd5b50565b80516200005f8162000065565b600080600060608486031215620000a657620000a6600080fd5b6000620000b486866200007f565b9350506020620000c7868287016200007f565b9250506040620000da868287016200007f565b9150509250925092565b60805160a05160c051612fa862000135600039600081816101a601526102e601526000818160fe01528181610771015281816108bd01526109af01526000818160cc01526102760152612fa86000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806345cd3cea1161005b57806345cd3cea146101405780636e3b7a79146101675780637d98ebac1461018e57806384796caf146101a157600080fd5b80630d94ea2a1461008d57806315c14a4a146100ca57806317f5e788146100f95780633a8fdd7d14610120575b600080fd5b6100b47f46c67b6d0000000000000000000000000000000000000000000000000000000081565b6040516100c191906113de565b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b6040516100c1919061142f565b6100ec7f000000000000000000000000000000000000000000000000000000000000000081565b61013361012e3660046114c2565b6101d5565b6040516100c1919061154c565b6100b47fa94e78ef0000000000000000000000000000000000000000000000000000000081565b6100b47f54e3f31b0000000000000000000000000000000000000000000000000000000081565b61013361019c36600461155a565b610259565b6101c87f000000000000000000000000000000000000000000000000000000000000000081565b6040516100c1919061160e565b60006102007f506172617377617041676772656761746f72547261646572563200000000000061046d565b604051602001610210919061166a565b60408051601f19818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610250916004016116fc565b60405180910390fd5b6000336102e073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682147f4f6e6c79446f6c6f6d6974654d617267696e00000000000000000000000000007f4f6e6c7920446f6c6f6d6974652063616e2063616c6c2066756e6374696f6e0084610520565b61030b867f0000000000000000000000000000000000000000000000000000000000000000876105be565b60008061031a85870187611819565b915091506000808280602001905181019061033591906118fc565b915091506103448983836106b3565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8d16906370a082319061039990309060040161160e565b60206040518083038186803b1580156103b157600080fd5b505afa1580156103c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e99190611955565b905061043b858210157f506172617377617041676772656761746f7254726164657256320000000000007f496e73756666696369656e74206f757470757420616d6f756e740000000000008489610a27565b61045c73ffffffffffffffffffffffffffffffffffffffff8d168e83610aeb565b9d9c50505050505050505050505050565b60606000826040516020016104829190611976565b60408051601f19818403018152919052905060205b801561050557806104a7816119ba565b9150508181815181106104bc576104bc6119ef565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016156105005760006104f5826001611a1e565b835250909392505050565b610497565b5060408051600080825260208201909252905b509392505050565b836105b85761052e8361046d565b7f3a200000000000000000000000000000000000000000000000000000000000006105588461046d565b7f203c00000000000000000000000000000000000000000000000000000000000061058285610c52565b6040516102109594939291907f3e0000000000000000000000000000000000000000000000000000000000000090602001611a86565b50505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff85169063dd62ed3e906106159030908790600401611ae4565b60206040518083038186803b15801561062d57600080fd5b505afa158015610641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106659190611955565b111561068d5761068d73ffffffffffffffffffffffffffffffffffffffff8416836000610aeb565b6106ae73ffffffffffffffffffffffffffffffffffffffff84168383610aeb565b505050565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f46c67b6d0000000000000000000000000000000000000000000000000000000014156107ff5760008180602001905181019061071391906120fb565b90506107288160200151858360600151610e05565b6060820152602081018490526040517f46c67b6d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906346c67b6d906107a6908490600401612513565b602060405180830381600087803b1580156107c057600080fd5b505af11580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190611955565b5050505050565b7fffffffff0000000000000000000000000000000000000000000000000000000082167fa94e78ef0000000000000000000000000000000000000000000000000000000014156108f25760008180602001905181019061085f91906125cf565b90506108748160200151858360600151610e05565b6060820152602081018490526040517fa94e78ef00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a94e78ef906107a6908490600401612683565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f54e3f31b0000000000000000000000000000000000000000000000000000000014156109e4576000818060200190518101906109529190612963565b90506109678160400151858360800151610e05565b60808201526040808201859052517f54e3f31b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906354e3f31b906107a6908490600401612b95565b610a0d7f506172617377617041676772656761746f72547261646572563200000000000061046d565b610a1683610e6c565b604051602001610210929190612bd3565b846107f857610a358461046d565b7f3a20000000000000000000000000000000000000000000000000000000000000610a5f8561046d565b7f203c000000000000000000000000000000000000000000000000000000000000610a898661100e565b7f2c20000000000000000000000000000000000000000000000000000000000000610ab38761100e565b60405161021097969594939291907f3e0000000000000000000000000000000000000000000000000000000000000090602001612c42565b801580610b9957506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063dd62ed3e90610b479030908690600401611ae4565b60206040518083038186803b158015610b5f57600080fd5b505afa158015610b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b979190611955565b155b610bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612d1b565b6106ae8363095ea7b360e01b8484604051602401610bee929190612d2b565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261114e565b60408051602a808252606082810190935273ffffffffffffffffffffffffffffffffffffffff841691600091602082018180368337019050509050603060f81b81600081518110610ca557610ca56119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350607860f81b81600181518110610cec57610cec6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b6014811015610518576000610d34826002612d46565b9050610d42600f8516611204565b83610d4e836029612d83565b81518110610d5e57610d5e6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600484901c9350610da0600f8516611204565b83610dac836028612d83565b81518110610dbc57610dbc6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060049290921c9180610dfd81612d9a565b915050610d1e565b6000828410610e15575080610e65565b600084610e316ec097ce7bc90715b34b9f100000000086612d46565b610e3b9190612dfb565b90506ec097ce7bc90715b34b9f1000000000610e578285612d46565b610e619190612dfb565b9150505b9392505050565b60408051600a80825281830190925260609160e084901c91600091602082018180368337019050509050603060f81b81600081518110610eae57610eae6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350607860f81b81600181518110610ef557610ef56119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b6004811015610518576000610f3d826002612d46565b9050610f4b600f8516611204565b83610f57836009612d83565b81518110610f6757610f676119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600484901c9350610fa9600f8516611204565b83610fb5836008612d83565b81518110610fc557610fc56119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060049290921c918061100681612d9a565b915050610f27565b60608161104e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611078578061106281612d9a565b91506110719050600a83612dfb565b9150611052565b60008167ffffffffffffffff8111156110935761109361170d565b6040519080825280601f01601f1916602001820160405280156110bd576020820181803683370190505b508593509050815b801561114557806110d5816119ba565b91506110e49050600a85612e0f565b6110ef906030611a1e565b60f81b828281518110611104576111046119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061113e600a85612dfb565b93506110c5565b50949350505050565b60006111b0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661122e9092919063ffffffff16565b8051909150156106ae57808060200190518101906111ce9190612e36565b6106ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612eb1565b6000600a8210156112235761121a603083611a1e565b60f81b92915050565b61121a605783611a1e565b606061123d8484600085611245565b949350505050565b606082471015611281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612f1b565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516112aa9190612f2b565b60006040518083038185875af1925050503d80600081146112e7576040519150601f19603f3d011682016040523d82523d6000602084013e6112ec565b606091505b50915091506112fd87838387611308565b979650505050505050565b6060831561136b5782516113645773ffffffffffffffffffffffffffffffffffffffff85163b611364576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612f37565b508161123d565b61123d83838151156113805781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025091906116fc565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b82525050565b602081016113ec82846113b4565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82166113ec565b60006113ec826113f2565b60006113ec82611410565b6113d88161141b565b602081016113ec8284611426565b611446816113f2565b811461145157600080fd5b50565b80356113ec8161143d565b80611446565b80356113ec8161145f565b60008083601f84011261148557611485600080fd5b50813567ffffffffffffffff8111156114a0576114a0600080fd5b6020830191508360018202830111156114bb576114bb600080fd5b9250929050565b6000806000806000608086880312156114dd576114dd600080fd5b60006114e98888611454565b95505060206114fa88828901611454565b945050604061150b88828901611465565b935050606086013567ffffffffffffffff81111561152b5761152b600080fd5b61153788828901611470565b92509250509295509295909350565b806113d8565b602081016113ec8284611546565b600080600080600080600060c0888a03121561157857611578600080fd5b60006115848a8a611454565b97505060206115958a828b01611454565b96505060406115a68a828b01611454565b95505060606115b78a828b01611454565b94505060806115c88a828b01611465565b93505060a088013567ffffffffffffffff8111156115e8576115e8600080fd5b6115f48a828b01611470565b925092505092959891949750929550565b6113d8816113f2565b602081016113ec8284611605565b60005b8381101561163757818101518382015260200161161f565b838111156105b85750506000910152565b6000611652825190565b61166081856020860161161c565b9290920192915050565b60006116768284611648565b7f3a2067657445786368616e6765436f7374206e6f7420696d706c656d656e746581527f64000000000000000000000000000000000000000000000000000000000000006020820152915060218201610e65565b60006116d4825190565b8084526020840193506116eb81856020860161161c565b601f01601f19169290920192915050565b60208082528101610e6581846116ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff821117156117625761176261170d565b6040525050565b600061177460405190565b9050611780828261173c565b919050565b600067ffffffffffffffff82111561179f5761179f61170d565b601f19601f83011660200192915050565b82818337506000910152565b60006117cf6117ca84611785565b611769565b9050828152602081018484840111156117ea576117ea600080fd5b6105188482856117b0565b600082601f83011261180957611809600080fd5b813561123d8482602086016117bc565b6000806040838503121561182f5761182f600080fd5b600061183b8585611465565b925050602083013567ffffffffffffffff81111561185b5761185b600080fd5b611867858286016117f5565b9150509250929050565b7fffffffff000000000000000000000000000000000000000000000000000000008116611446565b80516113ec81611871565b60006118b26117ca84611785565b9050828152602081018484840111156118cd576118cd600080fd5b61051884828561161c565b600082601f8301126118ec576118ec600080fd5b815161123d8482602086016118a4565b6000806040838503121561191257611912600080fd5b600061191e8585611899565b925050602083015167ffffffffffffffff81111561193e5761193e600080fd5b611867858286016118d8565b80516113ec8161145f565b60006020828403121561196a5761196a600080fd5b600061123d848461194a565b60006119828284611546565b50602001919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000816119c9576119c961198b565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115611a3157611a3161198b565b500190565b7fffff00000000000000000000000000000000000000000000000000000000000081166113d8565b7fff0000000000000000000000000000000000000000000000000000000000000081166113d8565b6000611a928289611648565b9150611a9e8288611a36565b600282019150611aae8287611648565b9150611aba8286611a36565b600282019150611aca8285611648565b9150611ad68284611a5e565b506001019695505050505050565b60408101611af28285611605565b610e656020830184611605565b80516113ec8161143d565b600067ffffffffffffffff821115611b2457611b2461170d565b5060209081020190565b600060a08284031215611b4357611b43600080fd5b611b4d60a0611769565b90506000611b5b848461194a565b8252506020611b6c84848301611aff565b6020830152506040611b808482850161194a565b604083015250606082015167ffffffffffffffff811115611ba357611ba3600080fd5b611baf848285016118d8565b6060830152506080611bc38482850161194a565b60808301525092915050565b6000611bdd6117ca84611b0a565b83815290506020808201908402830185811115611bfc57611bfc600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611c2057611c20600080fd5b808601611c2d8982611b2e565b8552505060209283019201611bfe565b5050509392505050565b600082601f830112611c5b57611c5b600080fd5b815161123d848260208601611bcf565b600060808284031215611c8057611c80600080fd5b611c8a6080611769565b90506000611c988484611aff565b8252506020611ca98484830161194a565b6020830152506040611cbd8482850161194a565b604083015250606082015167ffffffffffffffff811115611ce057611ce0600080fd5b611cec84828501611c47565b60608301525092915050565b6000611d066117ca84611b0a565b83815290506020808201908402830185811115611d2557611d25600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611d4957611d49600080fd5b808601611d568982611c6b565b8552505060209283019201611d27565b600082601f830112611d7a57611d7a600080fd5b815161123d848260208601611cf8565b600060608284031215611d9f57611d9f600080fd5b611da96060611769565b90506000611db78484611aff565b8252506020611dc88484830161194a565b602083015250604082015167ffffffffffffffff811115611deb57611deb600080fd5b611df784828501611d66565b60408301525092915050565b6000611e116117ca84611b0a565b83815290506020808201908402830185811115611e3057611e30600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611e5457611e54600080fd5b808601611e618982611d8a565b8552505060209283019201611e32565b600082601f830112611e8557611e85600080fd5b815161123d848260208601611e03565b600060408284031215611eaa57611eaa600080fd5b611eb46040611769565b90506000611ec2848461194a565b825250602082015167ffffffffffffffff811115611ee257611ee2600080fd5b611eee84828501611e71565b60208301525092915050565b6000611f086117ca84611b0a565b83815290506020808201908402830185811115611f2757611f27600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611f4b57611f4b600080fd5b808601611f588982611e95565b8552505060209283019201611f29565b600082601f830112611f7c57611f7c600080fd5b815161123d848260208601611efa565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116611446565b80516113ec81611f8c565b60006101608284031215611fd557611fd5600080fd5b611fe0610160611769565b90506000611fee8484611aff565b8252506020611fff8484830161194a565b60208301525060406120138482850161194a565b60408301525060606120278482850161194a565b606083015250608061203b84828501611aff565b60808301525060a082015167ffffffffffffffff81111561205e5761205e600080fd5b61206a84828501611f68565b60a08301525060c061207e84828501611aff565b60c08301525060e06120928482850161194a565b60e08301525061010082015167ffffffffffffffff8111156120b6576120b6600080fd5b6120c2848285016118d8565b610100830152506101206120d88482850161194a565b610120830152506101406120ee84828501611fb4565b6101408301525092915050565b60006020828403121561211057612110600080fd5b815167ffffffffffffffff81111561212a5761212a600080fd5b61123d84828501611fbf565b805160009060a084019061214a8582611546565b50602083015161215d6020860182611605565b5060408301516121706040860182611546565b506060830151848203606086015261218882826116ca565b91505060808301516105186080860182611546565b6000610e658383612136565b60006121b3825190565b808452602084019350836020820285016121cd8560200190565b8060005b8581101561220257848403895281516121ea858261219d565b94506020830160209a909a01999250506001016121d1565b5091979650505050505050565b805160009060808401906122238582611605565b5060208301516122366020860182611546565b5060408301516122496040860182611546565b506060830151848203606086015261226182826121a9565b95945050505050565b6000610e65838361220f565b6000612280825190565b8084526020840193508360208202850161229a8560200190565b8060005b8581101561220257848403895281516122b7858261226a565b94506020830160209a909a019992505060010161229e565b805160009060608401906122e38582611605565b5060208301516122f66020860182611546565b50604083015184820360408601526122618282612276565b6000610e6583836122cf565b6000612324825190565b8084526020840193508360208202850161233e8560200190565b8060005b85811015612202578484038952815161235b858261230e565b94506020830160209a909a0199925050600101612342565b805160009060408401906123878582611546565b5060208301518482036020860152612261828261231a565b6000610e658383612373565b60006123b5825190565b808452602084019350836020820285016123cf8560200190565b8060005b8581101561220257848403895281516123ec858261239f565b94506020830160209a909a01999250506001016123d3565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166113d8565b80516000906101608401906124418582611605565b5060208301516124546020860182611546565b5060408301516124676040860182611546565b50606083015161247a6060860182611546565b50608083015161248d6080860182611605565b5060a083015184820360a08601526124a582826123ab565b91505060c08301516124ba60c0860182611605565b5060e08301516124cd60e0860182611546565b506101008301518482036101008601526124e782826116ca565b9150506101208301516124fe610120860182611546565b50610140830151610518610140860182612404565b60208082528101610e65818461242c565b6000610160828403121561253a5761253a600080fd5b612545610160611769565b905060006125538484611aff565b82525060206125648484830161194a565b60208301525060406125788482850161194a565b604083015250606061258c8482850161194a565b60608301525060806125a084828501611aff565b60808301525060a082015167ffffffffffffffff8111156125c3576125c3600080fd5b61206a84828501611e71565b6000602082840312156125e4576125e4600080fd5b815167ffffffffffffffff8111156125fe576125fe600080fd5b61123d84828501612524565b805160009061016084019061261f8582611605565b5060208301516126326020860182611546565b5060408301516126456040860182611546565b5060608301516126586060860182611546565b50608083015161266b6080860182611605565b5060a083015184820360a08601526124a5828261231a565b60208082528101610e65818461260a565b60006126a26117ca84611b0a565b838152905060208082019084028301858111156126c1576126c1600080fd5b835b81811015611c3d57806126d68882611aff565b845250602092830192016126c3565b600082601f8301126126f9576126f9600080fd5b815161123d848260208601612694565b60006127176117ca84611b0a565b8381529050602080820190840283018581111561273657612736600080fd5b835b81811015611c3d578061274b888261194a565b84525060209283019201612738565b600082601f83011261276e5761276e600080fd5b815161123d848260208601612709565b60006101e0828403121561279457612794600080fd5b61279f6101e0611769565b905060006127ad8484611aff565b82525060206127be84848301611aff565b60208301525060406127d28482850161194a565b60408301525060606127e68482850161194a565b60608301525060806127fa8482850161194a565b60808301525060a082015167ffffffffffffffff81111561281d5761281d600080fd5b612829848285016126e5565b60a08301525060c082015167ffffffffffffffff81111561284c5761284c600080fd5b612858848285016118d8565b60c08301525060e082015167ffffffffffffffff81111561287b5761287b600080fd5b6128878482850161275a565b60e08301525061010082015167ffffffffffffffff8111156128ab576128ab600080fd5b6128b78482850161275a565b610100830152506101206128cd84828501611aff565b610120830152506101406128e384828501611aff565b610140830152506101606128f98482850161194a565b6101608301525061018082015167ffffffffffffffff81111561291e5761291e600080fd5b61292a848285016118d8565b610180830152506101a06129408482850161194a565b6101a0830152506101c061295684828501611fb4565b6101c08301525092915050565b60006020828403121561297857612978600080fd5b815167ffffffffffffffff81111561299257612992600080fd5b61123d8482850161277e565b60006129aa8383611605565b505060200190565b60006129bc825190565b80845260209384019383018060005b838110156129f05781516129df888261299e565b9750602083019250506001016129cb565b509495945050505050565b60006129aa8383611546565b6000612a11825190565b80845260209384019383018060005b838110156129f0578151612a3488826129fb565b975060208301925050600101612a20565b80516000906101e0840190612a5a8582611605565b506020830151612a6d6020860182611605565b506040830151612a806040860182611546565b506060830151612a936060860182611546565b506080830151612aa66080860182611546565b5060a083015184820360a0860152612abe82826129b2565b91505060c083015184820360c0860152612ad882826116ca565b91505060e083015184820360e0860152612af28282612a07565b915050610100830151848203610100860152612b0e8282612a07565b915050610120830151612b25610120860182611605565b50610140830151612b3a610140860182611605565b50610160830151612b4f610160860182611546565b50610180830151848203610180860152612b6982826116ca565b9150506101a0830151612b806101a0860182611546565b506101c08301516105186101c0860182612404565b60208082528101610e658184612a45565b7f3e00000000000000000000000000000000000000000000000000000000000000815260005b5060010190565b6000612bdf8285611648565b7f3a20496e76616c69642050617261737761702066756e6374696f6e2073656c6581527f63746f72203c000000000000000000000000000000000000000000000000000060208201526026019150612c378284611648565b915061123d82612ba6565b6000612c4e828b611648565b9150612c5a828a611a36565b600282019150612c6a8289611648565b9150612c768288611a36565b600282019150612c868287611648565b9150612c928286611a36565b600282019150612ca28285611648565b9150612cae8284611a5e565b5060010198975050505050505050565b603681526000602082017f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f81527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000602082015291505b5060400190565b602080825281016113ec81612cbe565b60408101612d398285611605565b610e656020830184611546565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612d7e57612d7e61198b565b500290565b600082821015612d9557612d9561198b565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612bcc57612bcc61198b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612e0a57612e0a612dcc565b500490565b600082612e1e57612e1e612dcc565b500690565b801515611446565b80516113ec81612e23565b600060208284031215612e4b57612e4b600080fd5b600061123d8484612e2b565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e81527f6f7420737563636565640000000000000000000000000000000000000000000060208201529150612d14565b602080825281016113ec81612e57565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f81527f722063616c6c000000000000000000000000000000000000000000000000000060208201529150612d14565b602080825281016113ec81612ec1565b6000610e658284611648565b602080825281016113ec81601d81527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060208201526040019056fea2646970667358221220247ff1554db9e872d06862ed15b1bac61139035d71079cefb02a6be807b1080364736f6c63430008090033000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee57000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae0000000000000000000000006bd780e7fdf01d77e4d475c821f1e7ae05409072
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c806345cd3cea1161005b57806345cd3cea146101405780636e3b7a79146101675780637d98ebac1461018e57806384796caf146101a157600080fd5b80630d94ea2a1461008d57806315c14a4a146100ca57806317f5e788146100f95780633a8fdd7d14610120575b600080fd5b6100b47f46c67b6d0000000000000000000000000000000000000000000000000000000081565b6040516100c191906113de565b60405180910390f35b7f0000000000000000000000006bd780e7fdf01d77e4d475c821f1e7ae054090725b6040516100c1919061142f565b6100ec7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5781565b61013361012e3660046114c2565b6101d5565b6040516100c1919061154c565b6100b47fa94e78ef0000000000000000000000000000000000000000000000000000000081565b6100b47f54e3f31b0000000000000000000000000000000000000000000000000000000081565b61013361019c36600461155a565b610259565b6101c87f000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae81565b6040516100c1919061160e565b60006102007f506172617377617041676772656761746f72547261646572563200000000000061046d565b604051602001610210919061166a565b60408051601f19818403018152908290527f08c379a0000000000000000000000000000000000000000000000000000000008252610250916004016116fc565b60405180910390fd5b6000336102e073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006bd780e7fdf01d77e4d475c821f1e7ae054090721682147f4f6e6c79446f6c6f6d6974654d617267696e00000000000000000000000000007f4f6e6c7920446f6c6f6d6974652063616e2063616c6c2066756e6374696f6e0084610520565b61030b867f000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae876105be565b60008061031a85870187611819565b915091506000808280602001905181019061033591906118fc565b915091506103448983836106b3565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8d16906370a082319061039990309060040161160e565b60206040518083038186803b1580156103b157600080fd5b505afa1580156103c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e99190611955565b905061043b858210157f506172617377617041676772656761746f7254726164657256320000000000007f496e73756666696369656e74206f757470757420616d6f756e740000000000008489610a27565b61045c73ffffffffffffffffffffffffffffffffffffffff8d168e83610aeb565b9d9c50505050505050505050505050565b60606000826040516020016104829190611976565b60408051601f19818403018152919052905060205b801561050557806104a7816119ba565b9150508181815181106104bc576104bc6119ef565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016156105005760006104f5826001611a1e565b835250909392505050565b610497565b5060408051600080825260208201909252905b509392505050565b836105b85761052e8361046d565b7f3a200000000000000000000000000000000000000000000000000000000000006105588461046d565b7f203c00000000000000000000000000000000000000000000000000000000000061058285610c52565b6040516102109594939291907f3e0000000000000000000000000000000000000000000000000000000000000090602001611a86565b50505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff85169063dd62ed3e906106159030908790600401611ae4565b60206040518083038186803b15801561062d57600080fd5b505afa158015610641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106659190611955565b111561068d5761068d73ffffffffffffffffffffffffffffffffffffffff8416836000610aeb565b6106ae73ffffffffffffffffffffffffffffffffffffffff84168383610aeb565b505050565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f46c67b6d0000000000000000000000000000000000000000000000000000000014156107ff5760008180602001905181019061071391906120fb565b90506107288160200151858360600151610e05565b6060820152602081018490526040517f46c67b6d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5716906346c67b6d906107a6908490600401612513565b602060405180830381600087803b1580156107c057600080fd5b505af11580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190611955565b5050505050565b7fffffffff0000000000000000000000000000000000000000000000000000000082167fa94e78ef0000000000000000000000000000000000000000000000000000000014156108f25760008180602001905181019061085f91906125cf565b90506108748160200151858360600151610e05565b6060820152602081018490526040517fa94e78ef00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee57169063a94e78ef906107a6908490600401612683565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f54e3f31b0000000000000000000000000000000000000000000000000000000014156109e4576000818060200190518101906109529190612963565b90506109678160400151858360800151610e05565b60808201526040808201859052517f54e3f31b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5716906354e3f31b906107a6908490600401612b95565b610a0d7f506172617377617041676772656761746f72547261646572563200000000000061046d565b610a1683610e6c565b604051602001610210929190612bd3565b846107f857610a358461046d565b7f3a20000000000000000000000000000000000000000000000000000000000000610a5f8561046d565b7f203c000000000000000000000000000000000000000000000000000000000000610a898661100e565b7f2c20000000000000000000000000000000000000000000000000000000000000610ab38761100e565b60405161021097969594939291907f3e0000000000000000000000000000000000000000000000000000000000000090602001612c42565b801580610b9957506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84169063dd62ed3e90610b479030908690600401611ae4565b60206040518083038186803b158015610b5f57600080fd5b505afa158015610b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b979190611955565b155b610bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612d1b565b6106ae8363095ea7b360e01b8484604051602401610bee929190612d2b565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261114e565b60408051602a808252606082810190935273ffffffffffffffffffffffffffffffffffffffff841691600091602082018180368337019050509050603060f81b81600081518110610ca557610ca56119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350607860f81b81600181518110610cec57610cec6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b6014811015610518576000610d34826002612d46565b9050610d42600f8516611204565b83610d4e836029612d83565b81518110610d5e57610d5e6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600484901c9350610da0600f8516611204565b83610dac836028612d83565b81518110610dbc57610dbc6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060049290921c9180610dfd81612d9a565b915050610d1e565b6000828410610e15575080610e65565b600084610e316ec097ce7bc90715b34b9f100000000086612d46565b610e3b9190612dfb565b90506ec097ce7bc90715b34b9f1000000000610e578285612d46565b610e619190612dfb565b9150505b9392505050565b60408051600a80825281830190925260609160e084901c91600091602082018180368337019050509050603060f81b81600081518110610eae57610eae6119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350607860f81b81600181518110610ef557610ef56119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b6004811015610518576000610f3d826002612d46565b9050610f4b600f8516611204565b83610f57836009612d83565b81518110610f6757610f676119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600484901c9350610fa9600f8516611204565b83610fb5836008612d83565b81518110610fc557610fc56119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060049290921c918061100681612d9a565b915050610f27565b60608161104e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611078578061106281612d9a565b91506110719050600a83612dfb565b9150611052565b60008167ffffffffffffffff8111156110935761109361170d565b6040519080825280601f01601f1916602001820160405280156110bd576020820181803683370190505b508593509050815b801561114557806110d5816119ba565b91506110e49050600a85612e0f565b6110ef906030611a1e565b60f81b828281518110611104576111046119ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061113e600a85612dfb565b93506110c5565b50949350505050565b60006111b0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661122e9092919063ffffffff16565b8051909150156106ae57808060200190518101906111ce9190612e36565b6106ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612eb1565b6000600a8210156112235761121a603083611a1e565b60f81b92915050565b61121a605783611a1e565b606061123d8484600085611245565b949350505050565b606082471015611281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612f1b565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516112aa9190612f2b565b60006040518083038185875af1925050503d80600081146112e7576040519150601f19603f3d011682016040523d82523d6000602084013e6112ec565b606091505b50915091506112fd87838387611308565b979650505050505050565b6060831561136b5782516113645773ffffffffffffffffffffffffffffffffffffffff85163b611364576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025090612f37565b508161123d565b61123d83838151156113805781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025091906116fc565b7fffffffff0000000000000000000000000000000000000000000000000000000081165b82525050565b602081016113ec82846113b4565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82166113ec565b60006113ec826113f2565b60006113ec82611410565b6113d88161141b565b602081016113ec8284611426565b611446816113f2565b811461145157600080fd5b50565b80356113ec8161143d565b80611446565b80356113ec8161145f565b60008083601f84011261148557611485600080fd5b50813567ffffffffffffffff8111156114a0576114a0600080fd5b6020830191508360018202830111156114bb576114bb600080fd5b9250929050565b6000806000806000608086880312156114dd576114dd600080fd5b60006114e98888611454565b95505060206114fa88828901611454565b945050604061150b88828901611465565b935050606086013567ffffffffffffffff81111561152b5761152b600080fd5b61153788828901611470565b92509250509295509295909350565b806113d8565b602081016113ec8284611546565b600080600080600080600060c0888a03121561157857611578600080fd5b60006115848a8a611454565b97505060206115958a828b01611454565b96505060406115a68a828b01611454565b95505060606115b78a828b01611454565b94505060806115c88a828b01611465565b93505060a088013567ffffffffffffffff8111156115e8576115e8600080fd5b6115f48a828b01611470565b925092505092959891949750929550565b6113d8816113f2565b602081016113ec8284611605565b60005b8381101561163757818101518382015260200161161f565b838111156105b85750506000910152565b6000611652825190565b61166081856020860161161c565b9290920192915050565b60006116768284611648565b7f3a2067657445786368616e6765436f7374206e6f7420696d706c656d656e746581527f64000000000000000000000000000000000000000000000000000000000000006020820152915060218201610e65565b60006116d4825190565b8084526020840193506116eb81856020860161161c565b601f01601f19169290920192915050565b60208082528101610e6581846116ca565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff821117156117625761176261170d565b6040525050565b600061177460405190565b9050611780828261173c565b919050565b600067ffffffffffffffff82111561179f5761179f61170d565b601f19601f83011660200192915050565b82818337506000910152565b60006117cf6117ca84611785565b611769565b9050828152602081018484840111156117ea576117ea600080fd5b6105188482856117b0565b600082601f83011261180957611809600080fd5b813561123d8482602086016117bc565b6000806040838503121561182f5761182f600080fd5b600061183b8585611465565b925050602083013567ffffffffffffffff81111561185b5761185b600080fd5b611867858286016117f5565b9150509250929050565b7fffffffff000000000000000000000000000000000000000000000000000000008116611446565b80516113ec81611871565b60006118b26117ca84611785565b9050828152602081018484840111156118cd576118cd600080fd5b61051884828561161c565b600082601f8301126118ec576118ec600080fd5b815161123d8482602086016118a4565b6000806040838503121561191257611912600080fd5b600061191e8585611899565b925050602083015167ffffffffffffffff81111561193e5761193e600080fd5b611867858286016118d8565b80516113ec8161145f565b60006020828403121561196a5761196a600080fd5b600061123d848461194a565b60006119828284611546565b50602001919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000816119c9576119c961198b565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115611a3157611a3161198b565b500190565b7fffff00000000000000000000000000000000000000000000000000000000000081166113d8565b7fff0000000000000000000000000000000000000000000000000000000000000081166113d8565b6000611a928289611648565b9150611a9e8288611a36565b600282019150611aae8287611648565b9150611aba8286611a36565b600282019150611aca8285611648565b9150611ad68284611a5e565b506001019695505050505050565b60408101611af28285611605565b610e656020830184611605565b80516113ec8161143d565b600067ffffffffffffffff821115611b2457611b2461170d565b5060209081020190565b600060a08284031215611b4357611b43600080fd5b611b4d60a0611769565b90506000611b5b848461194a565b8252506020611b6c84848301611aff565b6020830152506040611b808482850161194a565b604083015250606082015167ffffffffffffffff811115611ba357611ba3600080fd5b611baf848285016118d8565b6060830152506080611bc38482850161194a565b60808301525092915050565b6000611bdd6117ca84611b0a565b83815290506020808201908402830185811115611bfc57611bfc600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611c2057611c20600080fd5b808601611c2d8982611b2e565b8552505060209283019201611bfe565b5050509392505050565b600082601f830112611c5b57611c5b600080fd5b815161123d848260208601611bcf565b600060808284031215611c8057611c80600080fd5b611c8a6080611769565b90506000611c988484611aff565b8252506020611ca98484830161194a565b6020830152506040611cbd8482850161194a565b604083015250606082015167ffffffffffffffff811115611ce057611ce0600080fd5b611cec84828501611c47565b60608301525092915050565b6000611d066117ca84611b0a565b83815290506020808201908402830185811115611d2557611d25600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611d4957611d49600080fd5b808601611d568982611c6b565b8552505060209283019201611d27565b600082601f830112611d7a57611d7a600080fd5b815161123d848260208601611cf8565b600060608284031215611d9f57611d9f600080fd5b611da96060611769565b90506000611db78484611aff565b8252506020611dc88484830161194a565b602083015250604082015167ffffffffffffffff811115611deb57611deb600080fd5b611df784828501611d66565b60408301525092915050565b6000611e116117ca84611b0a565b83815290506020808201908402830185811115611e3057611e30600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611e5457611e54600080fd5b808601611e618982611d8a565b8552505060209283019201611e32565b600082601f830112611e8557611e85600080fd5b815161123d848260208601611e03565b600060408284031215611eaa57611eaa600080fd5b611eb46040611769565b90506000611ec2848461194a565b825250602082015167ffffffffffffffff811115611ee257611ee2600080fd5b611eee84828501611e71565b60208301525092915050565b6000611f086117ca84611b0a565b83815290506020808201908402830185811115611f2757611f27600080fd5b835b81811015611c3d57805167ffffffffffffffff811115611f4b57611f4b600080fd5b808601611f588982611e95565b8552505060209283019201611f29565b600082601f830112611f7c57611f7c600080fd5b815161123d848260208601611efa565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116611446565b80516113ec81611f8c565b60006101608284031215611fd557611fd5600080fd5b611fe0610160611769565b90506000611fee8484611aff565b8252506020611fff8484830161194a565b60208301525060406120138482850161194a565b60408301525060606120278482850161194a565b606083015250608061203b84828501611aff565b60808301525060a082015167ffffffffffffffff81111561205e5761205e600080fd5b61206a84828501611f68565b60a08301525060c061207e84828501611aff565b60c08301525060e06120928482850161194a565b60e08301525061010082015167ffffffffffffffff8111156120b6576120b6600080fd5b6120c2848285016118d8565b610100830152506101206120d88482850161194a565b610120830152506101406120ee84828501611fb4565b6101408301525092915050565b60006020828403121561211057612110600080fd5b815167ffffffffffffffff81111561212a5761212a600080fd5b61123d84828501611fbf565b805160009060a084019061214a8582611546565b50602083015161215d6020860182611605565b5060408301516121706040860182611546565b506060830151848203606086015261218882826116ca565b91505060808301516105186080860182611546565b6000610e658383612136565b60006121b3825190565b808452602084019350836020820285016121cd8560200190565b8060005b8581101561220257848403895281516121ea858261219d565b94506020830160209a909a01999250506001016121d1565b5091979650505050505050565b805160009060808401906122238582611605565b5060208301516122366020860182611546565b5060408301516122496040860182611546565b506060830151848203606086015261226182826121a9565b95945050505050565b6000610e65838361220f565b6000612280825190565b8084526020840193508360208202850161229a8560200190565b8060005b8581101561220257848403895281516122b7858261226a565b94506020830160209a909a019992505060010161229e565b805160009060608401906122e38582611605565b5060208301516122f66020860182611546565b50604083015184820360408601526122618282612276565b6000610e6583836122cf565b6000612324825190565b8084526020840193508360208202850161233e8560200190565b8060005b85811015612202578484038952815161235b858261230e565b94506020830160209a909a0199925050600101612342565b805160009060408401906123878582611546565b5060208301518482036020860152612261828261231a565b6000610e658383612373565b60006123b5825190565b808452602084019350836020820285016123cf8560200190565b8060005b8581101561220257848403895281516123ec858261239f565b94506020830160209a909a01999250506001016123d3565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081166113d8565b80516000906101608401906124418582611605565b5060208301516124546020860182611546565b5060408301516124676040860182611546565b50606083015161247a6060860182611546565b50608083015161248d6080860182611605565b5060a083015184820360a08601526124a582826123ab565b91505060c08301516124ba60c0860182611605565b5060e08301516124cd60e0860182611546565b506101008301518482036101008601526124e782826116ca565b9150506101208301516124fe610120860182611546565b50610140830151610518610140860182612404565b60208082528101610e65818461242c565b6000610160828403121561253a5761253a600080fd5b612545610160611769565b905060006125538484611aff565b82525060206125648484830161194a565b60208301525060406125788482850161194a565b604083015250606061258c8482850161194a565b60608301525060806125a084828501611aff565b60808301525060a082015167ffffffffffffffff8111156125c3576125c3600080fd5b61206a84828501611e71565b6000602082840312156125e4576125e4600080fd5b815167ffffffffffffffff8111156125fe576125fe600080fd5b61123d84828501612524565b805160009061016084019061261f8582611605565b5060208301516126326020860182611546565b5060408301516126456040860182611546565b5060608301516126586060860182611546565b50608083015161266b6080860182611605565b5060a083015184820360a08601526124a5828261231a565b60208082528101610e65818461260a565b60006126a26117ca84611b0a565b838152905060208082019084028301858111156126c1576126c1600080fd5b835b81811015611c3d57806126d68882611aff565b845250602092830192016126c3565b600082601f8301126126f9576126f9600080fd5b815161123d848260208601612694565b60006127176117ca84611b0a565b8381529050602080820190840283018581111561273657612736600080fd5b835b81811015611c3d578061274b888261194a565b84525060209283019201612738565b600082601f83011261276e5761276e600080fd5b815161123d848260208601612709565b60006101e0828403121561279457612794600080fd5b61279f6101e0611769565b905060006127ad8484611aff565b82525060206127be84848301611aff565b60208301525060406127d28482850161194a565b60408301525060606127e68482850161194a565b60608301525060806127fa8482850161194a565b60808301525060a082015167ffffffffffffffff81111561281d5761281d600080fd5b612829848285016126e5565b60a08301525060c082015167ffffffffffffffff81111561284c5761284c600080fd5b612858848285016118d8565b60c08301525060e082015167ffffffffffffffff81111561287b5761287b600080fd5b6128878482850161275a565b60e08301525061010082015167ffffffffffffffff8111156128ab576128ab600080fd5b6128b78482850161275a565b610100830152506101206128cd84828501611aff565b610120830152506101406128e384828501611aff565b610140830152506101606128f98482850161194a565b6101608301525061018082015167ffffffffffffffff81111561291e5761291e600080fd5b61292a848285016118d8565b610180830152506101a06129408482850161194a565b6101a0830152506101c061295684828501611fb4565b6101c08301525092915050565b60006020828403121561297857612978600080fd5b815167ffffffffffffffff81111561299257612992600080fd5b61123d8482850161277e565b60006129aa8383611605565b505060200190565b60006129bc825190565b80845260209384019383018060005b838110156129f05781516129df888261299e565b9750602083019250506001016129cb565b509495945050505050565b60006129aa8383611546565b6000612a11825190565b80845260209384019383018060005b838110156129f0578151612a3488826129fb565b975060208301925050600101612a20565b80516000906101e0840190612a5a8582611605565b506020830151612a6d6020860182611605565b506040830151612a806040860182611546565b506060830151612a936060860182611546565b506080830151612aa66080860182611546565b5060a083015184820360a0860152612abe82826129b2565b91505060c083015184820360c0860152612ad882826116ca565b91505060e083015184820360e0860152612af28282612a07565b915050610100830151848203610100860152612b0e8282612a07565b915050610120830151612b25610120860182611605565b50610140830151612b3a610140860182611605565b50610160830151612b4f610160860182611546565b50610180830151848203610180860152612b6982826116ca565b9150506101a0830151612b806101a0860182611546565b506101c08301516105186101c0860182612404565b60208082528101610e658184612a45565b7f3e00000000000000000000000000000000000000000000000000000000000000815260005b5060010190565b6000612bdf8285611648565b7f3a20496e76616c69642050617261737761702066756e6374696f6e2073656c6581527f63746f72203c000000000000000000000000000000000000000000000000000060208201526026019150612c378284611648565b915061123d82612ba6565b6000612c4e828b611648565b9150612c5a828a611a36565b600282019150612c6a8289611648565b9150612c768288611a36565b600282019150612c868287611648565b9150612c928286611a36565b600282019150612ca28285611648565b9150612cae8284611a5e565b5060010198975050505050505050565b603681526000602082017f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f81527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000602082015291505b5060400190565b602080825281016113ec81612cbe565b60408101612d398285611605565b610e656020830184611546565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612d7e57612d7e61198b565b500290565b600082821015612d9557612d9561198b565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612bcc57612bcc61198b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612e0a57612e0a612dcc565b500490565b600082612e1e57612e1e612dcc565b500690565b801515611446565b80516113ec81612e23565b600060208284031215612e4b57612e4b600080fd5b600061123d8484612e2b565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e81527f6f7420737563636565640000000000000000000000000000000000000000000060208201529150612d14565b602080825281016113ec81612e57565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f81527f722063616c6c000000000000000000000000000000000000000000000000000060208201529150612d14565b602080825281016113ec81612ec1565b6000610e658284611648565b602080825281016113ec81601d81527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060208201526040019056fea2646970667358221220247ff1554db9e872d06862ed15b1bac61139035d71079cefb02a6be807b1080364736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee57000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae0000000000000000000000006bd780e7fdf01d77e4d475c821f1e7ae05409072
-----Decoded View---------------
Arg [0] : _paraswapAugustusRouter (address): 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57
Arg [1] : _paraswapTransferProxy (address): 0x216B4B4Ba9F3e719726886d34a177484278Bfcae
Arg [2] : _dolomiteMargin (address): 0x6Bd780E7fDf01D77e4d475c821f1e7AE05409072
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee57
Arg [1] : 000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae
Arg [2] : 0000000000000000000000006bd780e7fdf01d77e4d475c821f1e7ae05409072
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.