Source Code
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Receive Eth From... | 19618016 | 681 days ago | 0.06151747 ETH | ||||
| Transfer | 19618016 | 681 days ago | 0.06151747 ETH | ||||
| Receive Eth From... | 19225460 | 736 days ago | 0.023893 ETH | ||||
| Transfer | 19225460 | 736 days ago | 0.023893 ETH | ||||
| Receive Eth From... | 19221395 | 736 days ago | 0.02689468 ETH | ||||
| Transfer | 19221395 | 736 days ago | 0.02689468 ETH | ||||
| Receive Eth From... | 19214252 | 737 days ago | 0.21552406 ETH | ||||
| Transfer | 19214252 | 737 days ago | 0.21552406 ETH | ||||
| Receive Eth From... | 19013412 | 765 days ago | 0.17677402 ETH | ||||
| Transfer | 19013412 | 765 days ago | 0.17677402 ETH | ||||
| Receive Eth From... | 19012014 | 766 days ago | 0.21979017 ETH | ||||
| Transfer | 19012014 | 766 days ago | 0.21979017 ETH | ||||
| Receive Eth From... | 19006236 | 767 days ago | 0.3127826 ETH | ||||
| Transfer | 19006236 | 767 days ago | 0.3127826 ETH | ||||
| Receive Eth From... | 18906564 | 781 days ago | 0.16512716 ETH | ||||
| Transfer | 18906564 | 781 days ago | 0.16512716 ETH | ||||
| Receive Eth From... | 18824660 | 792 days ago | 0.241923 ETH | ||||
| Transfer | 18824660 | 792 days ago | 0.241923 ETH | ||||
| Receive Eth From... | 18766011 | 800 days ago | 0.40408633 ETH | ||||
| Transfer | 18766011 | 800 days ago | 0.40408633 ETH | ||||
| Receive Eth From... | 18708201 | 808 days ago | 0.26337212 ETH | ||||
| Transfer | 18708201 | 808 days ago | 0.26337212 ETH | ||||
| Receive Eth From... | 18663523 | 815 days ago | 0.36387866 ETH | ||||
| Transfer | 18663523 | 815 days ago | 0.36387866 ETH | ||||
| Receive Eth From... | 18604583 | 823 days ago | 0.19227029 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EulerRedemptionBridge
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 100000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec.
pragma solidity >=0.8.4;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IRollupProcessor} from "rollup-encoder/interfaces/IRollupProcessor.sol";
import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol";
import {BridgeBase} from "../base/BridgeBase.sol";
import {ErrorLib} from "../base/ErrorLib.sol";
import {IWETH} from "../../interfaces/IWETH.sol";
import {ISwapRouter} from "../../interfaces/uniswapv3/ISwapRouter.sol";
import {IVault, IAsset, PoolSpecialization} from "../../interfaces/element/IVault.sol";
interface IMigrator {
function migrate(uint256 _amount, bytes32 _acceptanceToken) external returns (uint256, uint256, uint256);
function ERC4626Token() external view returns (address);
}
contract EulerRedemptionBridge is BridgeBase {
using SafeERC20 for IERC20;
using SafeERC20 for IERC4626;
error SlippageExceeded();
IWETH public constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 public constant DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);
IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
IERC20 public constant WSTETH = IERC20(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0);
IERC4626 public constant WEWETH = IERC4626(0x3c66B18F67CA6C1A71F829E2F6a0c987f97462d0);
IERC4626 public constant WEDAI = IERC4626(0x4169Df1B7820702f566cc10938DA51F6F597d264);
IERC4626 public constant WEWSTETH = IERC4626(0x60897720AA966452e8706e74296B018990aEc527);
bytes32 public constant TERMS_AND_CONDITIONS_HASH =
0x427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996;
ISwapRouter public constant ROUTER = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
IVault public constant BALANCER = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
bytes32 public constant BALANCER_WSTETH_POOLID = 0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080;
IMigrator public immutable WETH_MIGRATOR;
IMigrator public immutable DAI_MIGRATOR;
IMigrator public immutable WSTETH_MIGRATOR;
constructor(address _rollupProcessor, address _wethMigrator, address _daiMigrator, address _wstethMigrator)
BridgeBase(_rollupProcessor)
{
WETH_MIGRATOR = IMigrator(_wethMigrator);
DAI_MIGRATOR = IMigrator(_daiMigrator);
WSTETH_MIGRATOR = IMigrator(_wstethMigrator);
IERC20(WETH_MIGRATOR.ERC4626Token()).approve(address(WETH_MIGRATOR), type(uint256).max);
IERC20(DAI_MIGRATOR.ERC4626Token()).approve(address(DAI_MIGRATOR), type(uint256).max);
IERC20(WSTETH_MIGRATOR.ERC4626Token()).approve(address(WSTETH_MIGRATOR), type(uint256).max);
WETH.approve(address(BALANCER), type(uint256).max);
WETH.approve(address(ROUTER), type(uint256).max);
DAI.approve(address(ROUTER), type(uint256).max);
USDC.approve(address(ROUTER), type(uint256).max);
DAI.approve(address(ROLLUP_PROCESSOR), type(uint256).max);
WSTETH.approve(address(ROLLUP_PROCESSOR), type(uint256).max);
}
receive() external payable {}
/**
* @notice Redeems shares of Euler ERC4626 vaults for underlying assets
* following the redemption scheme. Will take the assets received and swap it into
* the expected underlying.
* @param _inputAssetA - The input asset to redeem
* @param _outputAssetA - The output asset to receive
* @param _totalInputValue - The total amount of input asset to redeem
* @param _interactionNonce - The nonce of the interaction
* @param _auxData - The aux data of the interaction (minAmountPerFullShare)
* @return outputValueA - The amount of output asset received
*/
function convert(
AztecTypes.AztecAsset calldata _inputAssetA,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata _outputAssetA,
AztecTypes.AztecAsset calldata,
uint256 _totalInputValue,
uint256 _interactionNonce,
uint64 _auxData,
address
) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) {
if (_inputAssetA.erc20Address == address(WEWETH)) {
return _exitWeweth(_totalInputValue, _outputAssetA.erc20Address, _interactionNonce, _auxData);
} else if (_inputAssetA.erc20Address == address(WEDAI)) {
return _exitDai(_totalInputValue, _outputAssetA.erc20Address, _auxData);
} else if (_inputAssetA.erc20Address == address(WEWSTETH)) {
return _exitWsteth(_totalInputValue, _outputAssetA.erc20Address, _auxData);
} else {
revert ErrorLib.InvalidInputA();
}
}
/**
* @notice Redeems shares of WEWETH vault for weth, dai, usdc
* swaps assets to Eth
* @param _totalInputValue - The total amount of input asset to redeem
* @param _outputAssetA - The output asset to receive
* @param _interactionNonce - The nonce of the interaction
* @param _auxData - The aux data of the interaction (minAmountPerFullShare)
* @return outputValueA - The amount of output asset received
*/
function _exitWeweth(uint256 _totalInputValue, address _outputAssetA, uint256 _interactionNonce, uint64 _auxData)
internal
returns (uint256 outputValueA, uint256, bool)
{
if (_outputAssetA != address(0)) {
revert ErrorLib.InvalidOutputA();
}
// Migrate the asset.
(uint256 wethAmount, uint256 daiAmount, uint256 usdcAmount) =
WETH_MIGRATOR.migrate(_totalInputValue, _acceptanceToken());
// Swap dai for usdc on uniswap
{
if (daiAmount > 0) {
bytes memory path = abi.encodePacked(address(DAI), uint24(100), address(USDC));
usdcAmount += ROUTER.exactInput(
ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: daiAmount,
amountOutMinimum: 0
})
);
}
}
// Swap usdc to weth
{
if (usdcAmount > 0) {
bytes memory path = abi.encodePacked(address(USDC), uint24(500), address(WETH));
wethAmount += ROUTER.exactInput(
ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: usdcAmount,
amountOutMinimum: 0
})
);
}
}
// @todo slippage aux could be 1e16 precision if there are very high interest amounts.
uint256 minExpected = _totalInputValue * _auxData / 1e18;
if (wethAmount < minExpected) {
revert SlippageExceeded();
}
IWETH(WETH).withdraw(wethAmount);
IRollupProcessor(ROLLUP_PROCESSOR).receiveEthFromBridge{value: wethAmount}(_interactionNonce);
return (wethAmount, 0, false);
}
/**
* @notice Redeems shares of WEDAI vault for weth, dai, usdc
* swaps assets to Dai
* @param _totalInputValue - The total amount of input asset to redeem
* @param _outputAssetA - The output asset to receive
* @param _auxData - The aux data of the interaction (minAmountPerFullShare)
* @return outputValueA - The amount of output asset received
*/
function _exitDai(uint256 _totalInputValue, address _outputAssetA, uint64 _auxData)
internal
returns (uint256 outputValueA, uint256, bool)
{
if (_outputAssetA != address(DAI)) {
revert ErrorLib.InvalidOutputA();
}
// Migrate the asset.
(uint256 wethAmount, uint256 daiAmount, uint256 usdcAmount) =
DAI_MIGRATOR.migrate(_totalInputValue, _acceptanceToken());
// Swap weth to usdc
{
if (wethAmount > 0) {
bytes memory path = abi.encodePacked(address(WETH), uint24(500), address(USDC));
usdcAmount += ROUTER.exactInput(
ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: wethAmount,
amountOutMinimum: 0
})
);
}
}
// Swap usdc for dai on uniswap
{
if (usdcAmount > 0) {
bytes memory path = abi.encodePacked(address(USDC), uint24(100), address(DAI));
daiAmount += ROUTER.exactInput(
ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: usdcAmount,
amountOutMinimum: 0
})
);
}
}
// @todo slippage aux could be 1e16 precision if there are very high interest amounts.
uint256 minExpected = _totalInputValue * _auxData / 1e18;
if (daiAmount < minExpected) {
revert SlippageExceeded();
}
return (daiAmount, 0, false);
}
/**
* @notice Redeems shares of WEWESTETH vault for weth, dai, usdc
* swaps assets to Wsteth
* @param _totalInputValue - The total amount of input asset to redeem
* @param _outputAssetA - The output asset to receive
* @param _auxData - The aux data of the interaction (minAmountPerFullShare)
* @return outputValueA - The amount of output asset received
*/
function _exitWsteth(uint256 _totalInputValue, address _outputAssetA, uint64 _auxData)
internal
returns (uint256 outputValueA, uint256, bool)
{
if (_outputAssetA != address(WSTETH)) {
revert ErrorLib.InvalidOutputA();
}
// Migrate the asset.
(uint256 wethAmount, uint256 daiAmount, uint256 usdcAmount) =
WSTETH_MIGRATOR.migrate(_totalInputValue, _acceptanceToken());
// Swap dai for usdc on uniswap
{
if (daiAmount > 0) {
bytes memory path = abi.encodePacked(address(DAI), uint24(100), address(USDC));
usdcAmount += ROUTER.exactInput(
ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: daiAmount,
amountOutMinimum: 0
})
);
}
}
// Swap usdc to weth
{
if (usdcAmount > 0) {
bytes memory path = abi.encodePacked(address(USDC), uint24(500), address(WETH));
wethAmount += ROUTER.exactInput(
ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: block.timestamp,
amountIn: usdcAmount,
amountOutMinimum: 0
})
);
}
}
// Swap weth to wsteth
uint256 wstethBal;
{
if (wethAmount > 0) {
IVault.SingleSwap memory singleSwap = IVault.SingleSwap({
poolId: BALANCER_WSTETH_POOLID,
kind: IVault.SwapKind.GIVEN_IN,
assetIn: IAsset(address(WETH)),
assetOut: IAsset(address(WSTETH)),
amount: wethAmount,
userData: "0x00"
});
IVault.FundManagement memory fundManagement = IVault.FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(address(this)),
toInternalBalance: false
});
wstethBal = BALANCER.swap(singleSwap, fundManagement, 0, block.timestamp);
}
}
// @todo slippage aux could be 1e16 precision if there are very high interest amounts.
uint256 minExpected = _totalInputValue * _auxData / 1e18;
if (wstethBal < minExpected) {
revert SlippageExceeded();
}
return (wstethBal, 0, false);
}
/**
* @notice Computes the acceptance token for the migration.
* @return The acceptance token.
*/
function _acceptanceToken() internal view returns (bytes32) {
return keccak256(abi.encodePacked(address(this), TERMS_AND_CONDITIONS_HASH));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
import "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*
* _Available since v4.7._
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec
pragma solidity >=0.8.4;
// @dev For documentation of the functions within this interface see RollupProcessor contract
interface IRollupProcessor {
/*----------------------------------------
MUTATING FUNCTIONS
----------------------------------------*/
function pause() external;
function unpause() external;
function setRollupProvider(address _provider, bool _valid) external;
function setVerifier(address _verifier) external;
function setAllowThirdPartyContracts(bool _allowThirdPartyContracts) external;
function setDefiBridgeProxy(address _defiBridgeProxy) external;
function setSupportedAsset(address _token, uint256 _gasLimit) external;
function setSupportedBridge(address _bridge, uint256 _gasLimit) external;
function processRollup(bytes calldata _encodedProofData, bytes calldata _signatures) external;
function receiveEthFromBridge(uint256 _interactionNonce) external payable;
function approveProof(bytes32 _proofHash) external;
function depositPendingFunds(uint256 _assetId, uint256 _amount, address _owner, bytes32 _proofHash)
external
payable;
function offchainData(uint256 _rollupId, uint256 _chunk, uint256 _totalChunks, bytes calldata _offchainTxData)
external;
function processAsyncDefiInteraction(uint256 _interactionNonce) external returns (bool);
/*----------------------------------------
NON-MUTATING FUNCTIONS
----------------------------------------*/
function rollupStateHash() external view returns (bytes32);
function userPendingDeposits(uint256 _assetId, address _user) external view returns (uint256);
function defiBridgeProxy() external view returns (address);
function prevDefiInteractionsHash() external view returns (bytes32);
function paused() external view returns (bool);
function verifier() external view returns (address);
function getDataSize() external view returns (uint256);
function getPendingDefiInteractionHashesLength() external view returns (uint256);
function getDefiInteractionHashesLength() external view returns (uint256);
function getAsyncDefiInteractionHashesLength() external view returns (uint256);
function getSupportedBridge(uint256 _bridgeAddressId) external view returns (address);
function getSupportedBridgesLength() external view returns (uint256);
function getSupportedAssetsLength() external view returns (uint256);
function getSupportedAsset(uint256 _assetId) external view returns (address);
function getEscapeHatchStatus() external view returns (bool, uint256);
function assetGasLimits(uint256 _bridgeAddressId) external view returns (uint256);
function bridgeGasLimits(uint256 _bridgeAddressId) external view returns (uint256);
function allowThirdPartyContracts() external view returns (bool);
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec
pragma solidity >=0.8.4;
library AztecTypes {
enum AztecAssetType {
NOT_USED,
ETH,
ERC20,
VIRTUAL
}
struct AztecAsset {
uint256 id;
address erc20Address;
AztecAssetType assetType;
}
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec
pragma solidity >=0.8.4;
import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol";
interface IDefiBridge {
/**
* @notice A function which converts input assets to output assets.
* @param _inputAssetA A struct detailing the first input asset
* @param _inputAssetB A struct detailing the second input asset
* @param _outputAssetA A struct detailing the first output asset
* @param _outputAssetB A struct detailing the second output asset
* @param _totalInputValue An amount of input assets transferred to the bridge (Note: "total" is in the name
* because the value can represent summed/aggregated token amounts of users actions on L2)
* @param _interactionNonce A globally unique identifier of this interaction/`convert(...)` call.
* @param _auxData Bridge specific data to be passed into the bridge contract (e.g. slippage, nftID etc.)
* @return outputValueA An amount of `_outputAssetA` returned from this interaction.
* @return outputValueB An amount of `_outputAssetB` returned from this interaction.
* @return isAsync A flag indicating if the interaction is async.
* @dev This function is called from the RollupProcessor contract via the DefiBridgeProxy. Before this function is
* called _RollupProcessor_ contract will have sent you all the assets defined by the input params. This
* function is expected to convert input assets to output assets (e.g. on Uniswap) and return the amounts
* of output assets to be received by the _RollupProcessor_. If output assets are ERC20 tokens the bridge has
* to _RollupProcessor_ as a spender before the interaction is finished. If some of the output assets is ETH
* it has to be sent to _RollupProcessor_ via the `receiveEthFromBridge(uint256 _interactionNonce)` method
* inside before the `convert(...)` function call finishes.
* @dev If there are two input assets, equal amounts of both assets will be transferred to the bridge before this
* method is called.
* @dev **BOTH** output assets could be virtual but since their `assetId` is currently assigned as
* `_interactionNonce` it would simply mean that more of the same virtual asset is minted.
* @dev If this interaction is async the function has to return `(0,0 true)`. Async interaction will be finalised at
* a later time and its output assets will be returned in a `IDefiBridge.finalise(...)` call.
*
*/
function convert(
AztecTypes.AztecAsset calldata _inputAssetA,
AztecTypes.AztecAsset calldata _inputAssetB,
AztecTypes.AztecAsset calldata _outputAssetA,
AztecTypes.AztecAsset calldata _outputAssetB,
uint256 _totalInputValue,
uint256 _interactionNonce,
uint64 _auxData,
address _rollupBeneficiary
) external payable returns (uint256 outputValueA, uint256 outputValueB, bool isAsync);
/**
* @notice A function that finalises asynchronous interaction.
* @param _inputAssetA A struct detailing the first input asset
* @param _inputAssetB A struct detailing the second input asset
* @param _outputAssetA A struct detailing the first output asset
* @param _outputAssetB A struct detailing the second output asset
* @param _interactionNonce A globally unique identifier of this interaction/`convert(...)` call.
* @param _auxData Bridge specific data to be passed into the bridge contract (e.g. slippage, nftID etc.)
* @return outputValueA An amount of `_outputAssetA` returned from this interaction.
* @return outputValueB An amount of `_outputAssetB` returned from this interaction.
* @dev This function should use the `BridgeBase.onlyRollup()` modifier to ensure it can only be called from
* the `RollupProcessor.processAsyncDefiInteraction(uint256 _interactionNonce)` method.
*
*/
function finalise(
AztecTypes.AztecAsset calldata _inputAssetA,
AztecTypes.AztecAsset calldata _inputAssetB,
AztecTypes.AztecAsset calldata _outputAssetA,
AztecTypes.AztecAsset calldata _outputAssetB,
uint256 _interactionNonce,
uint64 _auxData
) external payable returns (uint256 outputValueA, uint256 outputValueB, bool interactionComplete);
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec
pragma solidity >=0.8.4;
// @dev documentation of this interface is in its implementation (Subsidy contract)
interface ISubsidy {
/**
* @notice Container for Subsidy related information
* @member available Amount of ETH remaining to be paid out
* @member gasUsage Amount of gas the interaction consumes (used to define max possible payout)
* @member minGasPerMinute Minimum amount of gas per minute the subsidizer has to subsidize
* @member gasPerMinute Amount of gas per minute the subsidizer is willing to subsidize
* @member lastUpdated Last time subsidy was paid out or funded (if not subsidy was yet claimed after funding)
*/
struct Subsidy {
uint128 available;
uint32 gasUsage;
uint32 minGasPerMinute;
uint32 gasPerMinute;
uint32 lastUpdated;
}
function setGasUsageAndMinGasPerMinute(uint256 _criteria, uint32 _gasUsage, uint32 _minGasPerMinute) external;
function setGasUsageAndMinGasPerMinute(
uint256[] calldata _criteria,
uint32[] calldata _gasUsage,
uint32[] calldata _minGasPerMinute
) external;
function registerBeneficiary(address _beneficiary) external;
function subsidize(address _bridge, uint256 _criteria, uint32 _gasPerMinute) external payable;
function topUp(address _bridge, uint256 _criteria) external payable;
function claimSubsidy(uint256 _criteria, address _beneficiary) external returns (uint256);
function withdraw(address _beneficiary) external returns (uint256);
// solhint-disable-next-line
function MIN_SUBSIDY_VALUE() external view returns (uint256);
function claimableAmount(address _beneficiary) external view returns (uint256);
function isRegistered(address _beneficiary) external view returns (bool);
function getSubsidy(address _bridge, uint256 _criteria) external view returns (Subsidy memory);
function getAccumulatedSubsidyAmount(address _bridge, uint256 _criteria) external view returns (uint256);
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec.
pragma solidity >=0.8.4;
import {IDefiBridge} from "../../aztec/interfaces/IDefiBridge.sol";
import {ISubsidy} from "../../aztec/interfaces/ISubsidy.sol";
import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol";
import {ErrorLib} from "./ErrorLib.sol";
/**
* @title BridgeBase
* @notice A base that bridges can be built upon which imports a limited set of features
* @dev Reverts `convert` with missing implementation, and `finalise` with async disabled
* @author Lasse Herskind
*/
abstract contract BridgeBase is IDefiBridge {
error MissingImplementation();
ISubsidy public constant SUBSIDY = ISubsidy(0xABc30E831B5Cc173A9Ed5941714A7845c909e7fA);
address public immutable ROLLUP_PROCESSOR;
constructor(address _rollupProcessor) {
ROLLUP_PROCESSOR = _rollupProcessor;
}
modifier onlyRollup() {
if (msg.sender != ROLLUP_PROCESSOR) {
revert ErrorLib.InvalidCaller();
}
_;
}
function convert(
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
uint256,
uint256,
uint64,
address
) external payable virtual override(IDefiBridge) returns (uint256, uint256, bool) {
revert MissingImplementation();
}
function finalise(
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
uint256,
uint64
) external payable virtual override(IDefiBridge) returns (uint256, uint256, bool) {
revert ErrorLib.AsyncDisabled();
}
/**
* @notice Computes the criteria that is passed on to the subsidy contract when claiming
* @dev Should be overridden by bridge implementation if intended to limit subsidy.
* @return The criteria to be passed along
*/
function computeCriteria(
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
AztecTypes.AztecAsset calldata,
uint64
) public view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec.
pragma solidity >=0.8.4;
library ErrorLib {
error InvalidCaller();
error InvalidInput();
error InvalidInputA();
error InvalidInputB();
error InvalidOutputA();
error InvalidOutputB();
error InvalidInputAmount();
error InvalidAuxData();
error ApproveFailed(address token);
error TransferFailed(address token);
error InvalidNonce();
error AsyncDisabled();
}// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Aztec.
pragma solidity >=0.8.4;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.4;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IAsset {
// solhint-disable-previous-line no-empty-blocks
}
enum PoolSpecialization {
GENERAL,
MINIMAL_SWAP_INFO,
TWO_TOKEN
}
interface IVault {
enum SwapKind {
GIVEN_IN,
GIVEN_OUT
}
/**
* @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);
/**
* @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;
IAsset assetIn;
IAsset assetOut;
uint256 amount;
bytes userData;
}
/**
* @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;
}
// will revert if poolId is not a registered pool
function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);
/**
* @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be
* simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.
*
* Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)
* the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it
* receives are the same that an equivalent `batchSwap` call would receive.
*
* Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.
* This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,
* approve them for the Vault, or even know a user's address.
*
* Note that this function is not 'view' (due to implementation details): the client code must explicitly execute
* eth_call instead of eth_sendTransaction.
*/
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
function queryBatchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
IAsset[] memory assets,
FundManagement memory funds
) external view returns (int256[] memory assetDeltas);
/**
* @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of
* the tokens' `balances` changed.
*
* The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all
* Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.
*
* If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same
* order as passed to `registerTokens`.
*
* Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are
* the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`
* instead.
*/
function getPoolTokens(bytes32 poolId)
external
view
returns (IERC20[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.4;
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"euler-4626-redemption/=lib/euler-4626-redemption/src/",
"euler-redemption/=lib/euler-4626-redemption/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"oz/=lib/euler-4626-redemption/lib/openzeppelin-contracts/contracts/",
"rollup-encoder/=lib/rollup-encoder/src/",
"safe-contracts/=lib/euler-4626-redemption/lib/safe-contracts/contracts/",
"safe/=lib/euler-4626-redemption/lib/safe-contracts/contracts/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 100000
},
"metadata": {
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_rollupProcessor","type":"address"},{"internalType":"address","name":"_wethMigrator","type":"address"},{"internalType":"address","name":"_daiMigrator","type":"address"},{"internalType":"address","name":"_wstethMigrator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AsyncDisabled","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidInputA","type":"error"},{"inputs":[],"name":"InvalidOutputA","type":"error"},{"inputs":[],"name":"MissingImplementation","type":"error"},{"inputs":[],"name":"SlippageExceeded","type":"error"},{"inputs":[],"name":"BALANCER","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BALANCER_WSTETH_POOLID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAI","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAI_MIGRATOR","outputs":[{"internalType":"contract IMigrator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLLUP_PROCESSOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROUTER","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBSIDY","outputs":[{"internalType":"contract ISubsidy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TERMS_AND_CONDITIONS_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEDAI","outputs":[{"internalType":"contract IERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH_MIGRATOR","outputs":[{"internalType":"contract IMigrator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEWETH","outputs":[{"internalType":"contract IERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEWSTETH","outputs":[{"internalType":"contract IERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH_MIGRATOR","outputs":[{"internalType":"contract IMigrator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"computeCriteria","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"_inputAssetA","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"_outputAssetA","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"internalType":"uint256","name":"_totalInputValue","type":"uint256"},{"internalType":"uint256","name":"_interactionNonce","type":"uint256"},{"internalType":"uint64","name":"_auxData","type":"uint64"},{"internalType":"address","name":"","type":"address"}],"name":"convert","outputs":[{"internalType":"uint256","name":"outputValueA","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"finalise","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101006040523480156200001257600080fd5b50604051620024b5380380620024b583398101604081905262000035916200068f565b6001600160a01b0380851660805283811660a081905283821660c05290821660e05260408051633498190560e01b815290516334981905916004808201926020929091908290030181865afa15801562000093573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b99190620006ec565b60a05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af11580156200010d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000133919062000711565b5060c0516001600160a01b031663349819056040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019b9190620006ec565b60c05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015620001ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000215919062000711565b5060e0516001600160a01b031663349819056040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000257573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200027d9190620006ec565b60e05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015620002d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f7919062000711565b5060405163095ea7b360e01b815273ba12222222228d8ba445958a75a0704d566bf2c86004820152600019602482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063095ea7b3906044016020604051808303816000875af115801562000366573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200038c919062000711565b5060405163095ea7b360e01b815273e592427a0aece92de3edee1f18e0157c058615646004820152600019602482015273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29063095ea7b3906044016020604051808303816000875af1158015620003fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000421919062000711565b5060405163095ea7b360e01b815273e592427a0aece92de3edee1f18e0157c0586156460048201526000196024820152736b175474e89094c44da98b954eedeac495271d0f9063095ea7b3906044016020604051808303816000875af115801562000490573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004b6919062000711565b5060405163095ea7b360e01b815273e592427a0aece92de3edee1f18e0157c058615646004820152600019602482015273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063095ea7b3906044016020604051808303816000875af115801562000525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200054b919062000711565b5060805160405163095ea7b360e01b81526001600160a01b0390911660048201526000196024820152736b175474e89094c44da98b954eedeac495271d0f9063095ea7b3906044016020604051808303816000875af1158015620005b3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005d9919062000711565b5060805160405163095ea7b360e01b81526001600160a01b0390911660048201526000196024820152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09063095ea7b3906044016020604051808303816000875af115801562000641573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000667919062000711565b505050505062000735565b80516001600160a01b03811681146200068a57600080fd5b919050565b60008060008060808587031215620006a657600080fd5b620006b18562000672565b9350620006c16020860162000672565b9250620006d16040860162000672565b9150620006e16060860162000672565b905092959194509250565b600060208284031215620006ff57600080fd5b6200070a8262000672565b9392505050565b6000602082840312156200072457600080fd5b815180151581146200070a57600080fd5b60805160a05160c05160e051611d2362000792600039600081816102e9015261123301526000818161019b0152610d37015260008181610467015261071a01526000818161036d015281816104d90152610c400152611d236000f3fe6080604052600436106101485760003560e01c8063ad5c4648116100c0578063d9fb643a11610074578063e0bab4c411610059578063e0bab4c41461042d578063e2d51a7714610455578063f8e19cb11461048957600080fd5b8063d9fb643a146103df578063dbeacd541461040757600080fd5b8063ae9467b5116100a5578063ae9467b51461035b578063aedfdaea1461038f578063bb935cbf146103b757600080fd5b8063ad5c46481461030b578063ae4175b71461033357600080fd5b806389a302711161011757806396f50b2d116100fc57806396f50b2d1461029c5780639b07d342146102c4578063a5907215146102d757600080fd5b806389a302711461023257806394d0a7431461025a57600080fd5b806326c3b515146101545780632aa6584a1461018957806332fe7b26146101e25780636508156e1461020a57600080fd5b3661014f57005b600080fd5b61016761016236600461188d565b6104bd565b6040805193845260208401929092521515908201526060015b60405180910390f35b34801561019557600080fd5b506101bd7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610180565b3480156101ee57600080fd5b506101bd73e592427a0aece92de3edee1f18e0157c0586156481565b34801561021657600080fd5b506101bd73abc30e831b5cc173a9ed5941714a7845c909e7fa81565b34801561023e57600080fd5b506101bd73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b34801561026657600080fd5b5061028e7f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d829499681565b604051908152602001610180565b3480156102a857600080fd5b506101bd73ba12222222228d8ba445958a75a0704d566bf2c881565b6101676102d236600461191f565b61068a565b3480156102e357600080fd5b506101bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561031757600080fd5b506101bd73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561033f57600080fd5b506101bd734169df1b7820702f566cc10938da51f6f597d26481565b34801561036757600080fd5b506101bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561039b57600080fd5b506101bd733c66b18f67ca6c1a71f829e2f6a0c987f97462d081565b3480156103c357600080fd5b506101bd7360897720aa966452e8706e74296b018990aec52781565b3480156103eb57600080fd5b506101bd737f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b34801561041357600080fd5b5061028e610422366004611994565b600095945050505050565b34801561043957600080fd5b506101bd736b175474e89094c44da98b954eedeac495271d0f81565b34801561046157600080fd5b506101bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561049557600080fd5b5061028e7f32296969ef14eb0c6d29669c550d4a044913023000020000000000000000008081565b600080803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610530576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b733c66b18f67ca6c1a71f829e2f6a0c987f97462d061055560408d0160208e01611a00565b73ffffffffffffffffffffffffffffffffffffffff16036105965761058b8761058460408c0160208d01611a00565b88886106c1565b92509250925061067c565b734169df1b7820702f566cc10938da51f6f597d2646105bb60408d0160208e01611a00565b73ffffffffffffffffffffffffffffffffffffffff16036105f05761058b876105ea60408c0160208d01611a00565b87610cc9565b7360897720aa966452e8706e74296b018990aec52761061560408d0160208e01611a00565b73ffffffffffffffffffffffffffffffffffffffff160361064a5761058b8761064460408c0160208d01611a00565b876111c5565b6040517fc582880b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b985098509895505050505050565b60008060006040517f26d18eab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808073ffffffffffffffffffffffffffffffffffffffff861615610713576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638277908b8b6107cd6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660208201527f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996603482015260009060540160405160208183030381529060405280519060200120905090565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016060604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190611a22565b9194509250905081156109c1576040517f6b175474e89094c44da98b954eedeac495271d0f00000000000000000000000060208201527d64000000000000000000000000000000000000000000000000000000000060348201527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018690526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916109709190600401611ab4565b6020604051808303816000875af115801561098f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b39190611b1a565b6109bd9083611b62565b9150505b8015610b30576040517fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060208201527e01f4000000000000000000000000000000000000000000000000000000000060348201527fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018590526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d5991610adf9190600401611ab4565b6020604051808303816000875af1158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b229190611b1a565b610b2c9085611b62565b9350505b6000670de0b6b3a7640000610b4f67ffffffffffffffff8a168d611b7b565b610b599190611b92565b905080841015610b95576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810185905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b158015610bfb57600080fd5b505af1158015610c0f573d6000803e3d6000fd5b50506040517f12a53623000000000000000000000000000000000000000000000000000000008152600481018c90527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1692506312a53623915086906024016000604051808303818588803b158015610c9c57600080fd5b505af1158015610cb0573d6000803e3d6000fd5b50969e60009e508e9d509b505050505050505050505050565b6000808073ffffffffffffffffffffffffffffffffffffffff8516736b175474e89094c44da98b954eedeac495271d0f14610d30576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638277908b8a610dea6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660208201527f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996603482015260009060540160405160208183030381529060405280519060200120905090565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016060604051808303816000875af1158015610e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e699190611a22565b919450925090508215610fdf576040517fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000060208201527e01f4000000000000000000000000000000000000000000000000000000000060348201527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018790526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d5991610f8e9190600401611ab4565b6020604051808303816000875af1158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190611b1a565b610fdb9083611b62565b9150505b801561114d576040517fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060208201527d64000000000000000000000000000000000000000000000000000000000060348201527f6b175474e89094c44da98b954eedeac495271d0f0000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018590526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916110fc9190600401611ab4565b6020604051808303816000875af115801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190611b1a565b6111499084611b62565b9250505b6000670de0b6b3a764000061116c67ffffffffffffffff8a168c611b7b565b6111769190611b92565b9050808310156111b2576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090986000985088975095505050505050565b6000808073ffffffffffffffffffffffffffffffffffffffff8516737f39c581f595b53c5cb19bd0b3f8da6c935e2ca01461122c576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638277908b8a6112e66040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660208201527f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996603482015260009060540160405160208183030381529060405280519060200120905090565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016060604051808303816000875af1158015611341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113659190611a22565b9194509250905081156114da576040517f6b175474e89094c44da98b954eedeac495271d0f00000000000000000000000060208201527d64000000000000000000000000000000000000000000000000000000000060348201527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018690526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916114899190600401611ab4565b6020604051808303816000875af11580156114a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cc9190611b1a565b6114d69083611b62565b9150505b8015611649576040517fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060208201527e01f4000000000000000000000000000000000000000000000000000000000060348201527fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018590526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916115f89190600401611ab4565b6020604051808303816000875af1158015611617573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163b9190611b1a565b6116459085611b62565b9350505b600083156117bc576040805160c0810182527f32296969ef14eb0c6d29669c550d4a044913023000020000000000000000008081526000602080830182905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc283850152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca060608085019190915260808085018a90528551808701875260048082527f30783030000000000000000000000000000000000000000000000000000000008286015260a087019190915286519182018752308083529382018590528187019390935290810183905293517f52bbbe2900000000000000000000000000000000000000000000000000000000815292939273ba12222222228d8ba445958a75a0704d566bf2c8926352bbbe299261177492879287929091429101611bcd565b6020604051808303816000875af1158015611793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b79190611b1a565b925050505b6000670de0b6b3a76400006117db67ffffffffffffffff8b168d611b7b565b6117e59190611b92565b905080821015611821576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5099600099508998509650505050505050565b60006060828403121561184657600080fd5b50919050565b803567ffffffffffffffff8116811461186457600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461186457600080fd5b600080600080600080600080610200898b0312156118aa57600080fd5b6118b48a8a611834565b97506118c38a60608b01611834565b96506118d28a60c08b01611834565b95506118e28a6101208b01611834565b945061018089013593506101a089013592506119016101c08a0161184c565b91506119106101e08a01611869565b90509295985092959890939650565b6000806000806000806101c0878903121561193957600080fd5b6119438888611834565b95506119528860608901611834565b94506119618860c08901611834565b9350611971886101208901611834565b925061018087013591506119886101a0880161184c565b90509295509295509295565b60008060008060006101a086880312156119ad57600080fd5b6119b78787611834565b94506119c68760608801611834565b93506119d58760c08801611834565b92506119e5876101208801611834565b91506119f4610180870161184c565b90509295509295909350565b600060208284031215611a1257600080fd5b611a1b82611869565b9392505050565b600080600060608486031215611a3757600080fd5b8351925060208401519150604084015190509250925092565b6000815180845260005b81811015611a7657602081850181015186830182015201611a5a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000825160a06020840152611ad060c0840182611a50565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600060208284031215611b2c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611b7557611b75611b33565b92915050565b8082028115828204841417611b7557611b75611b33565b600082611bc8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60e08152845160e08201526000602086015160028110611c16577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b610100830152604086015173ffffffffffffffffffffffffffffffffffffffff166101208301526060860151611c6561014084018273ffffffffffffffffffffffffffffffffffffffff169052565b50608086015161016083015260a086015160c0610180840152611c8c6101a0840182611a50565b915050611cdb602083018673ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b60a082019390935260c001529291505056fea2646970667358221220b8c15c635ddfef51f1468cbcd54784b8ffca7ed8ac364d50d0548e33a0f2870064736f6c63430008120033000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b351680455000000000000000000000000c52b9ae03d971954701b07090c57d993edcfbe79000000000000000000000000257c42571414ba714e81b968652f9c91d63a5b6600000000000000000000000015e27d72a6e95318e6b0e5e4a42b3b6ca22f09a7
Deployed Bytecode
0x6080604052600436106101485760003560e01c8063ad5c4648116100c0578063d9fb643a11610074578063e0bab4c411610059578063e0bab4c41461042d578063e2d51a7714610455578063f8e19cb11461048957600080fd5b8063d9fb643a146103df578063dbeacd541461040757600080fd5b8063ae9467b5116100a5578063ae9467b51461035b578063aedfdaea1461038f578063bb935cbf146103b757600080fd5b8063ad5c46481461030b578063ae4175b71461033357600080fd5b806389a302711161011757806396f50b2d116100fc57806396f50b2d1461029c5780639b07d342146102c4578063a5907215146102d757600080fd5b806389a302711461023257806394d0a7431461025a57600080fd5b806326c3b515146101545780632aa6584a1461018957806332fe7b26146101e25780636508156e1461020a57600080fd5b3661014f57005b600080fd5b61016761016236600461188d565b6104bd565b6040805193845260208401929092521515908201526060015b60405180910390f35b34801561019557600080fd5b506101bd7f000000000000000000000000257c42571414ba714e81b968652f9c91d63a5b6681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610180565b3480156101ee57600080fd5b506101bd73e592427a0aece92de3edee1f18e0157c0586156481565b34801561021657600080fd5b506101bd73abc30e831b5cc173a9ed5941714a7845c909e7fa81565b34801561023e57600080fd5b506101bd73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b34801561026657600080fd5b5061028e7f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d829499681565b604051908152602001610180565b3480156102a857600080fd5b506101bd73ba12222222228d8ba445958a75a0704d566bf2c881565b6101676102d236600461191f565b61068a565b3480156102e357600080fd5b506101bd7f00000000000000000000000015e27d72a6e95318e6b0e5e4a42b3b6ca22f09a781565b34801561031757600080fd5b506101bd73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561033f57600080fd5b506101bd734169df1b7820702f566cc10938da51f6f597d26481565b34801561036757600080fd5b506101bd7f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b35168045581565b34801561039b57600080fd5b506101bd733c66b18f67ca6c1a71f829e2f6a0c987f97462d081565b3480156103c357600080fd5b506101bd7360897720aa966452e8706e74296b018990aec52781565b3480156103eb57600080fd5b506101bd737f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b34801561041357600080fd5b5061028e610422366004611994565b600095945050505050565b34801561043957600080fd5b506101bd736b175474e89094c44da98b954eedeac495271d0f81565b34801561046157600080fd5b506101bd7f000000000000000000000000c52b9ae03d971954701b07090c57d993edcfbe7981565b34801561049557600080fd5b5061028e7f32296969ef14eb0c6d29669c550d4a044913023000020000000000000000008081565b600080803373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b3516804551614610530576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b733c66b18f67ca6c1a71f829e2f6a0c987f97462d061055560408d0160208e01611a00565b73ffffffffffffffffffffffffffffffffffffffff16036105965761058b8761058460408c0160208d01611a00565b88886106c1565b92509250925061067c565b734169df1b7820702f566cc10938da51f6f597d2646105bb60408d0160208e01611a00565b73ffffffffffffffffffffffffffffffffffffffff16036105f05761058b876105ea60408c0160208d01611a00565b87610cc9565b7360897720aa966452e8706e74296b018990aec52761061560408d0160208e01611a00565b73ffffffffffffffffffffffffffffffffffffffff160361064a5761058b8761064460408c0160208d01611a00565b876111c5565b6040517fc582880b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b985098509895505050505050565b60008060006040517f26d18eab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808073ffffffffffffffffffffffffffffffffffffffff861615610713576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060007f000000000000000000000000c52b9ae03d971954701b07090c57d993edcfbe7973ffffffffffffffffffffffffffffffffffffffff16638277908b8b6107cd6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660208201527f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996603482015260009060540160405160208183030381529060405280519060200120905090565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016060604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190611a22565b9194509250905081156109c1576040517f6b175474e89094c44da98b954eedeac495271d0f00000000000000000000000060208201527d64000000000000000000000000000000000000000000000000000000000060348201527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018690526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916109709190600401611ab4565b6020604051808303816000875af115801561098f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b39190611b1a565b6109bd9083611b62565b9150505b8015610b30576040517fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060208201527e01f4000000000000000000000000000000000000000000000000000000000060348201527fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018590526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d5991610adf9190600401611ab4565b6020604051808303816000875af1158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b229190611b1a565b610b2c9085611b62565b9350505b6000670de0b6b3a7640000610b4f67ffffffffffffffff8a168d611b7b565b610b599190611b92565b905080841015610b95576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810185905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b158015610bfb57600080fd5b505af1158015610c0f573d6000803e3d6000fd5b50506040517f12a53623000000000000000000000000000000000000000000000000000000008152600481018c90527f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b35168045573ffffffffffffffffffffffffffffffffffffffff1692506312a53623915086906024016000604051808303818588803b158015610c9c57600080fd5b505af1158015610cb0573d6000803e3d6000fd5b50969e60009e508e9d509b505050505050505050505050565b6000808073ffffffffffffffffffffffffffffffffffffffff8516736b175474e89094c44da98b954eedeac495271d0f14610d30576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060007f000000000000000000000000257c42571414ba714e81b968652f9c91d63a5b6673ffffffffffffffffffffffffffffffffffffffff16638277908b8a610dea6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660208201527f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996603482015260009060540160405160208183030381529060405280519060200120905090565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016060604051808303816000875af1158015610e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e699190611a22565b919450925090508215610fdf576040517fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000060208201527e01f4000000000000000000000000000000000000000000000000000000000060348201527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018790526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d5991610f8e9190600401611ab4565b6020604051808303816000875af1158015610fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd19190611b1a565b610fdb9083611b62565b9150505b801561114d576040517fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060208201527d64000000000000000000000000000000000000000000000000000000000060348201527f6b175474e89094c44da98b954eedeac495271d0f0000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018590526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916110fc9190600401611ab4565b6020604051808303816000875af115801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190611b1a565b6111499084611b62565b9250505b6000670de0b6b3a764000061116c67ffffffffffffffff8a168c611b7b565b6111769190611b92565b9050808310156111b2576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090986000985088975095505050505050565b6000808073ffffffffffffffffffffffffffffffffffffffff8516737f39c581f595b53c5cb19bd0b3f8da6c935e2ca01461122c576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060007f00000000000000000000000015e27d72a6e95318e6b0e5e4a42b3b6ca22f09a773ffffffffffffffffffffffffffffffffffffffff16638277908b8a6112e66040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660208201527f427a506ff6e15bd1b7e4e93da52c8ec95f6af1279618a2f076946e83d8294996603482015260009060540160405160208183030381529060405280519060200120905090565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016060604051808303816000875af1158015611341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113659190611a22565b9194509250905081156114da576040517f6b175474e89094c44da98b954eedeac495271d0f00000000000000000000000060208201527d64000000000000000000000000000000000000000000000000000000000060348201527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018690526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916114899190600401611ab4565b6020604051808303816000875af11580156114a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cc9190611b1a565b6114d69083611b62565b9150505b8015611649576040517fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060208201527e01f4000000000000000000000000000000000000000000000000000000000060348201527fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006037820152600090604b01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815260a0830182528083523060208401524283830152606083018590526000608084015290517fc04b8d5900000000000000000000000000000000000000000000000000000000815290925073e592427a0aece92de3edee1f18e0157c058615649163c04b8d59916115f89190600401611ab4565b6020604051808303816000875af1158015611617573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163b9190611b1a565b6116459085611b62565b9350505b600083156117bc576040805160c0810182527f32296969ef14eb0c6d29669c550d4a044913023000020000000000000000008081526000602080830182905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc283850152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca060608085019190915260808085018a90528551808701875260048082527f30783030000000000000000000000000000000000000000000000000000000008286015260a087019190915286519182018752308083529382018590528187019390935290810183905293517f52bbbe2900000000000000000000000000000000000000000000000000000000815292939273ba12222222228d8ba445958a75a0704d566bf2c8926352bbbe299261177492879287929091429101611bcd565b6020604051808303816000875af1158015611793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b79190611b1a565b925050505b6000670de0b6b3a76400006117db67ffffffffffffffff8b168d611b7b565b6117e59190611b92565b905080821015611821576040517f8199f5f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5099600099508998509650505050505050565b60006060828403121561184657600080fd5b50919050565b803567ffffffffffffffff8116811461186457600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461186457600080fd5b600080600080600080600080610200898b0312156118aa57600080fd5b6118b48a8a611834565b97506118c38a60608b01611834565b96506118d28a60c08b01611834565b95506118e28a6101208b01611834565b945061018089013593506101a089013592506119016101c08a0161184c565b91506119106101e08a01611869565b90509295985092959890939650565b6000806000806000806101c0878903121561193957600080fd5b6119438888611834565b95506119528860608901611834565b94506119618860c08901611834565b9350611971886101208901611834565b925061018087013591506119886101a0880161184c565b90509295509295509295565b60008060008060006101a086880312156119ad57600080fd5b6119b78787611834565b94506119c68760608801611834565b93506119d58760c08801611834565b92506119e5876101208801611834565b91506119f4610180870161184c565b90509295509295909350565b600060208284031215611a1257600080fd5b611a1b82611869565b9392505050565b600080600060608486031215611a3757600080fd5b8351925060208401519150604084015190509250925092565b6000815180845260005b81811015611a7657602081850181015186830182015201611a5a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000825160a06020840152611ad060c0840182611a50565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600060208284031215611b2c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611b7557611b75611b33565b92915050565b8082028115828204841417611b7557611b75611b33565b600082611bc8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60e08152845160e08201526000602086015160028110611c16577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b610100830152604086015173ffffffffffffffffffffffffffffffffffffffff166101208301526060860151611c6561014084018273ffffffffffffffffffffffffffffffffffffffff169052565b50608086015161016083015260a086015160c0610180840152611c8c6101a0840182611a50565b915050611cdb602083018673ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b60a082019390935260c001529291505056fea2646970667358221220b8c15c635ddfef51f1468cbcd54784b8ffca7ed8ac364d50d0548e33a0f2870064736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b351680455000000000000000000000000c52b9ae03d971954701b07090c57d993edcfbe79000000000000000000000000257c42571414ba714e81b968652f9c91d63a5b6600000000000000000000000015e27d72a6e95318e6b0e5e4a42b3b6ca22f09a7
-----Decoded View---------------
Arg [0] : _rollupProcessor (address): 0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455
Arg [1] : _wethMigrator (address): 0xC52b9aE03d971954701B07090C57D993edCFbe79
Arg [2] : _daiMigrator (address): 0x257c42571414ba714e81B968652f9c91D63a5B66
Arg [3] : _wstethMigrator (address): 0x15e27d72a6E95318e6B0e5e4a42b3B6ca22F09A7
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b351680455
Arg [1] : 000000000000000000000000c52b9ae03d971954701b07090c57d993edcfbe79
Arg [2] : 000000000000000000000000257c42571414ba714e81b968652f9c91d63a5b66
Arg [3] : 00000000000000000000000015e27d72a6e95318e6b0e5e4a42b3b6ca22f09a7
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.