Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 17826165 | 483 days ago | IN | 0 ETH | 0.01594119 |
Loading...
Loading
Contract Name:
BalancerV2BoostedPortal
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/// SPDX-License-Identifier: GPL-3.0 /// Copyright (C) 2023 Portals.fi /// @author Portals.fi /// @notice This contract adds or removes liquidity to or from Balancer V2 Boosted pools using any ERC20 token or the network token. /// @dev This contract is intended to be consumed via a multicall contract and as such omits various checks /// including slippage and does not return the quantity of tokens acquired. These checks should be handled /// by the caller pragma solidity 0.8.19; import { ERC20 } from "solmate/tokens/ERC20.sol"; import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol"; import { Owned } from "solmate/auth/Owned.sol"; import { Pausable } from "openzeppelin-contracts/security/Pausable.sol"; import { IBalancerVault } from "./interface/IBalancerVault.sol"; contract BalancerV2BoostedPortal is Owned, Pausable { using SafeTransferLib for address; using SafeTransferLib for ERC20; constructor(address admin) Owned(admin) { } /// @notice Add or remove liquidity to/from Balancer V2 boosted pools with/to network tokens/ERC20 tokens /// @param inputToken The ERC20 token address to spend (address(0) if network token) /// @param inputAmount The quantity of inputToken to Portal in /// @param outputToken The ERC20 token address to receive (address(0) if network token) /// @param vault The Balancer V2 like vault to be used for adding or removing liquidity /// @param poolId The ID of the pool /// @param recipient The recipient of the outputToken function portal( address inputToken, uint256 inputAmount, address outputToken, address vault, bytes32 poolId, address recipient ) external whenNotPaused { uint256 amount = _transferFromCaller(inputToken, inputAmount); _approve(inputToken, vault); IBalancerVault(vault).swap( IBalancerVault.SingleSwap({ poolId: poolId, kind: IBalancerVault.SwapKind.GIVEN_IN, assetIn: inputToken, assetOut: outputToken, amount: amount, userData: "" }), IBalancerVault.FundManagement({ sender: address(this), fromInternalBalance: false, recipient: payable(recipient), toInternalBalance: false }), 0, 0xf000000000000000000000000000000000000000000000000000000000000000 ); } /// @notice Transfers tokens or the network token from the caller to this contract /// @param token The address of the token to transfer (address(0) if network token) /// @param quantity The quantity of tokens to transfer from the caller /// @return The quantity of tokens or network tokens transferred from the caller to this contract function _transferFromCaller(address token, uint256 quantity) internal virtual returns (uint256) { if (token == address(0)) { require(msg.value != 0, "Invalid msg.value"); return msg.value; } require( quantity != 0 && msg.value == 0, "Invalid quantity or msg.value" ); ERC20(token).safeTransferFrom( msg.sender, address(this), quantity ); return quantity; } /// @notice Approve a token for spending with infinite allowance /// @param token The ERC20 token to approve /// @param spender The spender of the token function _approve(address token, address spender) internal { ERC20 _token = ERC20(token); if (_token.allowance(address(this), spender) == 0) { _token.safeApprove(spender, type(uint256).max); } } /// @dev Pause the contract function pause() external onlyOwner { _pause(); } /// @dev Unpause the contract function unpause() external onlyOwner { _unpause(); } /// @notice Recovers stuck tokens /// @param tokenAddress The address of the token to recover (address(0) if ETH) /// @param tokenAmount The quantity of tokens to recover /// @param to The address to send the recovered tokens to function recoverToken( address tokenAddress, uint256 tokenAmount, address to ) external onlyOwner { if (tokenAddress == address(0)) { to.safeTransferETH(tokenAmount); } else { ERC20(tokenAddress).safeTransfer(to, tokenAmount); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @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 { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), 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) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), 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) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), 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) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; interface IBalancerVault { /** * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized * Pool shares. * * If the caller is not `sender`, it must be an authorized relayer for them. * * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces * these maximums. * * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent * back to the caller (not the sender, which is important for relayers). * * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final * `assets` array might not be sorted. Pools with no registered tokens cannot be joined. * * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be * withdrawn from Internal Balance: attempting to do so will trigger a revert. * * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement * their own custom logic. This typically requires additional information from the user (such as the expected number * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed * directly to the Pool's contract, as is `recipient`. * * Emits a `PoolBalanceChanged` event. */ function joinPool( bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request ) external payable; struct JoinPoolRequest { address[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } /** * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see * `getPoolTokenInfo`). * * If the caller is not `sender`, it must be an authorized relayer for them. * * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault: * it just enforces these minimums. * * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit. * * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited. * * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise, * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to * do so will trigger a revert. * * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the * `tokens` array. This array must match the Pool's registered tokens. * * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement * their own custom logic. This typically requires additional information from the user (such as the expected number * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and * passed directly to the Pool's contract. * * Emits a `PoolBalanceChanged` event. */ function exitPool( bytes32 poolId, address sender, address payable recipient, ExitPoolRequest memory request ) external; struct ExitPoolRequest { address[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } function getPoolTokens(bytes32 poolId) external view returns ( address[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock ); /** * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the * `recipient` account. * * If the caller is not `sender`, it must be an authorized relayer for them. * * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20 * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender` * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of * `joinPool`. * * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of * transferred. This matches the behavior of `exitPool`. * * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a * revert. */ struct FundManagement { address sender; bool fromInternalBalance; address payable recipient; bool toInternalBalance; } /** * @dev Performs a swap with a single Pool. * * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens * taken from the Pool, which must be greater than or equal to `limit`. * * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens * sent to the Pool, which must be less than or equal to `limit`. * * Internal Balance usage and the recipient are determined by the `funds` struct. * * Emits a `Swap` event. */ function swap( SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline ) external payable returns (uint256); enum SwapKind { GIVEN_IN, GIVEN_OUT } /** * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on * the `kind` value. * * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address). * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault. * * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be * used to extend swap behavior. */ struct SingleSwap { bytes32 poolId; SwapKind kind; address assetIn; address assetOut; uint256 amount; bytes userData; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "solidity-stringutils/=lib/surl/lib/solidity-stringutils/", "solmate/=lib/solmate/src/", "surl/=lib/surl/src/", "lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/", "lib/openzeppelin-contracts:ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "lib/openzeppelin-contracts:erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "lib/openzeppelin-contracts:forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/", "lib/openzeppelin-contracts:openzeppelin/=lib/openzeppelin-contracts/contracts/", "lib/solmate:ds-test/=lib/solmate/lib/ds-test/src/", "lib/surl:ds-test/=lib/surl/lib/forge-std/lib/ds-test/src/", "lib/surl:forge-std/=lib/surl/lib/forge-std/src/", "lib/surl:solidity-stringutils/=lib/surl/lib/solidity-stringutils/src/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"}],"name":"portal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"recoverToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50604051610eff380380610eff83398101604081905261002f9161008b565b600080546001600160a01b0319166001600160a01b03831690811782556040518392907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350506000805460ff60a01b191690556100bb565b60006020828403121561009d57600080fd5b81516001600160a01b03811681146100b457600080fd5b9392505050565b610e35806100ca6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80638da5cb5b1161005b5780638da5cb5b146100c7578063d04323c51461010c578063e7f46bb11461011f578063f2fde38b1461013257600080fd5b80633f4ba83a146100825780635c975abb1461008c5780638456cb59146100bf575b600080fd5b61008a610145565b005b60005474010000000000000000000000000000000000000000900460ff1660405190151581526020015b60405180910390f35b61008a6101bb565b6000546100e79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b6565b61008a61011a366004610b6f565b61022a565b61008a61012d366004610bab565b6102f2565b61008a610140366004610c11565b61048a565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101b15760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6101b9610561565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102225760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016101a8565b6101b96105de565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102915760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016101a8565b73ffffffffffffffffffffffffffffffffffffffff83166102d1576102cc73ffffffffffffffffffffffffffffffffffffffff82168361064d565b505050565b6102cc73ffffffffffffffffffffffffffffffffffffffff841682846106a8565b6102fa61074d565b600061030687876107b8565b905061031287856108b0565b8373ffffffffffffffffffffffffffffffffffffffff166352bbbe296040518060c001604052808681526020016000600181111561035257610352610c33565b81526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018481526020016040518060200160405280600081525081525060405180608001604052803073ffffffffffffffffffffffffffffffffffffffff1681526020016000151581526020018673ffffffffffffffffffffffffffffffffffffffff1681526020016000151581525060007ff0000000000000000000000000000000000000000000000000000000000000006040518563ffffffff1660e01b815260040161043d9493929190610cc6565b6020604051808303816000875af115801561045c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104809190610de6565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104f15760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016101a8565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b610569610991565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b6105e661074d565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586105b43390565b600080600080600085875af19050806102cc5760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016101a8565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806107475760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016101a8565b50505050565b60005474010000000000000000000000000000000000000000900460ff16156101b95760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016101a8565b600073ffffffffffffffffffffffffffffffffffffffff831661082c57346000036108255760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964206d73672e76616c756500000000000000000000000000000060448201526064016101a8565b50346108aa565b8115801590610839575034155b6108855760405162461bcd60e51b815260206004820152601d60248201527f496e76616c6964207175616e74697479206f72206d73672e76616c756500000060448201526064016101a8565b6108a773ffffffffffffffffffffffffffffffffffffffff84163330856109fb565b50805b92915050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff828116602483015283919082169063dd62ed3e90604401602060405180830381865afa158015610925573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109499190610de6565b6000036102cc576102cc73ffffffffffffffffffffffffffffffffffffffff8216837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610aa7565b60005474010000000000000000000000000000000000000000900460ff166101b95760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016101a8565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610aa05760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016101a8565b5050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806107475760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c454400000000000000000000000000000000000060448201526064016101a8565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b6a57600080fd5b919050565b600080600060608486031215610b8457600080fd5b610b8d84610b46565b925060208401359150610ba260408501610b46565b90509250925092565b60008060008060008060c08789031215610bc457600080fd5b610bcd87610b46565b955060208701359450610be260408801610b46565b9350610bf060608801610b46565b925060808701359150610c0560a08801610b46565b90509295509295509295565b600060208284031215610c2357600080fd5b610c2c82610b46565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000815180845260005b81811015610c8857602081850181015186830182015201610c6c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60e08152845160e08201526000602086015160028110610d0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b610100830152604086015173ffffffffffffffffffffffffffffffffffffffff166101208301526060860151610d5e61014084018273ffffffffffffffffffffffffffffffffffffffff169052565b50608086015161016083015260a086015160c0610180840152610d856101a0840182610c62565b915050610dd4602083018673ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b60a082019390935260c0015292915050565b600060208284031215610df857600080fd5b505191905056fea26469706673582212203ae0545f6d7fd213a850a7828eb790b31863fb2e3e217b8cb2dee25d275dd38664736f6c634300081300330000000000000000000000007cfecfba73d62125f2eef82a0e0454e4000935be
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80638da5cb5b1161005b5780638da5cb5b146100c7578063d04323c51461010c578063e7f46bb11461011f578063f2fde38b1461013257600080fd5b80633f4ba83a146100825780635c975abb1461008c5780638456cb59146100bf575b600080fd5b61008a610145565b005b60005474010000000000000000000000000000000000000000900460ff1660405190151581526020015b60405180910390f35b61008a6101bb565b6000546100e79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b6565b61008a61011a366004610b6f565b61022a565b61008a61012d366004610bab565b6102f2565b61008a610140366004610c11565b61048a565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101b15760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6101b9610561565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102225760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016101a8565b6101b96105de565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102915760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016101a8565b73ffffffffffffffffffffffffffffffffffffffff83166102d1576102cc73ffffffffffffffffffffffffffffffffffffffff82168361064d565b505050565b6102cc73ffffffffffffffffffffffffffffffffffffffff841682846106a8565b6102fa61074d565b600061030687876107b8565b905061031287856108b0565b8373ffffffffffffffffffffffffffffffffffffffff166352bbbe296040518060c001604052808681526020016000600181111561035257610352610c33565b81526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018481526020016040518060200160405280600081525081525060405180608001604052803073ffffffffffffffffffffffffffffffffffffffff1681526020016000151581526020018673ffffffffffffffffffffffffffffffffffffffff1681526020016000151581525060007ff0000000000000000000000000000000000000000000000000000000000000006040518563ffffffff1660e01b815260040161043d9493929190610cc6565b6020604051808303816000875af115801561045c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104809190610de6565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104f15760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016101a8565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b610569610991565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b6105e661074d565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586105b43390565b600080600080600085875af19050806102cc5760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016101a8565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806107475760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016101a8565b50505050565b60005474010000000000000000000000000000000000000000900460ff16156101b95760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016101a8565b600073ffffffffffffffffffffffffffffffffffffffff831661082c57346000036108255760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964206d73672e76616c756500000000000000000000000000000060448201526064016101a8565b50346108aa565b8115801590610839575034155b6108855760405162461bcd60e51b815260206004820152601d60248201527f496e76616c6964207175616e74697479206f72206d73672e76616c756500000060448201526064016101a8565b6108a773ffffffffffffffffffffffffffffffffffffffff84163330856109fb565b50805b92915050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff828116602483015283919082169063dd62ed3e90604401602060405180830381865afa158015610925573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109499190610de6565b6000036102cc576102cc73ffffffffffffffffffffffffffffffffffffffff8216837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610aa7565b60005474010000000000000000000000000000000000000000900460ff166101b95760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016101a8565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610aa05760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064016101a8565b5050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806107475760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c454400000000000000000000000000000000000060448201526064016101a8565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b6a57600080fd5b919050565b600080600060608486031215610b8457600080fd5b610b8d84610b46565b925060208401359150610ba260408501610b46565b90509250925092565b60008060008060008060c08789031215610bc457600080fd5b610bcd87610b46565b955060208701359450610be260408801610b46565b9350610bf060608801610b46565b925060808701359150610c0560a08801610b46565b90509295509295509295565b600060208284031215610c2357600080fd5b610c2c82610b46565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000815180845260005b81811015610c8857602081850181015186830182015201610c6c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60e08152845160e08201526000602086015160028110610d0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b610100830152604086015173ffffffffffffffffffffffffffffffffffffffff166101208301526060860151610d5e61014084018273ffffffffffffffffffffffffffffffffffffffff169052565b50608086015161016083015260a086015160c0610180840152610d856101a0840182610c62565b915050610dd4602083018673ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b60a082019390935260c0015292915050565b600060208284031215610df857600080fd5b505191905056fea26469706673582212203ae0545f6d7fd213a850a7828eb790b31863fb2e3e217b8cb2dee25d275dd38664736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007cfecfba73d62125f2eef82a0e0454e4000935be
-----Decoded View---------------
Arg [0] : admin (address): 0x7cFecFBA73D62125F2eef82A0E0454e4000935bE
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007cfecfba73d62125f2eef82a0e0454e4000935be
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.