Source Code
Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28332191 | 3 hrs ago | 0 ETH | ||||
| 28322400 | 9 hrs ago | 0 ETH | ||||
| 28313248 | 15 hrs ago | 0 ETH | ||||
| 28304321 | 21 hrs ago | 0 ETH | ||||
| 28294810 | 27 hrs ago | 0 ETH | ||||
| 28285259 | 33 hrs ago | 0 ETH | ||||
| 28275810 | 39 hrs ago | 0 ETH | ||||
| 28266934 | 45 hrs ago | 0 ETH | ||||
| 28256797 | 2 days ago | 0 ETH | ||||
| 28247516 | 2 days ago | 0 ETH | ||||
| 28238113 | 2 days ago | 0 ETH | ||||
| 28228522 | 2 days ago | 0 ETH | ||||
| 28218706 | 3 days ago | 0 ETH | ||||
| 28208850 | 3 days ago | 0 ETH | ||||
| 28198302 | 3 days ago | 0 ETH | ||||
| 28187597 | 3 days ago | 0 ETH | ||||
| 28176819 | 4 days ago | 0 ETH | ||||
| 28166131 | 4 days ago | 0 ETH | ||||
| 28163160 | 4 days ago | 0.005 ETH | ||||
| 28155697 | 4 days ago | 0 ETH | ||||
| 28145198 | 4 days ago | 0 ETH | ||||
| 28134457 | 5 days ago | 0 ETH | ||||
| 28123738 | 5 days ago | 0 ETH | ||||
| 28113237 | 5 days ago | 0 ETH | ||||
| 28102726 | 5 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
xRenzoDepositNativeBridge
Compiler Version
v0.8.27+commit.40a35a09
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;
import "./xRenzoDepositNativeBridgeStorage.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {
OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {
IERC20MetadataUpgradeable
} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
import "../../Errors/Errors.sol";
import "../xERC20/interfaces/IXERC20.sol";
import "../Connext/core/IWeth.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "../../RateProvider/IRateProvider.sol";
import "@hyperlane-xyz/core/contracts/libs/TypeCasts.sol";
/**
* @author Renzo
* @title xRenzoDeposit Contract
* @dev Tokens are sent to this contract via deposit, xezETH is minted for the user,
* and funds are batched and bridged down to the L1 for depositing into the Renzo Protocol.
* Any ezETH minted on the L1 will be locked in the lockbox for unwrapping at a later time with xezETH.
* @notice Allows L2 minting of xezETH tokens in exchange for deposited assets
*/
contract xRenzoDepositNativeBridge is
Initializable,
OwnableUpgradeable,
ReentrancyGuardUpgradeable,
IRateProvider,
xRenzoDepositNativeBridgeStorageV2
{
using TypeCasts for address;
using SafeERC20 for IERC20;
/// @dev - This contract expects all tokens to have 18 decimals for pricing
uint8 public constant EXPECTED_DECIMALS = 18;
/// @dev - Fee basis point, 100 basis point = 1 %
uint32 public constant FEE_BASIS = 10000;
IERC20 public constant ETH_NATIVE_TOKEN_ADDRESS =
IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
uint256 public constant MIN_DUST_BRIDGE = 500000 gwei;
event PriceUpdated(uint256 price, uint256 timestamp);
event Deposit(address indexed user, uint256 amountIn, uint256 amountOut);
event BridgeSwept(address token, uint256 amount, address sweeper);
event ReceiverPriceFeedUpdated(address newReceiver, address oldReceiver);
event SweeperBridgeFeeCollected(address sweeper, address token, uint256 feeCollected);
event BridgeFeeShareUpdated(uint256 oldBridgeFeeShare, uint256 newBridgeFeeShare);
event FlatBridgeFeeUpdated(uint256 oldFlatBridgeFee, uint256 newFlatBridgeFee);
event SweepBatchSizeUpdated(uint256 oldSweepBatchSize, uint256 newSweepBatchSize);
event TokenSupportUpdated(
address token,
bool supported,
address oracle,
address valueTransferBridge
);
event TokenTimeDiscountUpdated(address token, uint256 oldDiscount, uint256 newDiscount);
event BridgeFeeCollectorUpdated(address oldBridgeFeeCollector, address newBridgeFeeCollector);
/// @dev Prevents implementation contract from being initialized.
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/**
* @notice Initializes the contract with initial vars
* @dev All tokens are expected to have 18 decimals
* @param _currentPrice Initializes it with an initial price of ezETH to ETH
* @param _xezETH L2 ezETH token
* @param _weth WETH token for wrapping ETH - can be 0x0 if not supported
* @param _receiver Renzo Receiver middleware contract for price feed
* @param _mainnetDestinationDomain The mainnet destination domain to receive bridge funds
* @param _mainnetRecipient The contract on mainnet to receive bridge funds
* @param _bridgeFeeCollector The address to collect bridge fees - is sent funds as they are collected
*/
function initialize(
uint256 _currentPrice,
IERC20 _xezETH,
IWeth _weth,
address _receiver,
uint32 _mainnetDestinationDomain,
address _mainnetRecipient,
address _bridgeFeeCollector
) public initializer {
// Initialize inherited classes
__Ownable_init();
__ReentrancyGuard_init();
// Verify valid non zero values
if (
_currentPrice == 0 ||
address(_xezETH) == address(0) ||
address(_weth) == address(0) ||
address(_receiver) == address(0) ||
_mainnetDestinationDomain == 0 ||
_mainnetRecipient == address(0) ||
_bridgeFeeCollector == address(0)
) {
revert InvalidZeroInput();
}
// Verify all tokens have 18 decimals
uint8 decimals = IERC20MetadataUpgradeable(address(_xezETH)).decimals();
if (decimals != EXPECTED_DECIMALS) {
revert InvalidTokenDecimals(EXPECTED_DECIMALS, decimals);
}
decimals = IERC20MetadataUpgradeable(address(_weth)).decimals();
if (decimals != EXPECTED_DECIMALS) {
revert InvalidTokenDecimals(EXPECTED_DECIMALS, decimals);
}
// Initialize the price and timestamp
lastPrice = _currentPrice;
lastPriceTimestamp = block.timestamp;
// Set xezETH address
xezETH = _xezETH;
// Set WETH address
weth = _weth;
// Set price receiver contract address
receiver = _receiver;
// Set the destination domain and recipient
mainnetDestinationDomain = _mainnetDestinationDomain;
mainnetRecipient = _mainnetRecipient;
// set bridge Fee Share 0.05% where 100 basis point = 1%
bridgeFeeShare = 5;
//set sweep batch size to 32 ETH
sweepBatchSize = 32 ether;
// Set the bridge fee collector
bridgeFeeCollector = _bridgeFeeCollector;
}
/**
* @notice Accepts deposit for the user in the native asset and mints xezETH
* @dev This function allows anyone to call and deposit the native asset for xezETH
* ezETH will be immediately minted based on the current price
* @param _minOut Minimum number of xezETH to accept to ensure slippage minimums
* @param _deadline latest timestamp to accept this transaction
* @return uint256 Amount of xezETH minted to calling account
*/
function depositETH(
uint256 _minOut,
uint256 _deadline
) external payable nonReentrant returns (uint256) {
if (msg.value == 0) {
revert InvalidZeroInput();
}
// Calculate bridgeFee for deposit amount
uint256 bridgeFee = getBridgeFeeShare(msg.value);
// Send the eth fee to the bridgeFeeCollector
if (bridgeFee > 0) {
bool success = payable(bridgeFeeCollector).send(bridgeFee);
if (!success) revert TransferFailed();
emit SweeperBridgeFeeCollected(
bridgeFeeCollector,
address(ETH_NATIVE_TOKEN_ADDRESS),
bridgeFee
);
}
// Remaining amount after bridge fee
uint256 remainingAmount = msg.value - bridgeFee;
// Sanity check amount
if (remainingAmount == 0) {
revert InvalidZeroInput();
}
// Deposit remaining amount to mint xezETH
return _deposit(ETH_NATIVE_TOKEN_ADDRESS, remainingAmount, _minOut, _deadline);
}
/**
* @notice Accepts deposit for the user in depositToken and mints xezETH
* @dev This funcion allows anyone to call and deposit collateral for xezETH
* ezETH will be immediately minted based on the current price
* Funds will be held until sweep() is called.
* User calling this function should first approve the tokens to be pulled via transferFrom
* @param _amountIn Amount of tokens to deposit
* @param _minOut Minimum number of xezETH to accept to ensure slippage minimums
* @param _deadline latest timestamp to accept this transaction
* @return uint256 Amount of xezETH minted to calling account
*/
function deposit(
IERC20 _token,
uint256 _amountIn,
uint256 _minOut,
uint256 _deadline
) external nonReentrant returns (uint256) {
// Verify the amount is valid
if (_amountIn == 0) {
revert InvalidZeroInput();
}
// Transfer deposit tokens from user to this contract
_token.safeTransferFrom(msg.sender, address(this), _amountIn);
// calculate bridgeFee for deposit amount
uint256 bridgeFee = getBridgeFeeShare(_amountIn);
// Send the fee to the bridgeFeeCollector
if (bridgeFee > 0) {
_token.safeTransfer(bridgeFeeCollector, bridgeFee);
emit SweeperBridgeFeeCollected(bridgeFeeCollector, address(_token), bridgeFee);
}
// subtract from _amountIn
_amountIn -= bridgeFee;
// Get the ETH value of the token
uint256 tokenEthValue = _getTokenEthValue(_token, _amountIn);
if (tokenEthValue == 0) {
revert InvalidZeroOutput();
}
// Special Case if the token is WETH... unwrap to ETH
if (_token == IERC20(address(weth))) {
// Unwrap WETH to ETH
weth.withdraw(_amountIn);
}
return _deposit(_token, tokenEthValue, _minOut, _deadline);
}
/**
* @notice Internal function to trade deposit tokens
* @dev Deposit Tokens should be available in the contract before calling this function
* @param _token Address of the token to be deposited
* @param _tokenEthValue Amount of value priced in ETH
* @param _minOut Minimum number of xezETH to accept to ensure slippage minimums
* @param _deadline latest timestamp to accept this transaction
* @return uint256 Amount of xezETH minted to calling account
*/
function _deposit(
IERC20 _token,
uint256 _tokenEthValue,
uint256 _minOut,
uint256 _deadline
) internal returns (uint256) {
// Verify the token is supported
if (!depositTokenSupported[_token]) {
revert InvalidTokenReceived();
}
// Discount the value based on the time it takes to be sent across the bridge
uint256 timeBasedDiscount = _getTokenTimeBasedDiscount(_token, _tokenEthValue);
_tokenEthValue -= timeBasedDiscount;
// Fetch price and timestamp of ezETH from the configured price feed
(uint256 lastPrice, uint256 lastPriceTimestamp) = getMintRate();
// Verify the price is not stale
if (block.timestamp > lastPriceTimestamp + 1 days) {
revert OraclePriceExpired();
}
// Calculate the amount of xezETH to mint - assumes 18 decimals for price and token
uint256 xezETHAmount = (1e18 * _tokenEthValue) / lastPrice;
// Check that the user will get the minimum amount of xezETH
if (xezETHAmount < _minOut) {
revert InsufficientOutputAmount();
}
// Verify the deadline has not passed
if (block.timestamp > _deadline) {
revert InvalidTimestamp(_deadline);
}
// Mint xezETH to the user
IXERC20(address(xezETH)).mint(msg.sender, xezETHAmount);
// Emit the event and return amount minted
emit Deposit(msg.sender, _tokenEthValue, xezETHAmount);
return xezETHAmount;
}
/**
* @notice Gets the ETH value of the deposit token
* @dev Assumes oracle price is in ETH and is 18 decimals
* @return uint256 ETH Value
*/
function _getTokenEthValue(IERC20 _token, uint256 _amount) internal view returns (uint256) {
AggregatorV3Interface oracle = tokenOracleLookup[_token];
if (address(oracle) == address(0x0)) revert OracleNotFound();
(, int256 price, , uint256 timestamp, ) = oracle.latestRoundData();
if (block.timestamp > timestamp + 1 days) revert OraclePriceExpired();
if (price <= 0) revert InvalidOraclePrice();
// Calculate the value of the token in ETH - assumes both token and price are 18 decimals
return (_amount * uint256(price)) / 1e18;
}
/**
* @notice Function returns bridge fee share for deposit - includes percentage and flat fee
* @param _amountIn deposit amount in terms of ETH
*/
function getBridgeFeeShare(uint256 _amountIn) public view returns (uint256) {
// deduct bridge Fee share
if (_amountIn < sweepBatchSize) {
return ((_amountIn * bridgeFeeShare) / FEE_BASIS) + flatBridgeFee;
} else {
return ((sweepBatchSize * bridgeFeeShare) / FEE_BASIS) + flatBridgeFee;
}
}
/**
* @notice Gets the time based discount for the token amount
* @dev If the token takes 7 days to get across the bridge, the value will not be earning yield for 7 days so it must be discounted.
* The discount should include any staking and restaking yields that the token would have earned.
* @param _token address of the token
* @param _tokenEthValue ETH value of the token
* @return uint256 amount to be discounted by
*/
function _getTokenTimeBasedDiscount(
IERC20 _token,
uint256 _tokenEthValue
) internal view returns (uint256) {
// Calculate the time based discount
return (tokenTimeDiscountBasisPoints[_token] * _tokenEthValue) / FEE_BASIS;
}
/**
* @notice Fetch the price of ezETH from configured price feeds
*/
function getMintRate() public view returns (uint256, uint256) {
// revert if PriceFeedNotAvailable
if (receiver == address(0)) revert PriceFeedNotAvailable();
return (lastPrice, lastPriceTimestamp);
}
/**
* @notice Updates the price feed
* @dev This function will receive the price feed and timestamp from the L1 through CCIPReceiver middleware contract.
* It should verify the origin of the call and only allow permissioned source to call.
* @param _price The price of ezETH sent via L1.
* @param _timestamp The timestamp at which L1 sent the price.
*/
function updatePrice(uint256 _price, uint256 _timestamp) external override {
if (msg.sender != receiver) revert InvalidSender(receiver, msg.sender);
_updatePrice(_price, _timestamp);
}
/**
* @notice Updates the price feed from the Owner account
* @dev Sets the last price and timestamp
* @param price price of ezETH to ETH - 18 decimal precision
*/
function updatePriceByOwner(uint256 price) external onlyOwner {
return _updatePrice(price, block.timestamp);
}
/**
* @notice Internal function to update price
* @dev Sanity checks input values and updates prices
* @param _price Current price of ezETH to ETH - 18 decimal precision
* @param _timestamp The timestamp of the price update
*/
function _updatePrice(uint256 _price, uint256 _timestamp) internal {
_beforeUpdatePrice(_price, _timestamp);
// Update values and emit event
lastPrice = _price;
lastPriceTimestamp = _timestamp;
emit PriceUpdated(_price, _timestamp);
}
function _beforeUpdatePrice(uint256 _price, uint256 _timestamp) internal view {
// Check for 0
if (_price == 0) {
revert InvalidZeroInput();
}
// check for undercollateralized price - < 1
if (_price < 1 ether) {
revert InvalidOraclePrice();
}
// Check for price divergence - more than 1%
if (
(_price > lastPrice && (_price - lastPrice) > (lastPrice / 100)) ||
(_price < lastPrice && (lastPrice - _price) > (lastPrice / 100))
) {
revert InvalidOraclePrice();
}
// Do not allow older price timestamps
if (_timestamp <= lastPriceTimestamp) {
revert InvalidTimestamp(_timestamp);
}
// Do not allow future timestamps
if (_timestamp > block.timestamp) {
revert InvalidTimestamp(_timestamp);
}
}
/**
* @notice This function will take the balance of an asset in the contract and bridge it down to the L1
* @dev The L1 contract will unwrap, deposit in Renzo, and lock up the ezETH in the lockbox on L1
* The caller will estimate and pay the gas for the bridge call
* @param _token Address of token to be swept to L1
*/
function sweep(IERC20 _token) public payable nonReentrant {
// Verify it is a supported token
if (!depositTokenSupported[_token]) {
revert InvalidTokenReceived();
}
// Get the balance of the asset in the contract
uint256 balance = _token.balanceOf(address(this));
// If there is not enough to bridge balance, revert
if (balance <= MIN_DUST_BRIDGE) {
revert InsufficientOutputAmount();
}
// Approve the token and route it to mainnet
_token.safeIncreaseAllowance(address(valueTransferBridges[_token]), balance);
// Include the msg.value to pay any bridge fees
valueTransferBridges[_token].transferRemote{ value: msg.value }(
mainnetDestinationDomain,
mainnetRecipient.addressToBytes32(),
balance
);
// Emit the event
emit BridgeSwept(address(_token), balance, msg.sender);
}
/**
* @notice This function will take the balance ETH in the contract and bridge it down to the L1
* @dev The L1 contract will deposit in Renzo, and lock up the ezETH in the lockbox on L1
* The caller will estimate and pay the gas for the bridge call
*/
function sweepETH() public payable nonReentrant {
// Verify Native ETH is supported
if (!depositTokenSupported[ETH_NATIVE_TOKEN_ADDRESS]) {
revert InvalidTokenReceived();
}
// Get the balance of ETH in the contract minus the gas value
uint256 valueToSend = address(this).balance - msg.value;
// If there is not enough to bridge balance, revert
if (valueToSend <= MIN_DUST_BRIDGE) {
revert InsufficientOutputAmount();
}
// Send the full ETH available but specify the amount that should be bridged
valueTransferBridges[ETH_NATIVE_TOKEN_ADDRESS].transferRemote{
value: address(this).balance
}(mainnetDestinationDomain, mainnetRecipient.addressToBytes32(), valueToSend);
// Emit the event
emit BridgeSwept(address(ETH_NATIVE_TOKEN_ADDRESS), valueToSend, msg.sender);
}
/**
* @notice Exposes the price via getRate()
* @dev This is required for a balancer pool to get the price of ezETH
* @return uint256 .
*/
function getRate() external view override returns (uint256) {
(uint256 _lastPrice, uint256 _lastPriceTimestamp) = getMintRate();
if (block.timestamp > _lastPriceTimestamp + 1 days) {
revert OraclePriceExpired();
}
return _lastPrice;
}
/**
* @notice Allows the owner to set the support for a deposit asset
* @dev Checks the token for 0 anb verifies the oracle is set properly if adding support
* @param _token EC20 token
* @param _supported Indicates if the token is supported for a deposit asset
* @param _tokenOracle If supported, the oracle for the token to get pricing in ETH
* @param _valueTransferBridge Middleware contract used to transfer asset through configured bridge
*/
function setSupportedToken(
IERC20 _token,
bool _supported,
AggregatorV3Interface _tokenOracle,
IValueTransferBridge _valueTransferBridge
) external onlyOwner {
// Verify the token is not 0
if (address(_token) == address(0)) revert InvalidZeroInput();
// Verify the token is 18 decimals if it is not ETH
if (
address(_token) != address(ETH_NATIVE_TOKEN_ADDRESS) &&
IERC20MetadataUpgradeable(address(_token)).decimals() != 18
) revert InvalidTokenDecimals(18, IERC20MetadataUpgradeable(address(_token)).decimals());
// Update support value
depositTokenSupported[_token] = _supported;
// If support is being added, verify the oracle
if (_supported) {
if (address(_tokenOracle) == address(0)) revert InvalidZeroInput();
// Verify that the pricing of the oracle is to 18 decimals - pricing calculations will be off otherwise
if (_tokenOracle.decimals() != 18)
revert InvalidTokenDecimals(18, _tokenOracle.decimals());
// Set the oracle lookup
tokenOracleLookup[_token] = _tokenOracle;
if (address(_valueTransferBridge) == address(0)) {
revert InvalidZeroInput();
}
// Set the value transfer bridge
valueTransferBridges[_token] = _valueTransferBridge;
} else {
// If not supported, set the oracle to 0
tokenOracleLookup[_token] = AggregatorV3Interface(address(0));
// If not supported, set the value transfer bridge to 0
valueTransferBridges[_token] = IValueTransferBridge(address(0));
}
// Emit the event
emit TokenSupportUpdated(
address(_token),
_supported,
address(_tokenOracle),
address(_valueTransferBridge)
);
}
/**
* @notice Sweeps accidental ETH value sent to the contract
* @dev Restricted to be called by the Owner only.
* @param _amount amount of native asset
* @param _to destination address
*/
function recoverNative(uint256 _amount, address _to) external onlyOwner {
payable(_to).transfer(_amount);
}
/**
* @notice Sweeps accidental ERC20 value sent to the contract
* @dev Restricted to be called by the Owner only.
* @param _token address of the ERC20 token
* @param _amount amount of ERC20 token
* @param _to destination address
*/
function recoverERC20(address _token, uint256 _amount, address _to) external onlyOwner {
IERC20(_token).safeTransfer(_to, _amount);
}
/******************************
* Admin/OnlyOwner functions
*****************************/
/**
* @notice This function sets/updates the Bridge Fee Collector address
* @dev This should be permissioned call (onlyOwner)
* @param _bridgeFeeCollector new Bridge fee collector address
*/
function setBridgeFeeCollector(address _bridgeFeeCollector) external onlyOwner {
if (_bridgeFeeCollector == address(0)) revert InvalidZeroInput();
emit BridgeFeeCollectorUpdated(bridgeFeeCollector, _bridgeFeeCollector);
bridgeFeeCollector = _bridgeFeeCollector;
}
/**
* @notice This function sets/updates the Receiver Price Feed Middleware for ezETH
* @dev This should be permissioned call (onlyOnwer), can be set to address(0) for not configured
* @param _receiver Receiver address
*/
function setReceiverPriceFeed(address _receiver) external onlyOwner {
emit ReceiverPriceFeedUpdated(_receiver, receiver);
receiver = _receiver;
}
/**
* @notice This function updates the BridgeFeeShare for depositors (must be <= 1% i.e. 100 bps)
* @dev This should be a permissioned call (onlyOnwer)
* @param _newShare new Bridge fee share in basis points where 100 basis points = 1%
* @param _newFlatFee new flat fee charged for each deposit in addition to the % fee - in token units
*/
function updateBridgeFeeShare(uint256 _newShare, uint256 _newFlatFee) external onlyOwner {
if (_newShare > 100) revert InvalidBridgeFeeShare(_newShare);
emit BridgeFeeShareUpdated(bridgeFeeShare, _newShare);
bridgeFeeShare = _newShare;
emit FlatBridgeFeeUpdated(flatBridgeFee, _newFlatFee);
flatBridgeFee = _newFlatFee;
}
/**
* @notice This function updates the Sweep Batch Size (must be >= 32 ETH)
* @dev This should be a permissioned call (onlyOwner)
* @param _newBatchSize new batch size for sweeping
*/
function updateSweepBatchSize(uint256 _newBatchSize) external onlyOwner {
if (_newBatchSize < 32 ether) revert InvalidSweepBatchSize(_newBatchSize);
emit SweepBatchSizeUpdated(sweepBatchSize, _newBatchSize);
sweepBatchSize = _newBatchSize;
}
/**
* @notice Updates the time based discount bps per token
* @dev This should be a permissioned call (onlyOwner)
* @param _token address of the token
* @param _discount time based discount in basis points where 100 basis points = 1%
*/
function updateTokenTimeDiscount(IERC20 _token, uint256 _discount) external onlyOwner {
// Verify the token is supported
if (!depositTokenSupported[_token]) {
revert InvalidTokenReceived();
}
// The discount should not be greater than 1%
if (_discount > 100) revert OverMaxBasisPoints();
// Get the discount currently set
uint256 oldDiscount = tokenTimeDiscountBasisPoints[_token];
// Update the discount and emit event
tokenTimeDiscountBasisPoints[_token] = _discount;
emit TokenTimeDiscountUpdated(address(_token), oldDiscount, _discount);
}
/**
* @notice Fallback function to handle ETH sent to the contract from unwrapping WETH
* @dev Warning: users should not send ETH directly to this contract!
*/
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(
uint80 _roundId
) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.6.11;
library TypeCasts {
// alignment preserving cast
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
// alignment preserving cast
function bytes32ToAddress(bytes32 _buf) internal pure returns (address) {
require(
uint256(_buf) <= uint256(type(uint160).max),
"TypeCasts: bytes32ToAddress overflow"
);
return address(uint160(uint256(_buf)));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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 "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @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 (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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.8.0/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: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
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].
*
* CAUTION: See Security Considerations above.
*/
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.9.3) (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;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
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));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
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");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
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");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// 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 cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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.8.0/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: UNLICENSED
pragma solidity ^0.8.0;
interface IWeth {
function deposit() external payable;
function withdraw(uint256 value) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IxRenzoDeposit {
function deposit(
IERC20 _token,
uint256 _amountIn,
uint256 _minOut,
uint256 _deadline
) external returns (uint256);
function sweep(IERC20 _token) external payable;
function updatePrice(uint256 price, uint256 timestamp) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;
interface IRenzoOracleL2 {
function getMintRate() external view returns (uint256, uint256);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;
struct Quote {
address token; // address(0) for the native token
uint256 amount;
}
interface IValueTransferBridge {
/**
* @notice Transfer value to another domain
* @param _destination The destination domain of the message
* @param _recipient The message recipient address on `destination`
* @param _amount The amount to send to the recipient
* @return messageId The identifier of the dispatched message.
*/
function transferRemote(
uint32 _destination,
bytes32 _recipient,
uint256 _amount
) external payable returns (bytes32);
/**
* @notice Provide the value transfer quote
* @param _destination The destination domain of the message
* @param _recipient The message recipient address on `destination`
* @param _amount The amount to send to the recipient
* @return quotes Indicate how much of each token to approve and/or send.
* @dev Good practice is to use the first entry of the quotes for the native currency (i.e. ETH)
*/
function quoteTransferRemote(
uint32 _destination,
bytes32 _recipient,
uint256 _amount
) external view returns (Quote[] memory quotes);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;
import "./IxRenzoDeposit.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./Oracle/IRenzoOracleL2.sol";
import "../Connext/core/IWeth.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "./ValueTransfer/IValueTransferBridge.sol";
abstract contract xRenzoDepositNativeBridgeStorageV1 is IxRenzoDeposit {
/// @notice The last timestamp the price was updated
uint256 public lastPriceTimestamp;
/// @notice The last price that was updated - denominated in ETH with 18 decimal precision
uint256 public lastPrice;
/// @notice The xezETH token address
IERC20 public xezETH;
/// @notice The receiver middleware contract address
address public receiver;
/// @notice The contract address where the bridge call should be sent on mainnet ETH
address public bridgeTargetAddress;
// bridge fee in basis points 100 basis points = 1%
uint256 public bridgeFeeShare;
// Batch size for sweeping
uint256 public sweepBatchSize;
// WETH token for wrapping ETH
IWeth public weth;
/// @dev Contracts that routes funds down to mainnet per token
mapping(IERC20 => IValueTransferBridge) public valueTransferBridges;
/// @dev The mainnet destination domain to receive bridge funds
uint32 public mainnetDestinationDomain;
/// @dev The contract on mainnet to receive bridge funds
address public mainnetRecipient;
// @dev Mapping of supported tokens
mapping(IERC20 => bool) public depositTokenSupported;
// @dev Mapping of token to oracle lookup
mapping(IERC20 => AggregatorV3Interface) public tokenOracleLookup;
// @dev Bridge fees are sent to the bridge fee collector
address public bridgeFeeCollector;
// @dev The mapping of token to time based discount in basis points - 100 basis points = 1%
mapping(IERC20 => uint256) public tokenTimeDiscountBasisPoints;
}
abstract contract xRenzoDepositNativeBridgeStorageV2 is xRenzoDepositNativeBridgeStorageV1 {
/// @dev A flat amount charged to each deposit in addition to the % fee (optional)
uint256 public flatBridgeFee;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.4 <0.9.0;
interface IXERC20 {
/**
* @notice Emits when a lockbox is set
*
* @param _lockbox The address of the lockbox
*/
event LockboxSet(address _lockbox);
/**
* @notice Emits when a limit is set
*
* @param _mintingLimit The updated minting limit we are setting to the bridge
* @param _burningLimit The updated burning limit we are setting to the bridge
* @param _bridge The address of the bridge we are setting the limit too
*/
event BridgeLimitsSet(uint256 _mintingLimit, uint256 _burningLimit, address indexed _bridge);
/**
* @notice Reverts when a user with too low of a limit tries to call mint/burn
*/
error IXERC20_NotHighEnoughLimits();
/**
* @notice Reverts when caller is not the factory
*/
error IXERC20_NotFactory();
/**
* @notice Reverts when mint or burn value is 0
*/
error IXERC20_INVALID_0_VALUE();
/**
* @notice Contains the full minting and burning data for a particular bridge
*
* @param minterParams The minting parameters for the bridge
* @param burnerParams The burning parameters for the bridge
*/
struct Bridge {
BridgeParameters minterParams;
BridgeParameters burnerParams;
}
/**
* @notice Contains the mint or burn parameters for a bridge
*
* @param timestamp The timestamp of the last mint/burn
* @param ratePerSecond The rate per second of the bridge
* @param maxLimit The max limit of the bridge
* @param currentLimit The current limit of the bridge
*/
struct BridgeParameters {
uint256 timestamp;
uint256 ratePerSecond;
uint256 maxLimit;
uint256 currentLimit;
}
/**
* @notice Sets the lockbox address
*
* @param _lockbox The address of the lockbox
*/
function setLockbox(address _lockbox) external;
/**
* @notice Updates the limits of any bridge
* @dev Can only be called by the owner
* @param _mintingLimit The updated minting limit we are setting to the bridge
* @param _burningLimit The updated burning limit we are setting to the bridge
* @param _bridge The address of the bridge we are setting the limits too
*/
function setLimits(address _bridge, uint256 _mintingLimit, uint256 _burningLimit) external;
/**
* @notice Returns the max limit of a minter
*
* @param _minter The minter we are viewing the limits of
* @return _limit The limit the minter has
*/
function mintingMaxLimitOf(address _minter) external view returns (uint256 _limit);
/**
* @notice Returns the max limit of a bridge
*
* @param _bridge the bridge we are viewing the limits of
* @return _limit The limit the bridge has
*/
function burningMaxLimitOf(address _bridge) external view returns (uint256 _limit);
/**
* @notice Returns the current limit of a minter
*
* @param _minter The minter we are viewing the limits of
* @return _limit The limit the minter has
*/
function mintingCurrentLimitOf(address _minter) external view returns (uint256 _limit);
/**
* @notice Returns the current limit of a bridge
*
* @param _bridge the bridge we are viewing the limits of
* @return _limit The limit the bridge has
*/
function burningCurrentLimitOf(address _bridge) external view returns (uint256 _limit);
/**
* @notice Mints tokens for a user
* @dev Can only be called by a minter
* @param _user The address of the user who needs tokens minted
* @param _amount The amount of tokens being minted
*/
function mint(address _user, uint256 _amount) external;
/**
* @notice Burns tokens for a user
* @dev Can only be called by a minter
* @param _user The address of the user who needs tokens burned
* @param _amount The amount of tokens being burned
*/
function burn(address _user, uint256 _amount) external;
function owner() external view returns (address);
function balanceOf(address _user) external view returns (uint256);
}// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.27; /// @dev Error for 0x0 address inputs error InvalidZeroInput(); /// @dev Error for already added items to a list error AlreadyAdded(); /// @dev Error for not found items in a list error NotFound(); /// @dev Error for hitting max TVL error MaxTVLReached(); /// @dev Error for caller not having permissions error NotRestakeManagerAdmin(); /// @dev Error for call not coming from deposit queue contract error NotDepositQueue(); /// @dev Error for contract being paused error ContractPaused(); /// @dev Error for exceeding max basis points (100%) error OverMaxBasisPoints(); /// @dev Error for invalid token decimals for collateral tokens (must be 18) error InvalidTokenDecimals(uint8 expected, uint8 actual); /// @dev Error when withdraw is already completed error WithdrawAlreadyCompleted(); /// @dev Error when a different address tries to complete withdraw error NotOriginalWithdrawCaller(address expectedCaller); /// @dev Error when caller does not have OD admin role error NotOperatorDelegatorAdmin(); /// @dev Error when caller does not have Oracle Admin role error NotOracleAdmin(); /// @dev Error when caller is not RestakeManager contract error NotRestakeManager(); /// @dev Errror when caller does not have ETH Restake Admin role error NotNativeEthRestakeAdmin(); /// @dev Error when delegation address was already set - cannot be set again error DelegateAddressAlreadySet(); /// @dev Error when caller does not have ERC20 Rewards Admin role error NotERC20RewardsAdmin(); /// @dev Error when sending ETH fails error TransferFailed(); /// @dev Error when caller does not have ETH Minter Burner Admin role error NotEzETHMinterBurner(); /// @dev Error when caller does not have Token Admin role error NotTokenAdmin(); /// @dev Error when price oracle is not configured error OracleNotFound(); /// @dev Error when price oracle data is stale error OraclePriceExpired(); /// @dev Error when array lengths do not match error MismatchedArrayLengths(); /// @dev Error when caller does not have Deposit Withdraw Pauser role error NotDepositWithdrawPauser(); /// @dev Error when an individual token TVL is over the max error MaxTokenTVLReached(); /// @dev Error when Oracle price is invalid error InvalidOraclePrice(); /// @dev Error when calling an invalid function error NotImplemented(); /// @dev Error when calculating token amounts is invalid error InvalidTokenAmount(); /// @dev Error when timestamp is invalid - likely in the past error InvalidTimestamp(uint256 timestamp); /// @dev Error when trade does not meet minimum output amount error InsufficientOutputAmount(); /// @dev Error when the token received over the bridge is not the one expected error InvalidTokenReceived(); /// @dev Error when the origin address is not whitelisted error InvalidOrigin(); /// @dev Error when the sender is not expected error InvalidSender(address expectedSender, address actualSender); /// @dev error when function returns 0 amount error InvalidZeroOutput(); /// @dev error when xRenzoBridge does not have enough balance to pay for fee error NotEnoughBalance(uint256 currentBalance, uint256 calculatedFees); /// @dev error when source chain is not expected error InvalidSourceChain(uint64 expectedCCIPChainSelector, uint64 actualCCIPChainSelector); /// @dev Error when an unauthorized address tries to call the bridge function on the L2 error UnauthorizedBridgeSweeper(); /// @dev Error when caller does not have BRIDGE_ADMIN role error NotBridgeAdmin(); /// @dev Error when caller does not have PRICE_FEED_SENDER role error NotPriceFeedSender(); /// @dev Error for connext price Feed unauthorised call error UnAuthorisedCall(); /// @dev Error for no price feed configured on L2 error PriceFeedNotAvailable(); /// @dev Error for invalid bridge fee share configuration error InvalidBridgeFeeShare(uint256 bridgeFee); /// @dev Error for invalid sweep batch size error InvalidSweepBatchSize(uint256 batchSize); /// @dev Error when caller does not have Withdraw Queue admin role error NotWithdrawQueueAdmin(); /// @dev Error when caller try to withdraw more than Buffer error NotEnoughWithdrawBuffer(); /// @dev Error when caller try to claim withdraw before cooldown period error EarlyClaim(); /// @dev Error when caller try to withdraw for unsupported asset error UnsupportedWithdrawAsset(); /// @dev Error when caller try to claim invalidWithdrawIndex error InvalidWithdrawIndex(); /// @dev Error when TVL was expected to be 0 error InvalidTVL(); /// @dev Error when incorrect BeaconChainStrategy is set for LST in completeQueuedWithdrawal error IncorrectStrategy(); /// @dev Error when adding new OperatorDelegator which is not delegated error OperatoDelegatorNotDelegated(); /// @dev Error when emergency tracking already tracked withdrawal error WithdrawalAlreadyTracked(); /// @dev Error when emergency tracking already completed withdrawal error WithdrawalAlreadyCompleted(); /// @dev Error when caller does not have Emergency Withdraw Tracking Admin role error NotEmergencyWithdrawTrackingAdmin(); /// @dev Error when strategy does not have specified underlying error InvalidStrategy(); /// @dev Error when strategy already set and hold non zero token balance error NonZeroUnderlyingStrategyExist(); /// @dev Error when caller tried to claim queued withdrawal when not filled error QueuedWithdrawalNotFilled(); /// @dev Error when caller does not have EigenLayerRewardsAdmin role error NotEigenLayerRewardsAdmin(); /// @dev Error when rewardsDestination is not configured while trying to claim error RewardsDestinationNotConfigured(); /// @dev Error when WETHUnwrapper is not configured while trying to claim WETH restaking rewards error WETHUnwrapperNotConfigured(); /// @dev Error when currentCheckpoint is not accounted by OperatorDelegator error CheckpointAlreadyActive(); /// @dev Error when specified checkpoint is already recorded error CheckpointAlreadyRecorded(); /// @dev Error when caller does not have Emergency Checkpoint Tracking admin role error NotEmergencyCheckpointTrackingAdmin(); /// @dev Error when last completed checkpoint on EigenPod is not recorded in OperatorDelegator error CheckpointNotRecorded(); /// @dev Error when non pauser tries to change pause state error NotPauser(); /// @dev Error when user tried to withdraw asset more than available in protocol collateral error NotEnoughCollateralValue(); /// @dev Error when admin tries to disable asset withdraw queue which is not enabled error WithdrawQueueNotEnabled(); /// @dev Error when admin tries to enable erc20 withdraw queue for IS_NATIVE address error IsNativeAddressNotAllowed(); /// @dev Error when admin tried to complete queued withdrawal with receiveAsShares error OnlyReceiveAsTokenAllowed(); /// @dev Error when Withdrawal is not queued error WithdrawalNotQueued(); /// @dev Error when admin tries to track Withdraw of different staker error InvalidStakerAddress(); /// @dev Error when caller does not have Emergency track AVS ETH slashing admin role error NotEmergencyTrackAVSEthSlashingAdmin(); /// @dev Error when below the limit error BelowAllowedLimit(); /// @dev Error when gas refund address is not set in DepositQueue error GasRefundAddressNotSet(); /// @dev Error when withdraw requests are paused. error WithdrawRequestPaused(); /// @dev Error when withdraw claims are paused. error ClaimPaused();
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity 0.8.27;
interface IRateProvider {
function getRate() external view returns (uint256);
}{
"evmVersion": "paris",
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientOutputAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"bridgeFee","type":"uint256"}],"name":"InvalidBridgeFeeShare","type":"error"},{"inputs":[],"name":"InvalidOraclePrice","type":"error"},{"inputs":[{"internalType":"address","name":"expectedSender","type":"address"},{"internalType":"address","name":"actualSender","type":"address"}],"name":"InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"batchSize","type":"uint256"}],"name":"InvalidSweepBatchSize","type":"error"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"InvalidTimestamp","type":"error"},{"inputs":[{"internalType":"uint8","name":"expected","type":"uint8"},{"internalType":"uint8","name":"actual","type":"uint8"}],"name":"InvalidTokenDecimals","type":"error"},{"inputs":[],"name":"InvalidTokenReceived","type":"error"},{"inputs":[],"name":"InvalidZeroInput","type":"error"},{"inputs":[],"name":"InvalidZeroOutput","type":"error"},{"inputs":[],"name":"OracleNotFound","type":"error"},{"inputs":[],"name":"OraclePriceExpired","type":"error"},{"inputs":[],"name":"OverMaxBasisPoints","type":"error"},{"inputs":[],"name":"PriceFeedNotAvailable","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldBridgeFeeCollector","type":"address"},{"indexed":false,"internalType":"address","name":"newBridgeFeeCollector","type":"address"}],"name":"BridgeFeeCollectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldBridgeFeeShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBridgeFeeShare","type":"uint256"}],"name":"BridgeFeeShareUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sweeper","type":"address"}],"name":"BridgeSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFlatBridgeFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFlatBridgeFee","type":"uint256"}],"name":"FlatBridgeFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newReceiver","type":"address"},{"indexed":false,"internalType":"address","name":"oldReceiver","type":"address"}],"name":"ReceiverPriceFeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldSweepBatchSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSweepBatchSize","type":"uint256"}],"name":"SweepBatchSizeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sweeper","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeCollected","type":"uint256"}],"name":"SweeperBridgeFeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"supported","type":"bool"},{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"address","name":"valueTransferBridge","type":"address"}],"name":"TokenSupportUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldDiscount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDiscount","type":"uint256"}],"name":"TokenTimeDiscountUpdated","type":"event"},{"inputs":[],"name":"ETH_NATIVE_TOKEN_ADDRESS","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXPECTED_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BASIS","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_DUST_BRIDGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeFeeShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeTargetAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_minOut","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minOut","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"depositETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"depositTokenSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flatBridgeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"}],"name":"getBridgeFeeShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currentPrice","type":"uint256"},{"internalType":"contract IERC20","name":"_xezETH","type":"address"},{"internalType":"contract IWeth","name":"_weth","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint32","name":"_mainnetDestinationDomain","type":"uint32"},{"internalType":"address","name":"_mainnetRecipient","type":"address"},{"internalType":"address","name":"_bridgeFeeCollector","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPriceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainnetDestinationDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainnetRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"recoverNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridgeFeeCollector","type":"address"}],"name":"setBridgeFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"setReceiverPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"bool","name":"_supported","type":"bool"},{"internalType":"contract AggregatorV3Interface","name":"_tokenOracle","type":"address"},{"internalType":"contract IValueTransferBridge","name":"_valueTransferBridge","type":"address"}],"name":"setSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"sweepBatchSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sweepETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"tokenOracleLookup","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"tokenTimeDiscountBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newShare","type":"uint256"},{"internalType":"uint256","name":"_newFlatFee","type":"uint256"}],"name":"updateBridgeFeeShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"updatePriceByOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newBatchSize","type":"uint256"}],"name":"updateSweepBatchSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_discount","type":"uint256"}],"name":"updateTokenTimeDiscount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"valueTransferBridges","outputs":[{"internalType":"contract IValueTransferBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWeth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xezETH","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6080604052348015600f57600080fd5b506016601a565b60d7565b600054610100900460ff161560855760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161460d5576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6127e1806100e66000396000f3fe60806040526004361061024a5760003560e01c80637de93f9311610139578063b9a43d2f116100b6578063cf94e0051161007a578063cf94e005146106e7578063d47f687714610707578063f20899fc1461070f578063f2fde38b14610737578063f7260d3e14610757578063fe01ef521461077757600080fd5b8063b9a43d2f14610651578063c1e71a3c14610671578063c24de53414610691578063cd3a6c1b146106a7578063ce88b439146106c757600080fd5b80638fe923b4116100fd5780638fe923b4146105b457806396f0bd61146105d45780639f8420b3146105fe578063b397bbde14610611578063b51609b41461063157600080fd5b80637de93f931461052f5780637f79d7211461054557806382367b2d146105605780638686ebcc146105805780638da5cb5b1461059657600080fd5b806346025067116101c75780636976d3571161018b5780636976d3571461046e5780636f49d9f414610484578063715018a6146104ba57806378b7b3ee146104cf57806379ba417d1461050f57600080fd5b806346025067146103c35780634d5bc6a1146103e357806352a70e8f146104195780635d9c64e914610439578063679aefce1461045957600080fd5b8063152b2c4f1161020e578063152b2c4f1461031b57806319ddc3bb1461033b5780633fc8cef31461035b578063402488cf1461037b57806342b14168146103ad57600080fd5b806301681a6214610256578063053f14da1461026b5780630fb5b1661461029457806312f7165f146102b457806314049698146102f457600080fd5b3661025157005b600080fd5b610269610264366004612382565b6107a4565b005b34801561027757600080fd5b5061028160985481565b6040519081526020015b60405180910390f35b3480156102a057600080fd5b506102696102af36600461239f565b610999565b3480156102c057600080fd5b5060a0546102dc9064010000000090046001600160a01b031681565b6040516001600160a01b03909116815260200161028b565b34801561030057600080fd5b50610309601281565b60405160ff909116815260200161028b565b34801561032757600080fd5b506099546102dc906001600160a01b031681565b34801561034757600080fd5b50609b546102dc906001600160a01b031681565b34801561036757600080fd5b50609e546102dc906001600160a01b031681565b34801561038757600080fd5b5060a0546103989063ffffffff1681565b60405163ffffffff909116815260200161028b565b3480156103b957600080fd5b5061028160a55481565b3480156103cf57600080fd5b506102816103de3660046123cf565b6109dc565b3480156103ef57600080fd5b506102dc6103fe366004612382565b609f602052600090815260409020546001600160a01b031681565b34801561042557600080fd5b50610269610434366004612382565b610a31565b34801561044557600080fd5b50610269610454366004612382565b610ac9565b34801561046557600080fd5b50610281610b3a565b34801561047a57600080fd5b50610281609d5481565b34801561049057600080fd5b506102dc61049f366004612382565b60a2602052600090815260409020546001600160a01b031681565b3480156104c657600080fd5b50610269610b7f565b3480156104db57600080fd5b506104ff6104ea366004612382565b60a16020526000908152604090205460ff1681565b604051901515815260200161028b565b34801561051b57600080fd5b5061026961052a3660046123f6565b610b93565b34801561053b57600080fd5b5061028160975481565b34801561055157600080fd5b506102816601c6bf5263400081565b34801561056c57600080fd5b5061026961057b366004612452565b610efa565b34801561058c57600080fd5b5061039861271081565b3480156105a257600080fd5b506033546001600160a01b03166102dc565b3480156105c057600080fd5b506102696105cf366004612474565b610f48565b3480156105e057600080fd5b506105e96112a6565b6040805192835260208301919091520161028b565b61028161060c366004612452565b6112e0565b34801561061d57600080fd5b5061026961062c366004612452565b611426565b34801561063d57600080fd5b5061026961064c36600461250a565b6114d6565b34801561065d57600080fd5b5061026961066c36600461254c565b6114f2565b34801561067d57600080fd5b5061026961068c3660046123cf565b6115bb565b34801561069d57600080fd5b50610281609c5481565b3480156106b357600080fd5b506102696106c23660046123cf565b6115cd565b3480156106d357600080fd5b506102816106e2366004612578565b611643565b3480156106f357600080fd5b5060a3546102dc906001600160a01b031681565b6102696117d1565b34801561071b57600080fd5b506102dc73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561074357600080fd5b50610269610752366004612382565b61199e565b34801561076357600080fd5b50609a546102dc906001600160a01b031681565b34801561078357600080fd5b50610281610792366004612382565b60a46020526000908152604090205481565b6107ac611a14565b6001600160a01b038116600090815260a1602052604090205460ff166107e557604051636d5f86d560e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561082c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085091906125b3565b90506601c6bf526340008111610879576040516342301c2360e01b815260040160405180910390fd5b6001600160a01b038083166000818152609f602052604090205461089e921683611a6d565b6001600160a01b038281166000908152609f60209081526040918290205460a054835163206d3a2d60e21b815263ffffffff82166004820152640100000000909104851660248201526044810186905292519316926381b4e8b49234926064808301939192829003018185885af115801561091d573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061094291906125b3565b50604080516001600160a01b038416815260208101839052338183015290517f0380480a40062171509574a2623e64253440b5de1539c18b58e12ca29f25c7e49181900360600190a1506109966001606555565b50565b6109a1611b5a565b6040516001600160a01b0382169083156108fc029084906000818181858888f193505050501580156109d7573d6000803e3d6000fd5b505050565b6000609d54821015610a165760a554609c54612710906109fc90856125e2565b610a0691906125f9565b610a10919061261b565b92915050565b60a554609c54609d54612710916109fc916125e2565b919050565b610a39611b5a565b6001600160a01b038116610a605760405163862a606760e01b815260040160405180910390fd5b60a354604080516001600160a01b03928316815291831660208301527ffec8889d8ce98c4df9453b0594aa1b8081ed5c49708477f5537c8ece1346a1ee910160405180910390a160a380546001600160a01b0319166001600160a01b0392909216919091179055565b610ad1611b5a565b609a54604080516001600160a01b03808516825290921660208301527f428d03602fe9e8df28220536ffc5e5a7aac3a0bfc5105d5dc602d369dfb8aded910160405180910390a1609a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000806000610b476112a6565b9092509050610b59816201518061261b565b421115610b795760405163757ee0c360e11b815260040160405180910390fd5b50919050565b610b87611b5a565b610b916000611bb4565b565b610b9b611b5a565b6001600160a01b038416610bc25760405163862a606760e01b815260040160405180910390fd5b6001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14801590610c545750836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4c919061262e565b60ff16601214155b15610ce8576012846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbd919061262e565b6040516330946b1f60e21b815260ff9283166004820152911660248201526044015b60405180910390fd5b6001600160a01b038416600090815260a160205260409020805460ff19168415801591909117909155610e65576001600160a01b038216610d3c5760405163862a606760e01b815260040160405180910390fd5b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9e919061262e565b60ff16601214610de8576012826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c99573d6000803e3d6000fd5b6001600160a01b03848116600090815260a26020526040902080546001600160a01b0319168483161790558116610e325760405163862a606760e01b815260040160405180910390fd5b6001600160a01b038481166000908152609f6020526040902080546001600160a01b031916918316919091179055610ea1565b6001600160a01b038416600090815260a26020908152604080832080546001600160a01b0319908116909155609f909252909120805490911690555b604080516001600160a01b0386811682528515156020830152848116828401528316606082015290517fca1fa7efc06e9ca4871ce7deb7fa147fc471ebda3ce1cf3c80a8702bceebbf0a9181900360800190a150505050565b609a546001600160a01b03163314610f3a57609a5460405163708986dd60e11b81526001600160a01b039091166004820152336024820152604401610cdf565b610f448282611c06565b5050565b600054610100900460ff1615808015610f685750600054600160ff909116105b80610f825750303b158015610f82575060005460ff166001145b610fe55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610cdf565b6000805460ff191660011790558015611008576000805461ff0019166101001790555b611010611c57565b611018611c86565b87158061102c57506001600160a01b038716155b8061103e57506001600160a01b038616155b8061105057506001600160a01b038516155b8061105f575063ffffffff8416155b8061107157506001600160a01b038316155b8061108357506001600160a01b038216155b156110a15760405163862a606760e01b815260040160405180910390fd5b6000876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611105919061262e565b905060ff8116601214611137576040516330946b1f60e21b81526012600482015260ff82166024820152604401610cdf565b866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611199919061262e565b905060ff81166012146111cb576040516330946b1f60e21b81526012600482015260ff82166024820152604401610cdf565b50609888905542609755609980546001600160a01b03808a166001600160a01b031992831617909255609e8054898416908316179055609a805488841690831617905560a08054868416640100000000026001600160c01b031990911663ffffffff8916171790556005609c556801bc16d674ec800000609d5560a3805492851692909116919091179055801561129c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b609a5460009081906001600160a01b03166112d457604051634d57188360e01b815260040160405180910390fd5b50506098546097549091565b60006112ea611a14565b3460000361130b5760405163862a606760e01b815260040160405180910390fd5b6000611316346109dc565b905080156113c95760a3546040516000916001600160a01b03169083156108fc0290849084818181858888f19350505050905080611367576040516312171d8360e31b815260040160405180910390fd5b60a354604080516001600160a01b03909216825273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee602083015281018390527f82490425810931636f09288678430bcee6ac1af780bba59c0b5bb8e3b341ed4b9060600160405180910390a1505b60006113d58234612651565b9050806000036113f85760405163862a606760e01b815260040160405180910390fd5b61141873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee828787611cb5565b92505050610a106001606555565b61142e611b5a565b606482111561145357604051630b0f4e1960e31b815260048101839052602401610cdf565b609c5460408051918252602082018490527f079f42df2569d6e6cd52e9b9dbd84ad9b974146635b4ca662d5dcd8578e0e9eb910160405180910390a1609c82905560a55460408051918252602082018390527f32db537d3e45a65ce187544a9dbdf35d05fdb614ba1e7317fed32eed5ca993d0910160405180910390a160a55550565b6114de611b5a565b6109d76001600160a01b0384168284611e56565b6114fa611b5a565b6001600160a01b038216600090815260a1602052604090205460ff1661153357604051636d5f86d560e01b815260040160405180910390fd5b606481111561155557604051636b5c426160e01b815260040160405180910390fd5b6001600160a01b038216600081815260a460209081526040918290208054908590558251938452908301819052908201839052907f06a7b16e1cd57fefd53236c821fcdf6ffb7236c3781c95a9d2091e88595014789060600160405180910390a1505050565b6115c3611b5a565b6109968142611c06565b6115d5611b5a565b6801bc16d674ec8000008110156116025760405163e161281360e01b815260048101829052602401610cdf565b609d5460408051918252602082018390527f637c5126c97274794a6fea58b3806e566782fd7cce9ea7fcfce67e0ac9df5d28910160405180910390a1609d55565b600061164d611a14565b8360000361166e5760405163862a606760e01b815260040160405180910390fd5b6116836001600160a01b038616333087611e86565b600061168e856109dc565b905080156116ff5760a3546116b0906001600160a01b03888116911683611e56565b60a354604080516001600160a01b039283168152918816602083015281018290527f82490425810931636f09288678430bcee6ac1af780bba59c0b5bb8e3b341ed4b9060600160405180910390a15b6117098186612651565b945060006117178787611ebe565b90508060000361173a57604051637c68a38760e11b815260040160405180910390fd5b609e546001600160a01b03908116908816036117af57609e54604051632e1a7d4d60e01b8152600481018890526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561179657600080fd5b505af11580156117aa573d6000803e3d6000fd5b505050505b6117bb87828787611cb5565b925050506117c96001606555565b949350505050565b6117d9611a14565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60005260a16020527fd85c026c2b25704f97c7f785e418ad5664b345fdc5df7f9ae196ff38745078ee5460ff1661183857604051636d5f86d560e01b815260040160405180910390fd5b60006118443447612651565b90506601c6bf52634000811161186d576040516342301c2360e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee600052609f60209081527f3848fe4f5e8723ffa5fe57fb0750643358f0b1cde73045ea23719944173aaf675460a0546040805163206d3a2d60e21b815263ffffffff831660048201526401000000009092046001600160a01b0390811660248401526044830186905290519216926381b4e8b49247926064808201939291829003018185885af115801561191a573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061193f91906125b3565b506040805173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee815260208101839052338183015290517f0380480a40062171509574a2623e64253440b5de1539c18b58e12ca29f25c7e49181900360600190a150610b916001606555565b6119a6611b5a565b6001600160a01b038116611a0b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610cdf565b61099681611bb4565b600260655403611a665760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cdf565b6002606555565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae191906125b3565b9050611b4d8463095ea7b360e01b85611afa868661261b565b6040516001600160a01b03909216602483015260448201526064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611fdb565b50505050565b6001606555565b6033546001600160a01b03163314610b915760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610cdf565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611c1082826120b0565b6098829055609781905560408051838152602081018390527f945c1c4e99aa89f648fbfe3df471b916f719e16d960fcec0737d4d56bd696838910160405180910390a15050565b600054610100900460ff16611c7e5760405162461bcd60e51b8152600401610cdf90612664565b610b916121ba565b600054610100900460ff16611cad5760405162461bcd60e51b8152600401610cdf90612664565b610b916121ea565b6001600160a01b038416600090815260a1602052604081205460ff16611cee57604051636d5f86d560e01b815260040160405180910390fd5b6000611cfa8686612211565b9050611d068186612651565b9450600080611d136112a6565b9092509050611d25816201518061261b565b421115611d455760405163757ee0c360e11b815260040160405180910390fd5b600082611d5a89670de0b6b3a76400006125e2565b611d6491906125f9565b905086811015611d87576040516342301c2360e01b815260040160405180910390fd5b85421115611dab576040516304b8410560e31b815260048101879052602401610cdf565b6099546040516340c10f1960e01b8152336004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b158015611df757600080fd5b505af1158015611e0b573d6000803e3d6000fd5b5050604080518b8152602081018590523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1592500160405180910390a298975050505050505050565b6040516001600160a01b0383166024820152604481018290526109d790849063a9059cbb60e01b90606401611b16565b6040516001600160a01b0380851660248301528316604482015260648101829052611b4d9085906323b872dd60e01b90608401611b16565b6001600160a01b03808316600090815260a2602052604081205490911680611ef957604051630b0a0e0d60e21b815260040160405180910390fd5b600080826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e91906126c9565b509350509250508062015180611f74919061261b565b421115611f945760405163757ee0c360e11b815260040160405180910390fd5b60008213611fb45760405162fc7cad60e51b815260040160405180910390fd5b670de0b6b3a7640000611fc783876125e2565b611fd191906125f9565b9695505050505050565b6000612030826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661224a9092919063ffffffff16565b9050805160001480612051575080806020019051810190612051919061271b565b6109d75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cdf565b816000036120d15760405163862a606760e01b815260040160405180910390fd5b670de0b6b3a76400008210156120f95760405162fc7cad60e51b815260040160405180910390fd5b609854821180156121235750606460985461211491906125f9565b6098546121219084612651565b115b806121545750609854821080156121545750606460985461214491906125f9565b826098546121529190612651565b115b156121715760405162fc7cad60e51b815260040160405180910390fd5b6097548111612196576040516304b8410560e31b815260048101829052602401610cdf565b42811115610f44576040516304b8410560e31b815260048101829052602401610cdf565b600054610100900460ff166121e15760405162461bcd60e51b8152600401610cdf90612664565b610b9133611bb4565b600054610100900460ff16611b535760405162461bcd60e51b8152600401610cdf90612664565b6001600160a01b038216600090815260a46020526040812054612710906122399084906125e2565b61224391906125f9565b9392505050565b60606117c9848460008585600080866001600160a01b03168587604051612271919061275c565b60006040518083038185875af1925050503d80600081146122ae576040519150601f19603f3d011682016040523d82523d6000602084013e6122b3565b606091505b50915091506122c4878383876122cf565b979650505050505050565b6060831561233e578251600003612337576001600160a01b0385163b6123375760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cdf565b50816117c9565b6117c983838151156123535781518083602001fd5b8060405162461bcd60e51b8152600401610cdf9190612778565b6001600160a01b038116811461099657600080fd5b60006020828403121561239457600080fd5b81356122438161236d565b600080604083850312156123b257600080fd5b8235915060208301356123c48161236d565b809150509250929050565b6000602082840312156123e157600080fd5b5035919050565b801515811461099657600080fd5b6000806000806080858703121561240c57600080fd5b84356124178161236d565b93506020850135612427816123e8565b925060408501356124378161236d565b915060608501356124478161236d565b939692955090935050565b6000806040838503121561246557600080fd5b50508035926020909101359150565b600080600080600080600060e0888a03121561248f57600080fd5b8735965060208801356124a18161236d565b955060408801356124b18161236d565b945060608801356124c18161236d565b9350608088013563ffffffff811681146124da57600080fd5b925060a08801356124ea8161236d565b915060c08801356124fa8161236d565b8091505092959891949750929550565b60008060006060848603121561251f57600080fd5b833561252a8161236d565b92506020840135915060408401356125418161236d565b809150509250925092565b6000806040838503121561255f57600080fd5b823561256a8161236d565b946020939093013593505050565b6000806000806080858703121561258e57600080fd5b84356125998161236d565b966020860135965060408601359560600135945092505050565b6000602082840312156125c557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610a1057610a106125cc565b60008261261657634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610a1057610a106125cc565b60006020828403121561264057600080fd5b815160ff8116811461224357600080fd5b81810381811115610a1057610a106125cc565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b805169ffffffffffffffffffff81168114610a2c57600080fd5b600080600080600060a086880312156126e157600080fd5b6126ea866126af565b6020870151604088015160608901519297509095509350915061270f608087016126af565b90509295509295909350565b60006020828403121561272d57600080fd5b8151612243816123e8565b60005b8381101561275357818101518382015260200161273b565b50506000910152565b6000825161276e818460208701612738565b9190910192915050565b6020815260008251806020840152612797816040850160208701612738565b601f01601f1916919091016040019291505056fea264697066735822122011b52de46d8bc92b51a85beb77b8944fbe693f7fc2e216e71f20c740d8a4168d64736f6c634300081b0033
Deployed Bytecode
0x60806040526004361061024a5760003560e01c80637de93f9311610139578063b9a43d2f116100b6578063cf94e0051161007a578063cf94e005146106e7578063d47f687714610707578063f20899fc1461070f578063f2fde38b14610737578063f7260d3e14610757578063fe01ef521461077757600080fd5b8063b9a43d2f14610651578063c1e71a3c14610671578063c24de53414610691578063cd3a6c1b146106a7578063ce88b439146106c757600080fd5b80638fe923b4116100fd5780638fe923b4146105b457806396f0bd61146105d45780639f8420b3146105fe578063b397bbde14610611578063b51609b41461063157600080fd5b80637de93f931461052f5780637f79d7211461054557806382367b2d146105605780638686ebcc146105805780638da5cb5b1461059657600080fd5b806346025067116101c75780636976d3571161018b5780636976d3571461046e5780636f49d9f414610484578063715018a6146104ba57806378b7b3ee146104cf57806379ba417d1461050f57600080fd5b806346025067146103c35780634d5bc6a1146103e357806352a70e8f146104195780635d9c64e914610439578063679aefce1461045957600080fd5b8063152b2c4f1161020e578063152b2c4f1461031b57806319ddc3bb1461033b5780633fc8cef31461035b578063402488cf1461037b57806342b14168146103ad57600080fd5b806301681a6214610256578063053f14da1461026b5780630fb5b1661461029457806312f7165f146102b457806314049698146102f457600080fd5b3661025157005b600080fd5b610269610264366004612382565b6107a4565b005b34801561027757600080fd5b5061028160985481565b6040519081526020015b60405180910390f35b3480156102a057600080fd5b506102696102af36600461239f565b610999565b3480156102c057600080fd5b5060a0546102dc9064010000000090046001600160a01b031681565b6040516001600160a01b03909116815260200161028b565b34801561030057600080fd5b50610309601281565b60405160ff909116815260200161028b565b34801561032757600080fd5b506099546102dc906001600160a01b031681565b34801561034757600080fd5b50609b546102dc906001600160a01b031681565b34801561036757600080fd5b50609e546102dc906001600160a01b031681565b34801561038757600080fd5b5060a0546103989063ffffffff1681565b60405163ffffffff909116815260200161028b565b3480156103b957600080fd5b5061028160a55481565b3480156103cf57600080fd5b506102816103de3660046123cf565b6109dc565b3480156103ef57600080fd5b506102dc6103fe366004612382565b609f602052600090815260409020546001600160a01b031681565b34801561042557600080fd5b50610269610434366004612382565b610a31565b34801561044557600080fd5b50610269610454366004612382565b610ac9565b34801561046557600080fd5b50610281610b3a565b34801561047a57600080fd5b50610281609d5481565b34801561049057600080fd5b506102dc61049f366004612382565b60a2602052600090815260409020546001600160a01b031681565b3480156104c657600080fd5b50610269610b7f565b3480156104db57600080fd5b506104ff6104ea366004612382565b60a16020526000908152604090205460ff1681565b604051901515815260200161028b565b34801561051b57600080fd5b5061026961052a3660046123f6565b610b93565b34801561053b57600080fd5b5061028160975481565b34801561055157600080fd5b506102816601c6bf5263400081565b34801561056c57600080fd5b5061026961057b366004612452565b610efa565b34801561058c57600080fd5b5061039861271081565b3480156105a257600080fd5b506033546001600160a01b03166102dc565b3480156105c057600080fd5b506102696105cf366004612474565b610f48565b3480156105e057600080fd5b506105e96112a6565b6040805192835260208301919091520161028b565b61028161060c366004612452565b6112e0565b34801561061d57600080fd5b5061026961062c366004612452565b611426565b34801561063d57600080fd5b5061026961064c36600461250a565b6114d6565b34801561065d57600080fd5b5061026961066c36600461254c565b6114f2565b34801561067d57600080fd5b5061026961068c3660046123cf565b6115bb565b34801561069d57600080fd5b50610281609c5481565b3480156106b357600080fd5b506102696106c23660046123cf565b6115cd565b3480156106d357600080fd5b506102816106e2366004612578565b611643565b3480156106f357600080fd5b5060a3546102dc906001600160a01b031681565b6102696117d1565b34801561071b57600080fd5b506102dc73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561074357600080fd5b50610269610752366004612382565b61199e565b34801561076357600080fd5b50609a546102dc906001600160a01b031681565b34801561078357600080fd5b50610281610792366004612382565b60a46020526000908152604090205481565b6107ac611a14565b6001600160a01b038116600090815260a1602052604090205460ff166107e557604051636d5f86d560e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561082c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085091906125b3565b90506601c6bf526340008111610879576040516342301c2360e01b815260040160405180910390fd5b6001600160a01b038083166000818152609f602052604090205461089e921683611a6d565b6001600160a01b038281166000908152609f60209081526040918290205460a054835163206d3a2d60e21b815263ffffffff82166004820152640100000000909104851660248201526044810186905292519316926381b4e8b49234926064808301939192829003018185885af115801561091d573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061094291906125b3565b50604080516001600160a01b038416815260208101839052338183015290517f0380480a40062171509574a2623e64253440b5de1539c18b58e12ca29f25c7e49181900360600190a1506109966001606555565b50565b6109a1611b5a565b6040516001600160a01b0382169083156108fc029084906000818181858888f193505050501580156109d7573d6000803e3d6000fd5b505050565b6000609d54821015610a165760a554609c54612710906109fc90856125e2565b610a0691906125f9565b610a10919061261b565b92915050565b60a554609c54609d54612710916109fc916125e2565b919050565b610a39611b5a565b6001600160a01b038116610a605760405163862a606760e01b815260040160405180910390fd5b60a354604080516001600160a01b03928316815291831660208301527ffec8889d8ce98c4df9453b0594aa1b8081ed5c49708477f5537c8ece1346a1ee910160405180910390a160a380546001600160a01b0319166001600160a01b0392909216919091179055565b610ad1611b5a565b609a54604080516001600160a01b03808516825290921660208301527f428d03602fe9e8df28220536ffc5e5a7aac3a0bfc5105d5dc602d369dfb8aded910160405180910390a1609a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000806000610b476112a6565b9092509050610b59816201518061261b565b421115610b795760405163757ee0c360e11b815260040160405180910390fd5b50919050565b610b87611b5a565b610b916000611bb4565b565b610b9b611b5a565b6001600160a01b038416610bc25760405163862a606760e01b815260040160405180910390fd5b6001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14801590610c545750836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4c919061262e565b60ff16601214155b15610ce8576012846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbd919061262e565b6040516330946b1f60e21b815260ff9283166004820152911660248201526044015b60405180910390fd5b6001600160a01b038416600090815260a160205260409020805460ff19168415801591909117909155610e65576001600160a01b038216610d3c5760405163862a606760e01b815260040160405180910390fd5b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9e919061262e565b60ff16601214610de8576012826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c99573d6000803e3d6000fd5b6001600160a01b03848116600090815260a26020526040902080546001600160a01b0319168483161790558116610e325760405163862a606760e01b815260040160405180910390fd5b6001600160a01b038481166000908152609f6020526040902080546001600160a01b031916918316919091179055610ea1565b6001600160a01b038416600090815260a26020908152604080832080546001600160a01b0319908116909155609f909252909120805490911690555b604080516001600160a01b0386811682528515156020830152848116828401528316606082015290517fca1fa7efc06e9ca4871ce7deb7fa147fc471ebda3ce1cf3c80a8702bceebbf0a9181900360800190a150505050565b609a546001600160a01b03163314610f3a57609a5460405163708986dd60e11b81526001600160a01b039091166004820152336024820152604401610cdf565b610f448282611c06565b5050565b600054610100900460ff1615808015610f685750600054600160ff909116105b80610f825750303b158015610f82575060005460ff166001145b610fe55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610cdf565b6000805460ff191660011790558015611008576000805461ff0019166101001790555b611010611c57565b611018611c86565b87158061102c57506001600160a01b038716155b8061103e57506001600160a01b038616155b8061105057506001600160a01b038516155b8061105f575063ffffffff8416155b8061107157506001600160a01b038316155b8061108357506001600160a01b038216155b156110a15760405163862a606760e01b815260040160405180910390fd5b6000876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611105919061262e565b905060ff8116601214611137576040516330946b1f60e21b81526012600482015260ff82166024820152604401610cdf565b866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611199919061262e565b905060ff81166012146111cb576040516330946b1f60e21b81526012600482015260ff82166024820152604401610cdf565b50609888905542609755609980546001600160a01b03808a166001600160a01b031992831617909255609e8054898416908316179055609a805488841690831617905560a08054868416640100000000026001600160c01b031990911663ffffffff8916171790556005609c556801bc16d674ec800000609d5560a3805492851692909116919091179055801561129c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b609a5460009081906001600160a01b03166112d457604051634d57188360e01b815260040160405180910390fd5b50506098546097549091565b60006112ea611a14565b3460000361130b5760405163862a606760e01b815260040160405180910390fd5b6000611316346109dc565b905080156113c95760a3546040516000916001600160a01b03169083156108fc0290849084818181858888f19350505050905080611367576040516312171d8360e31b815260040160405180910390fd5b60a354604080516001600160a01b03909216825273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee602083015281018390527f82490425810931636f09288678430bcee6ac1af780bba59c0b5bb8e3b341ed4b9060600160405180910390a1505b60006113d58234612651565b9050806000036113f85760405163862a606760e01b815260040160405180910390fd5b61141873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee828787611cb5565b92505050610a106001606555565b61142e611b5a565b606482111561145357604051630b0f4e1960e31b815260048101839052602401610cdf565b609c5460408051918252602082018490527f079f42df2569d6e6cd52e9b9dbd84ad9b974146635b4ca662d5dcd8578e0e9eb910160405180910390a1609c82905560a55460408051918252602082018390527f32db537d3e45a65ce187544a9dbdf35d05fdb614ba1e7317fed32eed5ca993d0910160405180910390a160a55550565b6114de611b5a565b6109d76001600160a01b0384168284611e56565b6114fa611b5a565b6001600160a01b038216600090815260a1602052604090205460ff1661153357604051636d5f86d560e01b815260040160405180910390fd5b606481111561155557604051636b5c426160e01b815260040160405180910390fd5b6001600160a01b038216600081815260a460209081526040918290208054908590558251938452908301819052908201839052907f06a7b16e1cd57fefd53236c821fcdf6ffb7236c3781c95a9d2091e88595014789060600160405180910390a1505050565b6115c3611b5a565b6109968142611c06565b6115d5611b5a565b6801bc16d674ec8000008110156116025760405163e161281360e01b815260048101829052602401610cdf565b609d5460408051918252602082018390527f637c5126c97274794a6fea58b3806e566782fd7cce9ea7fcfce67e0ac9df5d28910160405180910390a1609d55565b600061164d611a14565b8360000361166e5760405163862a606760e01b815260040160405180910390fd5b6116836001600160a01b038616333087611e86565b600061168e856109dc565b905080156116ff5760a3546116b0906001600160a01b03888116911683611e56565b60a354604080516001600160a01b039283168152918816602083015281018290527f82490425810931636f09288678430bcee6ac1af780bba59c0b5bb8e3b341ed4b9060600160405180910390a15b6117098186612651565b945060006117178787611ebe565b90508060000361173a57604051637c68a38760e11b815260040160405180910390fd5b609e546001600160a01b03908116908816036117af57609e54604051632e1a7d4d60e01b8152600481018890526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561179657600080fd5b505af11580156117aa573d6000803e3d6000fd5b505050505b6117bb87828787611cb5565b925050506117c96001606555565b949350505050565b6117d9611a14565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60005260a16020527fd85c026c2b25704f97c7f785e418ad5664b345fdc5df7f9ae196ff38745078ee5460ff1661183857604051636d5f86d560e01b815260040160405180910390fd5b60006118443447612651565b90506601c6bf52634000811161186d576040516342301c2360e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee600052609f60209081527f3848fe4f5e8723ffa5fe57fb0750643358f0b1cde73045ea23719944173aaf675460a0546040805163206d3a2d60e21b815263ffffffff831660048201526401000000009092046001600160a01b0390811660248401526044830186905290519216926381b4e8b49247926064808201939291829003018185885af115801561191a573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061193f91906125b3565b506040805173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee815260208101839052338183015290517f0380480a40062171509574a2623e64253440b5de1539c18b58e12ca29f25c7e49181900360600190a150610b916001606555565b6119a6611b5a565b6001600160a01b038116611a0b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610cdf565b61099681611bb4565b600260655403611a665760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cdf565b6002606555565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae191906125b3565b9050611b4d8463095ea7b360e01b85611afa868661261b565b6040516001600160a01b03909216602483015260448201526064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611fdb565b50505050565b6001606555565b6033546001600160a01b03163314610b915760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610cdf565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611c1082826120b0565b6098829055609781905560408051838152602081018390527f945c1c4e99aa89f648fbfe3df471b916f719e16d960fcec0737d4d56bd696838910160405180910390a15050565b600054610100900460ff16611c7e5760405162461bcd60e51b8152600401610cdf90612664565b610b916121ba565b600054610100900460ff16611cad5760405162461bcd60e51b8152600401610cdf90612664565b610b916121ea565b6001600160a01b038416600090815260a1602052604081205460ff16611cee57604051636d5f86d560e01b815260040160405180910390fd5b6000611cfa8686612211565b9050611d068186612651565b9450600080611d136112a6565b9092509050611d25816201518061261b565b421115611d455760405163757ee0c360e11b815260040160405180910390fd5b600082611d5a89670de0b6b3a76400006125e2565b611d6491906125f9565b905086811015611d87576040516342301c2360e01b815260040160405180910390fd5b85421115611dab576040516304b8410560e31b815260048101879052602401610cdf565b6099546040516340c10f1960e01b8152336004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b158015611df757600080fd5b505af1158015611e0b573d6000803e3d6000fd5b5050604080518b8152602081018590523393507f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1592500160405180910390a298975050505050505050565b6040516001600160a01b0383166024820152604481018290526109d790849063a9059cbb60e01b90606401611b16565b6040516001600160a01b0380851660248301528316604482015260648101829052611b4d9085906323b872dd60e01b90608401611b16565b6001600160a01b03808316600090815260a2602052604081205490911680611ef957604051630b0a0e0d60e21b815260040160405180910390fd5b600080826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e91906126c9565b509350509250508062015180611f74919061261b565b421115611f945760405163757ee0c360e11b815260040160405180910390fd5b60008213611fb45760405162fc7cad60e51b815260040160405180910390fd5b670de0b6b3a7640000611fc783876125e2565b611fd191906125f9565b9695505050505050565b6000612030826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661224a9092919063ffffffff16565b9050805160001480612051575080806020019051810190612051919061271b565b6109d75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cdf565b816000036120d15760405163862a606760e01b815260040160405180910390fd5b670de0b6b3a76400008210156120f95760405162fc7cad60e51b815260040160405180910390fd5b609854821180156121235750606460985461211491906125f9565b6098546121219084612651565b115b806121545750609854821080156121545750606460985461214491906125f9565b826098546121529190612651565b115b156121715760405162fc7cad60e51b815260040160405180910390fd5b6097548111612196576040516304b8410560e31b815260048101829052602401610cdf565b42811115610f44576040516304b8410560e31b815260048101829052602401610cdf565b600054610100900460ff166121e15760405162461bcd60e51b8152600401610cdf90612664565b610b9133611bb4565b600054610100900460ff16611b535760405162461bcd60e51b8152600401610cdf90612664565b6001600160a01b038216600090815260a46020526040812054612710906122399084906125e2565b61224391906125f9565b9392505050565b60606117c9848460008585600080866001600160a01b03168587604051612271919061275c565b60006040518083038185875af1925050503d80600081146122ae576040519150601f19603f3d011682016040523d82523d6000602084013e6122b3565b606091505b50915091506122c4878383876122cf565b979650505050505050565b6060831561233e578251600003612337576001600160a01b0385163b6123375760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cdf565b50816117c9565b6117c983838151156123535781518083602001fd5b8060405162461bcd60e51b8152600401610cdf9190612778565b6001600160a01b038116811461099657600080fd5b60006020828403121561239457600080fd5b81356122438161236d565b600080604083850312156123b257600080fd5b8235915060208301356123c48161236d565b809150509250929050565b6000602082840312156123e157600080fd5b5035919050565b801515811461099657600080fd5b6000806000806080858703121561240c57600080fd5b84356124178161236d565b93506020850135612427816123e8565b925060408501356124378161236d565b915060608501356124478161236d565b939692955090935050565b6000806040838503121561246557600080fd5b50508035926020909101359150565b600080600080600080600060e0888a03121561248f57600080fd5b8735965060208801356124a18161236d565b955060408801356124b18161236d565b945060608801356124c18161236d565b9350608088013563ffffffff811681146124da57600080fd5b925060a08801356124ea8161236d565b915060c08801356124fa8161236d565b8091505092959891949750929550565b60008060006060848603121561251f57600080fd5b833561252a8161236d565b92506020840135915060408401356125418161236d565b809150509250925092565b6000806040838503121561255f57600080fd5b823561256a8161236d565b946020939093013593505050565b6000806000806080858703121561258e57600080fd5b84356125998161236d565b966020860135965060408601359560600135945092505050565b6000602082840312156125c557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610a1057610a106125cc565b60008261261657634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610a1057610a106125cc565b60006020828403121561264057600080fd5b815160ff8116811461224357600080fd5b81810381811115610a1057610a106125cc565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b805169ffffffffffffffffffff81168114610a2c57600080fd5b600080600080600060a086880312156126e157600080fd5b6126ea866126af565b6020870151604088015160608901519297509095509350915061270f608087016126af565b90509295509295909350565b60006020828403121561272d57600080fd5b8151612243816123e8565b60005b8381101561275357818101518382015260200161273b565b50506000910152565b6000825161276e818460208701612738565b9190910192915050565b6020815260008251806020840152612797816040850160208701612738565b601f01601f1916919091016040019291505056fea264697066735822122011b52de46d8bc92b51a85beb77b8944fbe693f7fc2e216e71f20c740d8a4168d64736f6c634300081b0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 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.