Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
SwapLib
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { DelegateModule } from "contracts/modules/DelegateModule.sol";
import { ConnectorRegistry } from "contracts/ConnectorRegistry.sol";
import { ISwapConnector } from "contracts/interfaces/ISwapConnector.sol";
import { SwapParams } from "contracts/structs/SwapStructs.sol";
import { ISwapLib } from "contracts/interfaces/libraries/ISwapLib.sol";
address constant UNISWAP_ETH = 0x0000000000000000000000000000000000000000;
contract SwapLib is DelegateModule, ISwapLib {
error SwapAmountZero();
ConnectorRegistry immutable connectorRegistry;
constructor(
ConnectorRegistry connectorRegistry_
) {
connectorRegistry = connectorRegistry_;
}
function swap(
SwapParams memory swapParams
) external payable {
_swap(swapParams);
}
function swapMultiple(
SwapParams[] memory swapParams
) external payable {
uint256 swapDataLength = swapParams.length;
for (uint256 i; i < swapDataLength;) {
_swap(swapParams[i]);
unchecked {
i++;
}
}
}
/* Internal Functions */
function _swap(
SwapParams memory swapParams
) internal {
address tokenIn = swapParams.tokenIn;
bool isNative = tokenIn == UNISWAP_ETH;
if (swapParams.amountIn == 0) {
swapParams.amountIn = isNative
? address(this).balance
: IERC20(tokenIn).balanceOf(address(this));
}
if (swapParams.amountIn == 0) {
revert SwapAmountZero();
}
if (!isNative) {
// In case there is USDT dust approval, revoke it
SafeTransferLib.safeApprove(tokenIn, swapParams.tokenApproval, 0);
SafeTransferLib.safeApprove(
tokenIn, swapParams.tokenApproval, swapParams.amountIn
);
}
address connectorAddress =
connectorRegistry.connectorOf(swapParams.router);
ISwapConnector swapConnector = ISwapConnector(connectorAddress);
if (!isNative) {
_delegateTo(
address(swapConnector),
abi.encodeCall(
swapConnector.swapExactTokensForTokens, (swapParams)
)
);
} else {
_delegateTo(
address(swapConnector),
abi.encodeCall(
swapConnector.swapExactETHForTokens, (swapParams)
)
);
}
if (!isNative) {
// Revoke any approval after swap in case the swap amount was
// estimated
SafeTransferLib.safeApprove(tokenIn, swapParams.tokenApproval, 0);
}
}
}// 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: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error ETHTransferFailed();
error TransferFromFailed();
error TransferFailed();
error ApproveFailed();
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
if (!success) revert ETHTransferFailed();
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
address token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
if (!success) revert TransferFromFailed();
}
function safeTransfer(
address token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert TransferFailed();
}
function safeApprove(
address token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert ApproveFailed();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract DelegateModule {
function _delegateTo(
address to,
bytes memory data
) internal returns (bytes memory) {
(bool success, bytes memory result) = to.delegatecall(data);
if (!success) {
if (result.length == 0) revert();
assembly {
revert(add(32, result), mload(result))
}
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { Admin } from "contracts/base/Admin.sol";
import { TimelockAdmin } from "contracts/base/TimelockAdmin.sol";
error ConnectorNotRegistered(address target);
error CustomRegistryAlreadyRegistered();
interface ICustomConnectorRegistry {
function connectorOf(
address target
) external view returns (address);
}
contract ConnectorRegistry is Admin, TimelockAdmin {
event ConnectorChanged(address target, address connector);
event CustomRegistryAdded(address registry);
event CustomRegistryRemoved(address registry);
error ConnectorAlreadySet(address target);
error ConnectorNotSet(address target);
error ArrayLengthMismatch();
ICustomConnectorRegistry[] public customRegistries;
mapping(address target => address connector) private connectors_;
constructor(
address admin_,
address timelockAdmin_
) Admin(admin_) TimelockAdmin(timelockAdmin_) { }
/// Admin functions
/// @notice Update connector addresses for a batch of targets.
/// @dev Controls which connector contracts are used for the specified
/// targets.
/// @custom:access Restricted to protocol admin.
function setConnectors(
address[] calldata targets,
address[] calldata connectors
) external onlyAdmin {
if (targets.length != connectors.length) {
revert ArrayLengthMismatch();
}
for (uint256 i; i != targets.length;) {
if (connectors_[targets[i]] != address(0)) {
revert ConnectorAlreadySet(targets[i]);
}
connectors_[targets[i]] = connectors[i];
emit ConnectorChanged(targets[i], connectors[i]);
unchecked {
++i;
}
}
}
function updateConnectors(
address[] calldata targets,
address[] calldata connectors
) external onlyTimelockAdmin {
if (targets.length != connectors.length) {
revert ArrayLengthMismatch();
}
for (uint256 i; i != targets.length;) {
if (connectors_[targets[i]] == address(0)) {
revert ConnectorNotSet(targets[i]);
}
connectors_[targets[i]] = connectors[i];
emit ConnectorChanged(targets[i], connectors[i]);
unchecked {
++i;
}
}
}
/// @notice Append an address to the custom registries list.
/// @custom:access Restricted to protocol admin.
function addCustomRegistry(
ICustomConnectorRegistry registry
) external onlyAdmin {
if (isCustomRegistry(registry)) {
revert CustomRegistryAlreadyRegistered();
}
customRegistries.push(registry);
emit CustomRegistryAdded(address(registry));
}
/// @notice Replace an address in the custom registries list.
/// @custom:access Restricted to protocol admin.
function updateCustomRegistry(
uint256 index,
ICustomConnectorRegistry newRegistry
) external onlyTimelockAdmin {
ICustomConnectorRegistry oldRegistry = customRegistries[index];
emit CustomRegistryRemoved(address(oldRegistry));
customRegistries[index] = newRegistry;
if (address(newRegistry) != address(0)) {
emit CustomRegistryAdded(address(newRegistry));
}
}
/// Public functions
function connectorOf(
address target
) external view returns (address) {
address connector = _getConnector(target);
if (connector != address(0)) {
return connector;
}
revert ConnectorNotRegistered(target);
}
function hasConnector(
address target
) external view returns (bool) {
return _getConnector(target) != address(0);
}
function isCustomRegistry(
ICustomConnectorRegistry registry
) public view returns (bool) {
for (uint256 i; i != customRegistries.length;) {
if (address(customRegistries[i]) == address(registry)) {
return true;
}
unchecked {
++i;
}
}
return false;
}
/// Internal functions
function _getConnector(
address target
) internal view returns (address) {
address connector = connectors_[target];
if (connector != address(0)) {
return connector;
}
uint256 length = customRegistries.length;
for (uint256 i; i != length;) {
if (address(customRegistries[i]) != address(0)) {
(bool success, bytes memory data) = address(customRegistries[i])
.staticcall(
abi.encodeWithSelector(
ICustomConnectorRegistry.connectorOf.selector, target
)
);
if (success && data.length == 32) {
address _connector = abi.decode(data, (address));
if (_connector != address(0)) {
return _connector;
}
}
}
unchecked {
++i;
}
}
return address(0);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/SwapStructs.sol";
interface ISwapConnector {
function swapExactTokensForTokens(
SwapParams memory swap
) external payable;
function swapExactETHForTokens(
SwapParams memory swap
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct SwapParams {
address tokenApproval;
address router;
uint256 amountIn;
uint256 desiredAmountOut;
uint256 minAmountOut;
address tokenIn;
address tokenOut;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/SwapStructs.sol";
interface ISwapLib {
function swap(
SwapParams memory swap
) external payable;
function swapMultiple(
SwapParams[] memory swaps
) external payable;
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title Admin contract
/// @author vfat.tools
/// @notice Provides an administration mechanism allowing restricted functions
abstract contract Admin {
/// ERRORS ///
/// @notice Thrown when the caller is not the admin
error NotAdminError(); //0xb5c42b3b
/// EVENTS ///
/// @notice Emitted when a new admin is set
/// @param oldAdmin Address of the old admin
/// @param newAdmin Address of the new admin
event AdminSet(address oldAdmin, address newAdmin);
/// STORAGE ///
/// @notice Address of the current admin
address public admin;
/// MODIFIERS ///
/// @dev Restricts a function to the admin
modifier onlyAdmin() {
if (msg.sender != admin) revert NotAdminError();
_;
}
/// WRITE FUNCTIONS ///
/// @param admin_ Address of the admin
constructor(
address admin_
) {
emit AdminSet(address(0), admin_);
admin = admin_;
}
/// @notice Sets a new admin
/// @param newAdmin Address of the new admin
/// @custom:access Restricted to protocol admin.
function setAdmin(
address newAdmin
) external onlyAdmin {
emit AdminSet(admin, newAdmin);
admin = newAdmin;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title TimelockAdmin contract
/// @author vfat.tools
/// @notice Provides an timelockAdministration mechanism allowing restricted
/// functions
abstract contract TimelockAdmin {
/// ERRORS ///
/// @notice Thrown when the caller is not the timelockAdmin
error NotTimelockAdminError();
/// EVENTS ///
/// @notice Emitted when a new timelockAdmin is set
/// @param oldTimelockAdmin Address of the old timelockAdmin
/// @param newTimelockAdmin Address of the new timelockAdmin
event TimelockAdminSet(address oldTimelockAdmin, address newTimelockAdmin);
/// STORAGE ///
/// @notice Address of the current timelockAdmin
address public timelockAdmin;
/// MODIFIERS ///
/// @dev Restricts a function to the timelockAdmin
modifier onlyTimelockAdmin() {
if (msg.sender != timelockAdmin) revert NotTimelockAdminError();
_;
}
/// WRITE FUNCTIONS ///
/// @param timelockAdmin_ Address of the timelockAdmin
constructor(
address timelockAdmin_
) {
emit TimelockAdminSet(timelockAdmin, timelockAdmin_);
timelockAdmin = timelockAdmin_;
}
/// @notice Sets a new timelockAdmin
/// @dev Can only be called by the current timelockAdmin
/// @param newTimelockAdmin Address of the new timelockAdmin
function setTimelockAdmin(
address newTimelockAdmin
) external onlyTimelockAdmin {
emit TimelockAdminSet(timelockAdmin, newTimelockAdmin);
timelockAdmin = newTimelockAdmin;
}
}{
"remappings": [
"solmate/=lib/solmate/src/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@morpho-blue/=lib/morpho-blue/src/",
"ds-test/=lib/solmate/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"morpho-blue/=lib/morpho-blue/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ConnectorRegistry","name":"connectorRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApproveFailed","type":"error"},{"inputs":[],"name":"SwapAmountZero","type":"error"},{"inputs":[{"components":[{"internalType":"address","name":"tokenApproval","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"desiredAmountOut","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct SwapParams","name":"swapParams","type":"tuple"}],"name":"swap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenApproval","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"desiredAmountOut","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct SwapParams[]","name":"swapParams","type":"tuple[]"}],"name":"swapMultiple","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
60a060405234801561001057600080fd5b5060405161085038038061085083398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516107c561008b60003960006101a901526107c56000f3fe6080604052600436106100295760003560e01c806321e9d05b1461002e578063c472d3e114610043575b600080fd5b61004161003c36600461054d565b610056565b005b610041610051366004610610565b610092565b805160005b8181101561008d5761008583828151811061007857610078610645565b602002602001015161009e565b60010161005b565b505050565b61009b8161009e565b50565b60a081015160408201516001600160a01b0382161590600003610135578061012d576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610104573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610128919061065b565b61012f565b475b60408401525b826040015160000361015a57604051630690709160e41b815260040160405180910390fd5b806101825761016f82846000015160006102ba565b61018282846000015185604001516102ba565b60208301516040516363cd755760e11b81526001600160a01b0391821660048201526000917f0000000000000000000000000000000000000000000000000000000000000000169063c79aeaae90602401602060405180830381865afa1580156101f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102149190610674565b905080826102785761027281826001600160a01b03166353ef91208860405160240161024091906106e8565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610317565b5061029e565b61029c81826001600160a01b031663e697fa538860405160240161024091906106e8565b505b826102b3576102b384866000015160006102ba565b5050505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061031157604051633e3f8f7360e01b815260040160405180910390fd5b50505050565b6060600080846001600160a01b0316846040516103349190610773565b600060405180830381855af49150503d806000811461036f576040519150601f19603f3d011682016040523d82523d6000602084013e610374565b606091505b50915091508161039457805160000361038c57600080fd5b805181602001fd5b949350505050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156103d6576103d661039c565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156104055761040561039c565b604052919050565b6001600160a01b038116811461009b57600080fd5b803561042d8161040d565b919050565b600082601f83011261044357600080fd5b813567ffffffffffffffff81111561045d5761045d61039c565b610470601f8201601f19166020016103dc565b81815284602083860101111561048557600080fd5b816020850160208301376000918101602001919091529392505050565b600061010082840312156104b557600080fd5b6104bd6103b2565b90506104c882610422565b81526104d660208301610422565b602082015260408201356040820152606082013560608201526080820135608082015261050560a08301610422565b60a082015261051660c08301610422565b60c082015260e082013567ffffffffffffffff81111561053557600080fd5b61054184828501610432565b60e08301525092915050565b6000602080838503121561056057600080fd5b823567ffffffffffffffff8082111561057857600080fd5b818501915085601f83011261058c57600080fd5b81358181111561059e5761059e61039c565b8060051b6105ad8582016103dc565b91825283810185019185810190898411156105c757600080fd5b86860192505b83831015610603578235858111156105e55760008081fd5b6105f38b89838a01016104a2565b83525091860191908601906105cd565b9998505050505050505050565b60006020828403121561062257600080fd5b813567ffffffffffffffff81111561063957600080fd5b610394848285016104a2565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561066d57600080fd5b5051919050565b60006020828403121561068657600080fd5b81516106918161040d565b9392505050565b60005b838110156106b357818101518382015260200161069b565b50506000910152565b600081518084526106d4816020860160208601610698565b601f01601f19169290920160200192915050565b60208152600060018060a01b03808451166020840152806020850151166040840152506040830151606083015260608301516080830152608083015160a083015260a083015161074360c08401826001600160a01b03169052565b5060c08301516001600160a01b03811660e08401525060e0830151610100838101526103946101208401826106bc565b60008251610785818460208701610698565b919091019291505056fea26469706673582212203dc3a7acc4d0032deec8d1362507fe450e212ce67a46c21f1d336f0d17ca6d7e64736f6c63430008130033000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c99
Deployed Bytecode
0x6080604052600436106100295760003560e01c806321e9d05b1461002e578063c472d3e114610043575b600080fd5b61004161003c36600461054d565b610056565b005b610041610051366004610610565b610092565b805160005b8181101561008d5761008583828151811061007857610078610645565b602002602001015161009e565b60010161005b565b505050565b61009b8161009e565b50565b60a081015160408201516001600160a01b0382161590600003610135578061012d576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610104573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610128919061065b565b61012f565b475b60408401525b826040015160000361015a57604051630690709160e41b815260040160405180910390fd5b806101825761016f82846000015160006102ba565b61018282846000015185604001516102ba565b60208301516040516363cd755760e11b81526001600160a01b0391821660048201526000917f000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c99169063c79aeaae90602401602060405180830381865afa1580156101f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102149190610674565b905080826102785761027281826001600160a01b03166353ef91208860405160240161024091906106e8565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610317565b5061029e565b61029c81826001600160a01b031663e697fa538860405160240161024091906106e8565b505b826102b3576102b384866000015160006102ba565b5050505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061031157604051633e3f8f7360e01b815260040160405180910390fd5b50505050565b6060600080846001600160a01b0316846040516103349190610773565b600060405180830381855af49150503d806000811461036f576040519150601f19603f3d011682016040523d82523d6000602084013e610374565b606091505b50915091508161039457805160000361038c57600080fd5b805181602001fd5b949350505050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156103d6576103d661039c565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156104055761040561039c565b604052919050565b6001600160a01b038116811461009b57600080fd5b803561042d8161040d565b919050565b600082601f83011261044357600080fd5b813567ffffffffffffffff81111561045d5761045d61039c565b610470601f8201601f19166020016103dc565b81815284602083860101111561048557600080fd5b816020850160208301376000918101602001919091529392505050565b600061010082840312156104b557600080fd5b6104bd6103b2565b90506104c882610422565b81526104d660208301610422565b602082015260408201356040820152606082013560608201526080820135608082015261050560a08301610422565b60a082015261051660c08301610422565b60c082015260e082013567ffffffffffffffff81111561053557600080fd5b61054184828501610432565b60e08301525092915050565b6000602080838503121561056057600080fd5b823567ffffffffffffffff8082111561057857600080fd5b818501915085601f83011261058c57600080fd5b81358181111561059e5761059e61039c565b8060051b6105ad8582016103dc565b91825283810185019185810190898411156105c757600080fd5b86860192505b83831015610603578235858111156105e55760008081fd5b6105f38b89838a01016104a2565b83525091860191908601906105cd565b9998505050505050505050565b60006020828403121561062257600080fd5b813567ffffffffffffffff81111561063957600080fd5b610394848285016104a2565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561066d57600080fd5b5051919050565b60006020828403121561068657600080fd5b81516106918161040d565b9392505050565b60005b838110156106b357818101518382015260200161069b565b50506000910152565b600081518084526106d4816020860160208601610698565b601f01601f19169290920160200192915050565b60208152600060018060a01b03808451166020840152806020850151166040840152506040830151606083015260608301516080830152608083015160a083015260a083015161074360c08401826001600160a01b03169052565b5060c08301516001600160a01b03811660e08401525060e0830151610100838101526103946101208401826106bc565b60008251610785818460208701610698565b919091019291505056fea26469706673582212203dc3a7acc4d0032deec8d1362507fe450e212ce67a46c21f1d336f0d17ca6d7e64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c99
-----Decoded View---------------
Arg [0] : connectorRegistry_ (address): 0xc6013E57a0811C7111A8fB07ACd2E248D9489C99
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000c6013e57a0811c7111a8fb07acd2e248d9489c99
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.