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 | 17609014 | 510 days ago | IN | 0 ETH | 0.01599409 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
BalancerV2Portal
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 like pools using any ERC20 token or the network token. /// @note 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 BalancerV2Portal is Owned, Pausable { using SafeTransferLib for address; using SafeTransferLib for ERC20; constructor(address admin) Owned(admin) { } /// @notice Add liquidity to Balancer V2 like pools with 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 vault The Balancer V2 like vault to be used for adding liquidity /// @param poolId The ID of the pool to add liquidity to /// @param assets The assets in the pool /// @param index The index of the asset to add /// @param recipient The recipient of the liquidity tokens function portalIn( address inputToken, uint256 inputAmount, address vault, bytes32 poolId, address[] calldata assets, uint256 index, address recipient ) external payable whenNotPaused { uint256 amount = _transferFromCaller(inputToken, inputAmount); uint256[] memory maxAmountsIn = new uint256[](assets.length); maxAmountsIn[index] = amount; bytes memory userData = abi.encode(1, maxAmountsIn, 0); _approve(inputToken, vault); IBalancerVault(vault).joinPool( poolId, address(this), recipient, IBalancerVault.JoinPoolRequest({ assets: assets, maxAmountsIn: maxAmountsIn, userData: userData, fromInternalBalance: false }) ); } /// @notice Remove liquidity from Balancer V2 like pools into network tokens/ERC20 tokens /// @param inputToken The Balancer V2 like pool address (i.e. the LP token address) /// @param inputAmount The quantity of inputToken to Portal out /// @param vault The Balancer V2 like vault to be used for removing liquidity /// @param poolId The ID of the pool to remove liquidity from /// @param assets The assets in the pool /// @param index The index of the asset to remove /// @param recipient The recipient of the withdrawn tokens function portalOut( address inputToken, uint256 inputAmount, address vault, bytes32 poolId, address[] calldata assets, uint256 index, address payable recipient ) external payable whenNotPaused { uint256 amount = _transferFromCaller(inputToken, inputAmount); uint256[] memory minAmountsOut = new uint256[](assets.length); bytes memory userData = abi.encode(0, amount, index); _approve(inputToken, address(vault)); IBalancerVault(vault).exitPool( poolId, address(this), recipient, IBalancerVault.ExitPoolRequest({ assets: assets, minAmountsOut: minAmountsOut, userData: userData, toInternalBalance: false }) ); } /// @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); } } receive() 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: 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/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "solidity-stringutils/=lib/surl/lib/solidity-stringutils/", "solmate/=lib/solmate/src/", "surl/=lib/surl/src/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "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":"vault","type":"address"},{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"portalIn","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"name":"portalOut","outputs":[],"stateMutability":"payable","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"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516111c63803806111c683398101604081905261002f9161008b565b600080546001600160a01b0319166001600160a01b03831690811782556040518392907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350506000805460ff60a01b191690556100bb565b60006020828403121561009d57600080fd5b81516001600160a01b03811681146100b457600080fd5b9392505050565b6110fc806100ca6000396000f3fe60806040526004361061007f5760003560e01c80638da5cb5b1161004e5780638da5cb5b1461010a578063b98f8d151461015c578063d04323c51461016f578063f2fde38b1461018f57600080fd5b80633f4ba83a1461008b5780635c975abb146100a257806366b47db3146100e25780638456cb59146100f557600080fd5b3661008657005b600080fd5b34801561009757600080fd5b506100a06101af565b005b3480156100ae57600080fd5b5060005474010000000000000000000000000000000000000000900460ff1660405190151581526020015b60405180910390f35b6100a06100f0366004610d67565b610225565b34801561010157600080fd5b506100a06103c2565b34801561011657600080fd5b506000546101379073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d9565b6100a061016a366004610d67565b610431565b34801561017b57600080fd5b506100a061018a366004610e00565b610572565b34801561019b57600080fd5b506100a06101aa366004610e42565b61063a565b60005473ffffffffffffffffffffffffffffffffffffffff16331461021b5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b610223610711565b565b61022d61078e565b600061023989896107f9565b905060008467ffffffffffffffff81111561025657610256610e66565b60405190808252806020026020018201604052801561027f578160200160208202803683370190505b5090508181858151811061029557610295610e95565b602002602001018181525050600060018260006040516020016102ba93929190610ec4565b60405160208183030381529060405290506102d58b8a6108f1565b8873ffffffffffffffffffffffffffffffffffffffff1663b95cac2889308760405180608001604052808d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505050602082018a905260408083018a9052606090920152517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526103839493929190600401611064565b600060405180830381600087803b15801561039d57600080fd5b505af11580156103b1573d6000803e3d6000fd5b505050505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104295760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610212565b6102236109d2565b61043961078e565b600061044589896107f9565b905060008467ffffffffffffffff81111561046257610462610e66565b60405190808252806020026020018201604052801561048b578160200160208202803683370190505b50604080516000602082015280820185905260608082018890528251808303909101815260809091019091529091506104c48b8a6108f1565b8873ffffffffffffffffffffffffffffffffffffffff16638bdb391389308760405180608001604052808d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505050602082018a905260408083018a9052606090920152517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526103839493929190600401611064565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105d95760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610212565b73ffffffffffffffffffffffffffffffffffffffff83166106195761061473ffffffffffffffffffffffffffffffffffffffff821683610a41565b505050565b61061473ffffffffffffffffffffffffffffffffffffffff84168284610a9c565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a15760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610212565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b610719610b41565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60005474010000000000000000000000000000000000000000900460ff16156102235760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610212565b600073ffffffffffffffffffffffffffffffffffffffff831661086d57346000036108665760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964206d73672e76616c75650000000000000000000000000000006044820152606401610212565b50346108eb565b811580159061087a575034155b6108c65760405162461bcd60e51b815260206004820152601d60248201527f496e76616c6964207175616e74697479206f72206d73672e76616c75650000006044820152606401610212565b6108e873ffffffffffffffffffffffffffffffffffffffff8416333085610bab565b50805b92915050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff828116602483015283919082169063dd62ed3e90604401602060405180830381865afa158015610966573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098a91906110ad565b6000036106145761061473ffffffffffffffffffffffffffffffffffffffff8216837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610c57565b6109da61078e565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586107643390565b600080600080600085875af19050806106145760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610212565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610b3b5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610212565b50505050565b60005474010000000000000000000000000000000000000000900460ff166102235760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610212565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610c505760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610212565b5050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610b3b5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610212565b73ffffffffffffffffffffffffffffffffffffffff81168114610d1857600080fd5b50565b60008083601f840112610d2d57600080fd5b50813567ffffffffffffffff811115610d4557600080fd5b6020830191508360208260051b8501011115610d6057600080fd5b9250929050565b60008060008060008060008060e0898b031215610d8357600080fd5b8835610d8e81610cf6565b9750602089013596506040890135610da581610cf6565b955060608901359450608089013567ffffffffffffffff811115610dc857600080fd5b610dd48b828c01610d1b565b90955093505060a0890135915060c0890135610def81610cf6565b809150509295985092959890939650565b600080600060608486031215610e1557600080fd5b8335610e2081610cf6565b9250602084013591506040840135610e3781610cf6565b809150509250925092565b600060208284031215610e5457600080fd5b8135610e5f81610cf6565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006060820160ff861683526020606081850152818651808452608086019150828801935060005b81811015610f0857845183529383019391830191600101610eec565b505080935050505060ff83166040830152949350505050565b600081518084526020808501945080840160005b83811015610f5157815187529582019590820190600101610f35565b509495945050505050565b6000815180845260005b81811015610f8257602081850181015186830182015201610f66565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b8051608080845281519084018190526000916020919082019060a0860190845b8181101561101257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610fe0565b50508285015191508581038387015261102b8183610f21565b92505050604083015184820360408601526110468282610f5c565b915050606083015161105c606086018215159052565b509392505050565b848152600073ffffffffffffffffffffffffffffffffffffffff8086166020840152808516604084015250608060608301526110a36080830184610fc0565b9695505050505050565b6000602082840312156110bf57600080fd5b505191905056fea2646970667358221220f97d3804335cc6fdb8d61532a0aa943c3ea6d8f8bec68c1e175c076b2ba7ef8b64736f6c634300081300330000000000000000000000007cfecfba73d62125f2eef82a0e0454e4000935be
Deployed Bytecode
0x60806040526004361061007f5760003560e01c80638da5cb5b1161004e5780638da5cb5b1461010a578063b98f8d151461015c578063d04323c51461016f578063f2fde38b1461018f57600080fd5b80633f4ba83a1461008b5780635c975abb146100a257806366b47db3146100e25780638456cb59146100f557600080fd5b3661008657005b600080fd5b34801561009757600080fd5b506100a06101af565b005b3480156100ae57600080fd5b5060005474010000000000000000000000000000000000000000900460ff1660405190151581526020015b60405180910390f35b6100a06100f0366004610d67565b610225565b34801561010157600080fd5b506100a06103c2565b34801561011657600080fd5b506000546101379073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d9565b6100a061016a366004610d67565b610431565b34801561017b57600080fd5b506100a061018a366004610e00565b610572565b34801561019b57600080fd5b506100a06101aa366004610e42565b61063a565b60005473ffffffffffffffffffffffffffffffffffffffff16331461021b5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b610223610711565b565b61022d61078e565b600061023989896107f9565b905060008467ffffffffffffffff81111561025657610256610e66565b60405190808252806020026020018201604052801561027f578160200160208202803683370190505b5090508181858151811061029557610295610e95565b602002602001018181525050600060018260006040516020016102ba93929190610ec4565b60405160208183030381529060405290506102d58b8a6108f1565b8873ffffffffffffffffffffffffffffffffffffffff1663b95cac2889308760405180608001604052808d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505050602082018a905260408083018a9052606090920152517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526103839493929190600401611064565b600060405180830381600087803b15801561039d57600080fd5b505af11580156103b1573d6000803e3d6000fd5b505050505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104295760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610212565b6102236109d2565b61043961078e565b600061044589896107f9565b905060008467ffffffffffffffff81111561046257610462610e66565b60405190808252806020026020018201604052801561048b578160200160208202803683370190505b50604080516000602082015280820185905260608082018890528251808303909101815260809091019091529091506104c48b8a6108f1565b8873ffffffffffffffffffffffffffffffffffffffff16638bdb391389308760405180608001604052808d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250938552505050602082018a905260408083018a9052606090920152517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526103839493929190600401611064565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105d95760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610212565b73ffffffffffffffffffffffffffffffffffffffff83166106195761061473ffffffffffffffffffffffffffffffffffffffff821683610a41565b505050565b61061473ffffffffffffffffffffffffffffffffffffffff84168284610a9c565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a15760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610212565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b610719610b41565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60005474010000000000000000000000000000000000000000900460ff16156102235760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610212565b600073ffffffffffffffffffffffffffffffffffffffff831661086d57346000036108665760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964206d73672e76616c75650000000000000000000000000000006044820152606401610212565b50346108eb565b811580159061087a575034155b6108c65760405162461bcd60e51b815260206004820152601d60248201527f496e76616c6964207175616e74697479206f72206d73672e76616c75650000006044820152606401610212565b6108e873ffffffffffffffffffffffffffffffffffffffff8416333085610bab565b50805b92915050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff828116602483015283919082169063dd62ed3e90604401602060405180830381865afa158015610966573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098a91906110ad565b6000036106145761061473ffffffffffffffffffffffffffffffffffffffff8216837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610c57565b6109da61078e565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586107643390565b600080600080600085875af19050806106145760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610212565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610b3b5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610212565b50505050565b60005474010000000000000000000000000000000000000000900460ff166102235760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610212565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610c505760405162461bcd60e51b815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610212565b5050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610b3b5760405162461bcd60e51b815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610212565b73ffffffffffffffffffffffffffffffffffffffff81168114610d1857600080fd5b50565b60008083601f840112610d2d57600080fd5b50813567ffffffffffffffff811115610d4557600080fd5b6020830191508360208260051b8501011115610d6057600080fd5b9250929050565b60008060008060008060008060e0898b031215610d8357600080fd5b8835610d8e81610cf6565b9750602089013596506040890135610da581610cf6565b955060608901359450608089013567ffffffffffffffff811115610dc857600080fd5b610dd48b828c01610d1b565b90955093505060a0890135915060c0890135610def81610cf6565b809150509295985092959890939650565b600080600060608486031215610e1557600080fd5b8335610e2081610cf6565b9250602084013591506040840135610e3781610cf6565b809150509250925092565b600060208284031215610e5457600080fd5b8135610e5f81610cf6565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006060820160ff861683526020606081850152818651808452608086019150828801935060005b81811015610f0857845183529383019391830191600101610eec565b505080935050505060ff83166040830152949350505050565b600081518084526020808501945080840160005b83811015610f5157815187529582019590820190600101610f35565b509495945050505050565b6000815180845260005b81811015610f8257602081850181015186830182015201610f66565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b8051608080845281519084018190526000916020919082019060a0860190845b8181101561101257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610fe0565b50508285015191508581038387015261102b8183610f21565b92505050604083015184820360408601526110468282610f5c565b915050606083015161105c606086018215159052565b509392505050565b848152600073ffffffffffffffffffffffffffffffffffffffff8086166020840152808516604084015250608060608301526110a36080830184610fc0565b9695505050505050565b6000602082840312156110bf57600080fd5b505191905056fea2646970667358221220f97d3804335cc6fdb8d61532a0aa943c3ea6d8f8bec68c1e175c076b2ba7ef8b64736f6c63430008130033
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.