Source Code
Overview
S Balance
More Info
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 18 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
24779322 | 23 hrs ago | 0 S | ||||
24779322 | 23 hrs ago | 0 S | ||||
24283483 | 3 days ago | 0 S | ||||
24283483 | 3 days ago | 0 S | ||||
24283483 | 3 days ago | 0 S | ||||
24281578 | 3 days ago | 0 S | ||||
24281578 | 3 days ago | 0 S | ||||
24281578 | 3 days ago | 0 S | ||||
21737536 | 14 days ago | 0 S | ||||
21737432 | 14 days ago | 0 S | ||||
21737432 | 14 days ago | 0 S | ||||
21737432 | 14 days ago | 0 S | ||||
21737020 | 14 days ago | 0 S | ||||
21737020 | 14 days ago | 0 S | ||||
21737020 | 14 days ago | 0 S | ||||
21732405 | 14 days ago | 0 S | ||||
21732314 | 14 days ago | 0 S | ||||
21732146 | 14 days ago | 0 S |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
VaultToken
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./IRateLimits.sol"; import "@contracts/xTokenManager/XToken.sol"; contract VaultToken is XToken { using SafeERC20 for IERC20; struct TokenInfo { uint8 decimals; // Decimals of the underlying token uint256 depositFee; // Fee in basis points (e.g., 50 = 0.5%) uint256 withdrawalFee; // Fee in basis points (e.g., 50 = 0.5%) uint256 maxDeposit; // Maximum allowable cumulative deposit for this token bool isSupported; // Whether the token is supported } mapping(address => TokenInfo) public tokenInfo; address[] public supportedTokens; uint256 public constant FEE_DENOMINATOR = 10000; // Basis points denominator (10000 = 100%) address public feeRecipient; // Address to receive claimable fees IRateLimits public rateLimits; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize( string memory name, string memory symbol, address _feeRecipient, IRateLimits _rateLimits, address _xTokenManager ) public initializer { __ERC20_init(name, symbol); __Ownable_init(msg.sender); __UUPSUpgradeable_init(); feeRecipient = _feeRecipient; rateLimits = _rateLimits; xTokenManager = _xTokenManager; } function setRateLimits(IRateLimits _rateLimits) external onlyOwner { rateLimits = _rateLimits; } /// @dev UUPS authorization mechanism for upgrades function _authorizeUpgrade( address newImplementation ) internal override onlyOwner {} function getImplementation() external view returns (address) { return ERC1967Utils.getImplementation(); } function _update( address from, address to, uint256 value ) internal override { super._update(from, to, value); rateLimits.update( from, to, balanceOf(from), balanceOf(to), value, totalSupply() ); } function removeSupportedToken(address token) external onlyOwner { require(tokenInfo[token].isSupported, "Token not supported"); delete tokenInfo[token]; for (uint256 i = 0; i < supportedTokens.length; i++) { if (supportedTokens[i] == token) { supportedTokens[i] = supportedTokens[supportedTokens.length - 1]; supportedTokens.pop(); break; } } } function addSupportedToken( address token, uint8 decimals, uint256 depositFee, uint256 withdrawalFee, uint256 maxDeposit ) external onlyOwner { require(!tokenInfo[token].isSupported, "Token already supported"); require(depositFee <= FEE_DENOMINATOR, "Invalid deposit fee"); require(withdrawalFee <= FEE_DENOMINATOR, "Invalid withdrawal fee"); tokenInfo[token] = TokenInfo({ decimals: decimals, depositFee: depositFee, withdrawalFee: withdrawalFee, maxDeposit: maxDeposit, isSupported: true }); supportedTokens.push(token); } function updateToken( address token, uint256 depositFee, uint256 withdrawalFee, uint256 maxDeposit ) external onlyOwner { require(tokenInfo[token].isSupported, "Token not supported"); require(depositFee <= FEE_DENOMINATOR, "Invalid deposit fee"); require(withdrawalFee <= FEE_DENOMINATOR, "Invalid withdrawal fee"); tokenInfo[token].depositFee = depositFee; tokenInfo[token].withdrawalFee = withdrawalFee; tokenInfo[token].maxDeposit = maxDeposit; } function setFeeRecipient(address _feeRecipient) external onlyOwner { require(_feeRecipient != address(0), "Invalid fee recipient"); feeRecipient = _feeRecipient; } function setMaxDeposit( address token, uint256 maxDeposit ) external onlyOwner { require(tokenInfo[token].isSupported, "Token not supported"); tokenInfo[token].maxDeposit = maxDeposit; } function deposit(address token, uint256 amount) external { TokenInfo storage info = tokenInfo[token]; require(info.isSupported, "Unsupported token"); require(amount > 0, "Amount must be greater than zero"); // Check if the total deposits would exceed maxDeposit uint256 currentBalance = IERC20(token).balanceOf(address(this)); require( currentBalance + amount <= info.maxDeposit, "Deposit exceeds maximum allowable total deposits" ); // Transfer the token to the contract IERC20(token).safeTransferFrom(msg.sender, address(this), amount); // Adjust for token decimals uint256 netAmount = translateIncomingDecimals(info.decimals, amount); // Apply deposit fee if (info.depositFee != 0) { uint256 fee = (netAmount * info.depositFee) / FEE_DENOMINATOR; _mint(feeRecipient, fee); netAmount -= fee; } // Mint wrapped token to the user _mint(msg.sender, netAmount); } function withdraw(address token, uint256 amount) external { TokenInfo storage info = tokenInfo[token]; require(info.isSupported, "Unsupported token"); require(amount > 0, "Amount must be greater than zero"); // Burn wrapped token from the user _burn(msg.sender, amount); // Apply withdrawal fee uint256 netAmount = amount; if (info.withdrawalFee != 0) { uint256 fee = (amount * info.withdrawalFee) / FEE_DENOMINATOR; _mint(feeRecipient, fee); netAmount -= fee; } // Adjust for token decimals uint256 grossAmount = translateOutGoingDecimals( info.decimals, netAmount ); // Transfer the token back to the user IERC20(token).safeTransfer(msg.sender, grossAmount); } function translateIncomingDecimals( uint8 decimals, uint256 amount ) internal pure returns (uint256) { if (decimals <= 18) { return amount * (10 ** (18 - decimals)); } else { return amount / (10 ** (decimals - 18)); } } function translateOutGoingDecimals( uint8 decimals, uint256 amount ) internal pure returns (uint256) { if (decimals <= 18) { return amount / (10 ** (18 - decimals)); } else { return amount * (10 ** (decimals - 18)); } } function getVaultReserves() external view returns (address[] memory, uint256[] memory) { uint256[] memory balances = new uint256[](supportedTokens.length); for (uint256 i = 0; i < supportedTokens.length; i++) { balances[i] = IERC20(supportedTokens[i]).balanceOf(address(this)); } return (supportedTokens, balances); } function getAllTokenInfo() external view returns (address[] memory, TokenInfo[] memory, uint256[] memory) { uint256 length = supportedTokens.length; TokenInfo[] memory infos = new TokenInfo[](length); uint256[] memory reserves = new uint256[](length); for (uint256 i = 0; i < length; i++) { address token = supportedTokens[i]; infos[i] = tokenInfo[token]; reserves[i] = IERC20(token).balanceOf(address(this)); } return (supportedTokens, infos, reserves); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol"; import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC-20 * applications. */ abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors { /// @custom:storage-location erc7201:openzeppelin.storage.ERC20 struct ERC20Storage { mapping(address account => uint256) _balances; mapping(address account => mapping(address spender => uint256)) _allowances; uint256 _totalSupply; string _name; string _symbol; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; function _getERC20Storage() private pure returns (ERC20Storage storage $) { assembly { $.slot := ERC20StorageLocation } } /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC20Storage storage $ = _getERC20Storage(); $._name = name_; $._symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows $._totalSupply += value; } else { uint256 fromBalance = $._balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. $._balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. $._totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. $._balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * * ```solidity * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } $._allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 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 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, 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. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @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. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @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 silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @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 Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._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 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._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() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @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 { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../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. * * The initial owner is set to the address provided by the deployer. 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 { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC-1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0; interface IRateLimits { function update( address from, address to, uint256 value, uint256 supply, uint256 fromBalance, uint256 toBalance ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import "@openzeppelin-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; interface IXToken { // Debit tokens from a user. function debit( address account, uint256 amount, uint256 dstChainId, bytes memory dstToken ) external; // Credit tokens to a user. function credit( uint256 srcChainId, bytes memory srcToken, address account, uint256 amount ) external; } abstract contract XToken is ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable, IXToken { address public xTokenManager; mapping(uint256 => mapping(bytes => uint256)) public maxDebit; mapping(uint256 => mapping(bytes => uint256)) public currentDebit; modifier onlyXTokenManager() { require(msg.sender == xTokenManager); _; } /** * @dev Set xTokenManager * @param _xTokenManager The max allowed to be transferred to that chain and token */ function setXTokenManager( address _xTokenManager ) external onlyOwner { xTokenManager = _xTokenManager; } /** * @dev Set max amount that can be bridges to a specific token. * Can only be called by the Owner * @param chainId ChainId of token * @param token token address on the target chain * @param limit The max allowed to be transferred to that chain and token */ function setMaxDebit( uint256 chainId, bytes memory token, uint256 limit ) external onlyOwner { maxDebit[chainId][token] = limit; } /** * @dev Configured the current debit to a specific chain, if token already has a supply on that chain. * Can only be called by the Owner * @param chainId ChainId of token * @param token token address on the target chain * @param amount The max amount that can be used to mint this token without more debits first. */ function setDebit( uint256 chainId, bytes memory token, uint256 amount ) external onlyOwner { currentDebit[chainId][token] = amount; } /** * @dev Debit tokens from a user. * Can only be called by the bridge contract. * @param account Address of the account to debit. * @param amount Amount of tokens to debit. * @param dstChainId The destination chain id. * @param dstToken Destination token. */ function debit( address account, uint256 amount, uint256 dstChainId, bytes memory dstToken ) external override onlyXTokenManager { uint256 _debit = currentDebit[dstChainId][dstToken]; _debit += amount; require(_debit <= maxDebit[dstChainId][dstToken], "Amount exceeds total debit for target token"); currentDebit[dstChainId][dstToken] = _debit; _burn(account, amount); } /** * @dev Credit tokens to a user. * Can only be called by the bridge contract. * @param srcChainId ID of the source chain. * @param srcToken Address of the token on the source chain. * @param account Address of the account to credit. * @param amount Amount of tokens to credit. */ function credit( uint256 srcChainId, bytes memory srcToken, address account, uint256 amount ) external override onlyXTokenManager { uint256 _currentDebit = currentDebit[srcChainId][srcToken]; require(_currentDebit > amount, "This token has no available debit"); currentDebit[srcChainId][srcToken] = _currentDebit - amount; _mint(account, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) 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 assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.21; import {IBeacon} from "../beacon/IBeacon.sol"; import {IERC1967} from "../../interfaces/IERC1967.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This library provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots. */ library ERC1967Utils { /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit IERC1967.Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit IERC1967.AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the ERC-1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit IERC1967.BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.20; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC-1967 implementation slot: * ```solidity * contract ERC1967 { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "@pythnetwork/=lib/pyth-sdk-solidity/", "@money-market/=contracts/moneyMarket/src/", "@money-market-scripts/=contracts/moneyMarket/scripts/", "@money-market-tests/=contracts/moneyMarket/tests/", "@contracts/=contracts/", "solidity-utils/=lib/solidity-utils/src/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "ds-test/=lib/solmate/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/", "pyth-sdk-solidity/=lib/pyth-sdk-solidity/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"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":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"depositFee","type":"uint256"},{"internalType":"uint256","name":"withdrawalFee","type":"uint256"},{"internalType":"uint256","name":"maxDeposit","type":"uint256"}],"name":"addSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"internalType":"bytes","name":"srcToken","type":"bytes"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"credit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"currentDebit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"bytes","name":"dstToken","type":"bytes"}],"name":"debit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllTokenInfo","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"components":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"depositFee","type":"uint256"},{"internalType":"uint256","name":"withdrawalFee","type":"uint256"},{"internalType":"uint256","name":"maxDeposit","type":"uint256"},{"internalType":"bool","name":"isSupported","type":"bool"}],"internalType":"struct VaultToken.TokenInfo[]","name":"","type":"tuple[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultReserves","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"contract IRateLimits","name":"_rateLimits","type":"address"},{"internalType":"address","name":"_xTokenManager","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"maxDebit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateLimits","outputs":[{"internalType":"contract IRateLimits","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bytes","name":"token","type":"bytes"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setDebit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bytes","name":"token","type":"bytes"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setMaxDebit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maxDeposit","type":"uint256"}],"name":"setMaxDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRateLimits","name":"_rateLimits","type":"address"}],"name":"setRateLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_xTokenManager","type":"address"}],"name":"setXTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenInfo","outputs":[{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"depositFee","type":"uint256"},{"internalType":"uint256","name":"withdrawalFee","type":"uint256"},{"internalType":"uint256","name":"maxDeposit","type":"uint256"},{"internalType":"bool","name":"isSupported","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"depositFee","type":"uint256"},{"internalType":"uint256","name":"withdrawalFee","type":"uint256"},{"internalType":"uint256","name":"maxDeposit","type":"uint256"}],"name":"updateToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"xTokenManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405230608052348015610013575f5ffd5b5061001c610021565b6100d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100715760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051612ecb6100f95f395f8181611d2e01528181611d570152611e960152612ecb5ff3fe608060405260043610610233575f3560e01c806395abc09111610129578063d768779a116100a8578063e971d2421161006d578063e971d24214610709578063f092159414610728578063f2fde38b14610747578063f3fef3a314610766578063f5dab71114610785575f5ffd5b8063d768779a1461066f578063d9e119af1461068e578063db0ed6a0146106ac578063dd62ed3e146106cb578063e74b981b146106ea575f5ffd5b8063a9059cbb116100ee578063a9059cbb146105d8578063aaf10f42146105f7578063ad3cb1cc1461060b578063c62556261461063b578063d73792a91461065a575f5ffd5b806395abc0911461051c57806395d89b411461053f5780639733132314610553578063999d385514610572578063a88ad6fb146105b9575f5ffd5b80634f1ef286116101b5578063742ef0421161017a578063742ef04214610461578063763191901461048057806385c994f71461049f5780638774d9d5146104be5780638da5cb5b146104e0575f5ffd5b80634f1ef286146103e857806352d1902d146103fb57806370a082311461040f578063715018a61461042e57806373f65f8a14610442575f5ffd5b806326b2117a116101fb57806326b2117a14610337578063313ce567146103585780633149b69314610373578063469048401461039257806347e7ef24146103c9575f5ffd5b806306fdde0314610237578063095ea7b31461026157806311e132ad1461029057806318160ddd146102e557806323b872dd14610318575b5f5ffd5b348015610242575f5ffd5b5061024b610801565b604051610258919061258b565b60405180910390f35b34801561026c575f5ffd5b5061028061027b3660046125d4565b6108c1565b6040519015158152602001610258565b34801561029b575f5ffd5b506102d76102aa3660046126a1565b600260209081525f9283526040909220815180830184018051928152908401929093019190912091525481565b604051908152602001610258565b3480156102f0575f5ffd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02546102d7565b348015610323575f5ffd5b506102806103323660046126e4565b6108da565b348015610342575f5ffd5b50610356610351366004612722565b6108ff565b005b348015610363575f5ffd5b5060405160128152602001610258565b34801561037e575f5ffd5b5061035661038d36600461276e565b61093c565b34801561039d575f5ffd5b506005546103b1906001600160a01b031681565b6040516001600160a01b039091168152602001610258565b3480156103d4575f5ffd5b506103566103e33660046125d4565b610a61565b6103566103f63660046127cc565b610c72565b348015610406575f5ffd5b506102d7610c91565b34801561041a575f5ffd5b506102d7610429366004612802565b610cac565b348015610439575f5ffd5b50610356610cd2565b34801561044d575f5ffd5b5061035661045c3660046125d4565b610ce5565b34801561046c575f5ffd5b5061035661047b36600461281d565b610d46565b34801561048b575f5ffd5b5061035661049a366004612802565b610f0c565b3480156104aa575f5ffd5b506103566104b9366004612722565b611083565b3480156104c9575f5ffd5b506104d26110ab565b6040516102589291906128e2565b3480156104eb575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166103b1565b348015610527575f5ffd5b50610530611215565b60405161025893929190612906565b34801561054a575f5ffd5b5061024b611480565b34801561055e575f5ffd5b5061035661056d3660046129a6565b6114be565b34801561057d575f5ffd5b506102d761058c3660046126a1565b600160209081525f9283526040909220815180830184018051928152908401929093019190912091525481565b3480156105c4575f5ffd5b506103566105d3366004612802565b611598565b3480156105e3575f5ffd5b506102806105f23660046125d4565b6115c1565b348015610602575f5ffd5b506103b16115ce565b348015610616575f5ffd5b5061024b604051806040016040528060058152602001640352e302e360dc1b81525081565b348015610646575f5ffd5b506103b1610655366004612a02565b6115f2565b348015610665575f5ffd5b506102d761271081565b34801561067a575f5ffd5b50610356610689366004612a19565b61161a565b348015610699575f5ffd5b505f546103b1906001600160a01b031681565b3480156106b7575f5ffd5b506103566106c6366004612a51565b61171e565b3480156106d6575f5ffd5b506102d76106e5366004612aec565b61187c565b3480156106f5575f5ffd5b50610356610704366004612802565b6118c5565b348015610714575f5ffd5b50610356610723366004612802565b61193d565b348015610733575f5ffd5b506006546103b1906001600160a01b031681565b348015610752575f5ffd5b50610356610761366004612802565b611967565b348015610771575f5ffd5b506103566107803660046125d4565b6119a4565b348015610790575f5ffd5b506107d361079f366004612802565b600360208190525f91825260409091208054600182015460028301549383015460049093015460ff92831694919391921685565b6040805160ff909616865260208601949094529284019190915260608301521515608082015260a001610258565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060915f516020612e565f395f51905f529161083f90612b23565b80601f016020809104026020016040519081016040528092919081815260200182805461086b90612b23565b80156108b65780601f1061088d576101008083540402835291602001916108b6565b820191905f5260205f20905b81548152906001019060200180831161089957829003601f168201915b505050505091505090565b5f336108ce818585611ad4565b60019150505b92915050565b5f336108e7858285611ae6565b6108f2858585611b49565b60019150505b9392505050565b610907611ba6565b8060015f8581526020019081526020015f20836040516109279190612b5b565b90815260405190819003602001902055505050565b5f546001600160a01b03163314610951575f5ffd5b5f82815260026020526040808220905161096c908490612b5b565b9081526040519081900360200190205490506109888482612b85565b905060015f8481526020019081526020015f20826040516109a99190612b5b565b908152602001604051809103902054811115610a205760405162461bcd60e51b815260206004820152602b60248201527f416d6f756e74206578636565647320746f74616c20646562697420666f72207460448201526a30b933b2ba103a37b5b2b760a91b60648201526084015b60405180910390fd5b8060025f8581526020019081526020015f2083604051610a409190612b5b565b90815260405190819003602001902055610a5a8585611c01565b5050505050565b6001600160a01b0382165f908152600360205260409020600481015460ff16610ac05760405162461bcd60e51b81526020600482015260116024820152702ab739bab83837b93a32b2103a37b5b2b760791b6044820152606401610a17565b5f8211610b0f5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610a17565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa158015610b53573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b779190612b98565b6003830154909150610b898483612b85565b1115610bf05760405162461bcd60e51b815260206004820152603060248201527f4465706f7369742065786365656473206d6178696d756d20616c6c6f7761626c60448201526f6520746f74616c206465706f7369747360801b6064820152608401610a17565b610c056001600160a01b038516333086611c35565b81545f90610c169060ff1685611c9c565b905082600101545f14610c68575f612710846001015483610c379190612baf565b610c419190612bc6565b600554909150610c5a906001600160a01b031682611cef565b610c648183612be5565b9150505b610a5a3382611cef565b610c7a611d23565b610c8382611dc7565b610c8d8282611dcf565b5050565b5f610c9a611e8b565b505f516020612e765f395f51905f5290565b6001600160a01b03165f9081525f516020612e565f395f51905f52602052604090205490565b610cda611ba6565b610ce35f611ed4565b565b610ced611ba6565b6001600160a01b0382165f9081526003602052604090206004015460ff16610d275760405162461bcd60e51b8152600401610a1790612bf8565b6001600160a01b039091165f9081526003602081905260409091200155565b610d4e611ba6565b6001600160a01b0385165f9081526003602052604090206004015460ff1615610db95760405162461bcd60e51b815260206004820152601760248201527f546f6b656e20616c726561647920737570706f727465640000000000000000006044820152606401610a17565b612710831115610e015760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964206465706f7369742066656560681b6044820152606401610a17565b612710821115610e4c5760405162461bcd60e51b8152602060048201526016602482015275496e76616c6964207769746864726177616c2066656560501b6044820152606401610a17565b6040805160a08101825260ff95861681526020808201958652818301948552606082019384526001608083018181526001600160a01b039099165f81815260039384905294852093518454991660ff19998a1617845596518382015594516002830155925192810192909255945160049182018054911515919095161790935582549081018355919092527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319169091179055565b610f14611ba6565b6001600160a01b0381165f9081526003602052604090206004015460ff16610f4e5760405162461bcd60e51b8152600401610a1790612bf8565b6001600160a01b0381165f9081526003602081905260408220805460ff1990811682556001820184905560028201849055918101839055600401805490911690555b600454811015610c8d57816001600160a01b031660048281548110610fb757610fb7612c25565b5f918252602090912001546001600160a01b03160361107b5760048054610fe090600190612be5565b81548110610ff057610ff0612c25565b5f91825260209091200154600480546001600160a01b03909216918390811061101b5761101b612c25565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550600480548061105757611057612c39565b5f8281526020902081015f1990810180546001600160a01b03191690550190555050565b600101610f90565b61108b611ba6565b8060025f8581526020019081526020015f20836040516109279190612b5b565b6060805f6004805490506001600160401b038111156110cc576110cc6125fe565b6040519080825280602002602001820160405280156110f5578160200160208202803683370190505b5090505f5b6004548110156111ae576004818154811061111757611117612c25565b5f918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611165573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111899190612b98565b82828151811061119b5761119b612c25565b60209081029190910101526001016110fa565b506004818180548060200260200160405190810160405280929190818152602001828054801561120557602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116111e7575b5050505050915092509250509091565b600454606090819081905f816001600160401b03811115611238576112386125fe565b60405190808252806020026020018201604052801561129b57816020015b6112886040518060a001604052805f60ff1681526020015f81526020015f81526020015f81526020015f151581525090565b8152602001906001900390816112565790505b5090505f826001600160401b038111156112b7576112b76125fe565b6040519080825280602002602001820160405280156112e0578160200160208202803683370190505b5090505f5b83811015611413575f6004828154811061130157611301612c25565b5f9182526020808320909101546001600160a01b03168083526003808352604093849020845160a081018652815460ff90811682526001830154958201959095526002820154958101959095529081015460608501526004015490911615156080830152855190925085908490811061137c5761137c612c25565b60209081029190910101526040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113ed9190612b98565b8383815181106113ff576113ff612c25565b6020908102919091010152506001016112e5565b50600482828280548060200260200160405190810160405280929190818152602001828054801561146b57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161144d575b50505050509250955095509550505050909192565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060915f516020612e565f395f51905f529161083f90612b23565b5f546001600160a01b031633146114d3575f5ffd5b5f8481526002602052604080822090516114ee908690612b5b565b90815260200160405180910390205490508181116115585760405162461bcd60e51b815260206004820152602160248201527f5468697320746f6b656e20686173206e6f20617661696c61626c6520646562696044820152601d60fa1b6064820152608401610a17565b6115628282612be5565b5f8681526002602052604090819020905161157e908790612b5b565b90815260405190819003602001902055610a5a8383611cef565b6115a0611ba6565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b5f336108ce818585611b49565b5f6115ed5f516020612e765f395f51905f52546001600160a01b031690565b905090565b60048181548110611601575f80fd5b5f918252602090912001546001600160a01b0316905081565b611622611ba6565b6001600160a01b0384165f9081526003602052604090206004015460ff1661165c5760405162461bcd60e51b8152600401610a1790612bf8565b6127108311156116a45760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964206465706f7369742066656560681b6044820152606401610a17565b6127108211156116ef5760405162461bcd60e51b8152602060048201526016602482015275496e76616c6964207769746864726177616c2066656560501b6044820152606401610a17565b6001600160a01b039093165f908152600360208190526040909120600181019390935560028301919091550155565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156117625750825b90505f826001600160401b0316600114801561177d5750303b155b90508115801561178b575080155b156117a95760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156117d357845460ff60401b1916600160401b1785555b6117dd8a8a611f44565b6117e633611f56565b6117ee611f67565b600580546001600160a01b03808b166001600160a01b031992831617909255600680548a84169083161790555f805492891692909116919091179055831561187057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b6001600160a01b039182165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b6118cd611ba6565b6001600160a01b03811661191b5760405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a5908199959481c9958da5c1a595b9d605a1b6044820152606401610a17565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b611945611ba6565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b61196f611ba6565b6001600160a01b03811661199857604051631e4fbdf760e01b81525f6004820152602401610a17565b6119a181611ed4565b50565b6001600160a01b0382165f908152600360205260409020600481015460ff16611a035760405162461bcd60e51b81526020600482015260116024820152702ab739bab83837b93a32b2103a37b5b2b760791b6044820152606401610a17565b5f8211611a525760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610a17565b611a5c3383611c01565b6002810154829015611aad575f612710836002015485611a7c9190612baf565b611a869190612bc6565b600554909150611a9f906001600160a01b031682611cef565b611aa98183612be5565b9150505b81545f90611abe9060ff1683611f6f565b9050610a5a6001600160a01b0386163383611f91565b611ae18383836001611fc2565b505050565b5f611af1848461187c565b90505f198114611b435781811015611b3557604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610a17565b611b4384848484035f611fc2565b50505050565b6001600160a01b038316611b7257604051634b637e8f60e11b81525f6004820152602401610a17565b6001600160a01b038216611b9b5760405163ec442f0560e01b81525f6004820152602401610a17565b611ae18383836120a5565b33611bd87f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610ce35760405163118cdaa760e01b8152336004820152602401610a17565b6001600160a01b038216611c2a57604051634b637e8f60e11b81525f6004820152602401610a17565b610c8d825f836120a5565b6040516001600160a01b038481166024830152838116604483015260648201839052611b439186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612177565b5f60128360ff1611611ccf57611cb3836012612c4d565b611cbe90600a612d49565b611cc89083612baf565b90506108d4565b611cda601284612c4d565b611ce590600a612d49565b611cc89083612bc6565b6001600160a01b038216611d185760405163ec442f0560e01b81525f6004820152602401610a17565b610c8d5f83836120a5565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611da957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611d9d5f516020612e765f395f51905f52546001600160a01b031690565b6001600160a01b031614155b15610ce35760405163703e46dd60e11b815260040160405180910390fd5b6119a1611ba6565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611e29575060408051601f3d908101601f19168201909252611e2691810190612b98565b60015b611e5157604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610a17565b5f516020612e765f395f51905f528114611e8157604051632a87526960e21b815260048101829052602401610a17565b611ae183836121e3565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610ce35760405163703e46dd60e11b815260040160405180910390fd5b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b611f4c612238565b610c8d8282612281565b611f5e612238565b6119a1816122d1565b610ce3612238565b5f60128360ff1611611f8657611cda836012612c4d565b611cb3601284612c4d565b6040516001600160a01b03838116602483015260448201839052611ae191859182169063a9059cbb90606401611c6a565b5f516020612e565f395f51905f526001600160a01b038516611ff95760405163e602df0560e01b81525f6004820152602401610a17565b6001600160a01b03841661202257604051634a1406b160e11b81525f6004820152602401610a17565b6001600160a01b038086165f90815260018301602090815260408083209388168352929052208390558115610a5a57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258560405161209691815260200190565b60405180910390a35050505050565b6120b08383836122d9565b6006546001600160a01b0316630e2ba3b284846120cc82610cac565b6120d587610cac565b866120fe7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b6040516001600160e01b031960e089901b1681526001600160a01b03968716600482015295909416602486015260448501929092526064840152608483015260a482015260c4015f604051808303815f87803b15801561215c575f5ffd5b505af115801561216e573d5f5f3e3d5ffd5b50505050505050565b5f5f60205f8451602086015f885af180612196576040513d5f823e3d81fd5b50505f513d915081156121ad5780600114156121ba565b6001600160a01b0384163b155b15611b4357604051635274afe760e01b81526001600160a01b0385166004820152602401610a17565b6121ec82612412565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561223057611ae18282612475565b610c8d6124e7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610ce357604051631afcd79f60e31b815260040160405180910390fd5b612289612238565b5f516020612e565f395f51905f527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036122c28482612d9b565b5060048101611b438382612d9b565b61196f612238565b5f516020612e565f395f51905f526001600160a01b0384166123135781816002015f8282546123089190612b85565b909155506123839050565b6001600160a01b0384165f90815260208290526040902054828110156123655760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610a17565b6001600160a01b0385165f9081526020839052604090209083900390555b6001600160a01b0383166123a15760028101805483900390556123bf565b6001600160a01b0383165f9081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161240491815260200190565b60405180910390a350505050565b806001600160a01b03163b5f0361244757604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610a17565b5f516020612e765f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b0316846040516124919190612b5b565b5f60405180830381855af49150503d805f81146124c9576040519150601f19603f3d011682016040523d82523d5f602084013e6124ce565b606091505b50915091506124de858383612506565b95945050505050565b3415610ce35760405163b398979f60e01b815260040160405180910390fd5b60608261251b5761251682612562565b6108f8565b815115801561253257506001600160a01b0384163b155b1561255b57604051639996b31560e01b81526001600160a01b0385166004820152602401610a17565b50806108f8565b8051156125725780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b03811681146119a1575f5ffd5b5f5f604083850312156125e5575f5ffd5b82356125f0816125c0565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112612621575f5ffd5b8135602083015f5f6001600160401b03841115612640576126406125fe565b50604051601f19601f85018116603f011681018181106001600160401b038211171561266e5761266e6125fe565b604052838152905080828401871015612685575f5ffd5b838360208301375f602085830101528094505050505092915050565b5f5f604083850312156126b2575f5ffd5b8235915060208301356001600160401b038111156126ce575f5ffd5b6126da85828601612612565b9150509250929050565b5f5f5f606084860312156126f6575f5ffd5b8335612701816125c0565b92506020840135612711816125c0565b929592945050506040919091013590565b5f5f5f60608486031215612734575f5ffd5b8335925060208401356001600160401b03811115612750575f5ffd5b61275c86828701612612565b93969395505050506040919091013590565b5f5f5f5f60808587031215612781575f5ffd5b843561278c816125c0565b9350602085013592506040850135915060608501356001600160401b038111156127b4575f5ffd5b6127c087828801612612565b91505092959194509250565b5f5f604083850312156127dd575f5ffd5b82356127e8816125c0565b915060208301356001600160401b038111156126ce575f5ffd5b5f60208284031215612812575f5ffd5b81356108f8816125c0565b5f5f5f5f5f60a08688031215612831575f5ffd5b853561283c816125c0565b9450602086013560ff81168114612851575f5ffd5b94979496505050506040830135926060810135926080909101359150565b5f8151808452602084019350602083015f5b828110156128a85781516001600160a01b0316865260209586019590910190600101612881565b5093949350505050565b5f8151808452602084019350602083015f5b828110156128a85781518652602095860195909101906001016128c4565b604081525f6128f4604083018561286f565b82810360208401526124de81856128b2565b606081525f612918606083018661286f565b82810360208401528085518083526020830191506020870192505f5b8181101561298757835160ff81511684526020810151602085015260408101516040850152606081015160608501526080810151151560808501525060a083019250602084019350600181019050612934565b5050838103604085015261299b81866128b2565b979650505050505050565b5f5f5f5f608085870312156129b9575f5ffd5b8435935060208501356001600160401b038111156129d5575f5ffd5b6129e187828801612612565b93505060408501356129f2816125c0565b9396929550929360600135925050565b5f60208284031215612a12575f5ffd5b5035919050565b5f5f5f5f60808587031215612a2c575f5ffd5b8435612a37816125c0565b966020860135965060408601359560600135945092505050565b5f5f5f5f5f60a08688031215612a65575f5ffd5b85356001600160401b03811115612a7a575f5ffd5b612a8688828901612612565b95505060208601356001600160401b03811115612aa1575f5ffd5b612aad88828901612612565b9450506040860135612abe816125c0565b92506060860135612ace816125c0565b91506080860135612ade816125c0565b809150509295509295909350565b5f5f60408385031215612afd575f5ffd5b8235612b08816125c0565b91506020830135612b18816125c0565b809150509250929050565b600181811c90821680612b3757607f821691505b602082108103612b5557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156108d4576108d4612b71565b5f60208284031215612ba8575f5ffd5b5051919050565b80820281158282048414176108d4576108d4612b71565b5f82612be057634e487b7160e01b5f52601260045260245ffd5b500490565b818103818111156108d4576108d4612b71565b602080825260139082015272151bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b60ff82811682821603908111156108d4576108d4612b71565b6001815b6001841115612ca157808504811115612c8557612c85612b71565b6001841615612c9357908102905b60019390931c928002612c6a565b935093915050565b5f82612cb7575060016108d4565b81612cc357505f6108d4565b8160018114612cd95760028114612ce357612cff565b60019150506108d4565b60ff841115612cf457612cf4612b71565b50506001821b6108d4565b5060208310610133831016604e8410600b8410161715612d22575081810a6108d4565b612d2e5f198484612c66565b805f1904821115612d4157612d41612b71565b029392505050565b5f6108f860ff841683612ca9565b601f821115611ae157805f5260205f20601f840160051c81016020851015612d7c5750805b601f840160051c820191505b81811015610a5a575f8155600101612d88565b81516001600160401b03811115612db457612db46125fe565b612dc881612dc28454612b23565b84612d57565b6020601f821160018114612dfa575f8315612de35750848201515b5f19600385901b1c1916600184901b178455610a5a565b5f84815260208120601f198516915b82811015612e295787850151825560209485019460019092019101612e09565b5084821015612e4657868401515f19600387901b60f8161c191681555b50505050600190811b0190555056fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122026ab6195d4b873eaf7aed1e1751ece39ff678d419ef4297c723548a64af27b4b64736f6c634300081c0033
Deployed Bytecode
0x608060405260043610610233575f3560e01c806395abc09111610129578063d768779a116100a8578063e971d2421161006d578063e971d24214610709578063f092159414610728578063f2fde38b14610747578063f3fef3a314610766578063f5dab71114610785575f5ffd5b8063d768779a1461066f578063d9e119af1461068e578063db0ed6a0146106ac578063dd62ed3e146106cb578063e74b981b146106ea575f5ffd5b8063a9059cbb116100ee578063a9059cbb146105d8578063aaf10f42146105f7578063ad3cb1cc1461060b578063c62556261461063b578063d73792a91461065a575f5ffd5b806395abc0911461051c57806395d89b411461053f5780639733132314610553578063999d385514610572578063a88ad6fb146105b9575f5ffd5b80634f1ef286116101b5578063742ef0421161017a578063742ef04214610461578063763191901461048057806385c994f71461049f5780638774d9d5146104be5780638da5cb5b146104e0575f5ffd5b80634f1ef286146103e857806352d1902d146103fb57806370a082311461040f578063715018a61461042e57806373f65f8a14610442575f5ffd5b806326b2117a116101fb57806326b2117a14610337578063313ce567146103585780633149b69314610373578063469048401461039257806347e7ef24146103c9575f5ffd5b806306fdde0314610237578063095ea7b31461026157806311e132ad1461029057806318160ddd146102e557806323b872dd14610318575b5f5ffd5b348015610242575f5ffd5b5061024b610801565b604051610258919061258b565b60405180910390f35b34801561026c575f5ffd5b5061028061027b3660046125d4565b6108c1565b6040519015158152602001610258565b34801561029b575f5ffd5b506102d76102aa3660046126a1565b600260209081525f9283526040909220815180830184018051928152908401929093019190912091525481565b604051908152602001610258565b3480156102f0575f5ffd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02546102d7565b348015610323575f5ffd5b506102806103323660046126e4565b6108da565b348015610342575f5ffd5b50610356610351366004612722565b6108ff565b005b348015610363575f5ffd5b5060405160128152602001610258565b34801561037e575f5ffd5b5061035661038d36600461276e565b61093c565b34801561039d575f5ffd5b506005546103b1906001600160a01b031681565b6040516001600160a01b039091168152602001610258565b3480156103d4575f5ffd5b506103566103e33660046125d4565b610a61565b6103566103f63660046127cc565b610c72565b348015610406575f5ffd5b506102d7610c91565b34801561041a575f5ffd5b506102d7610429366004612802565b610cac565b348015610439575f5ffd5b50610356610cd2565b34801561044d575f5ffd5b5061035661045c3660046125d4565b610ce5565b34801561046c575f5ffd5b5061035661047b36600461281d565b610d46565b34801561048b575f5ffd5b5061035661049a366004612802565b610f0c565b3480156104aa575f5ffd5b506103566104b9366004612722565b611083565b3480156104c9575f5ffd5b506104d26110ab565b6040516102589291906128e2565b3480156104eb575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166103b1565b348015610527575f5ffd5b50610530611215565b60405161025893929190612906565b34801561054a575f5ffd5b5061024b611480565b34801561055e575f5ffd5b5061035661056d3660046129a6565b6114be565b34801561057d575f5ffd5b506102d761058c3660046126a1565b600160209081525f9283526040909220815180830184018051928152908401929093019190912091525481565b3480156105c4575f5ffd5b506103566105d3366004612802565b611598565b3480156105e3575f5ffd5b506102806105f23660046125d4565b6115c1565b348015610602575f5ffd5b506103b16115ce565b348015610616575f5ffd5b5061024b604051806040016040528060058152602001640352e302e360dc1b81525081565b348015610646575f5ffd5b506103b1610655366004612a02565b6115f2565b348015610665575f5ffd5b506102d761271081565b34801561067a575f5ffd5b50610356610689366004612a19565b61161a565b348015610699575f5ffd5b505f546103b1906001600160a01b031681565b3480156106b7575f5ffd5b506103566106c6366004612a51565b61171e565b3480156106d6575f5ffd5b506102d76106e5366004612aec565b61187c565b3480156106f5575f5ffd5b50610356610704366004612802565b6118c5565b348015610714575f5ffd5b50610356610723366004612802565b61193d565b348015610733575f5ffd5b506006546103b1906001600160a01b031681565b348015610752575f5ffd5b50610356610761366004612802565b611967565b348015610771575f5ffd5b506103566107803660046125d4565b6119a4565b348015610790575f5ffd5b506107d361079f366004612802565b600360208190525f91825260409091208054600182015460028301549383015460049093015460ff92831694919391921685565b6040805160ff909616865260208601949094529284019190915260608301521515608082015260a001610258565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060915f516020612e565f395f51905f529161083f90612b23565b80601f016020809104026020016040519081016040528092919081815260200182805461086b90612b23565b80156108b65780601f1061088d576101008083540402835291602001916108b6565b820191905f5260205f20905b81548152906001019060200180831161089957829003601f168201915b505050505091505090565b5f336108ce818585611ad4565b60019150505b92915050565b5f336108e7858285611ae6565b6108f2858585611b49565b60019150505b9392505050565b610907611ba6565b8060015f8581526020019081526020015f20836040516109279190612b5b565b90815260405190819003602001902055505050565b5f546001600160a01b03163314610951575f5ffd5b5f82815260026020526040808220905161096c908490612b5b565b9081526040519081900360200190205490506109888482612b85565b905060015f8481526020019081526020015f20826040516109a99190612b5b565b908152602001604051809103902054811115610a205760405162461bcd60e51b815260206004820152602b60248201527f416d6f756e74206578636565647320746f74616c20646562697420666f72207460448201526a30b933b2ba103a37b5b2b760a91b60648201526084015b60405180910390fd5b8060025f8581526020019081526020015f2083604051610a409190612b5b565b90815260405190819003602001902055610a5a8585611c01565b5050505050565b6001600160a01b0382165f908152600360205260409020600481015460ff16610ac05760405162461bcd60e51b81526020600482015260116024820152702ab739bab83837b93a32b2103a37b5b2b760791b6044820152606401610a17565b5f8211610b0f5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610a17565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa158015610b53573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b779190612b98565b6003830154909150610b898483612b85565b1115610bf05760405162461bcd60e51b815260206004820152603060248201527f4465706f7369742065786365656473206d6178696d756d20616c6c6f7761626c60448201526f6520746f74616c206465706f7369747360801b6064820152608401610a17565b610c056001600160a01b038516333086611c35565b81545f90610c169060ff1685611c9c565b905082600101545f14610c68575f612710846001015483610c379190612baf565b610c419190612bc6565b600554909150610c5a906001600160a01b031682611cef565b610c648183612be5565b9150505b610a5a3382611cef565b610c7a611d23565b610c8382611dc7565b610c8d8282611dcf565b5050565b5f610c9a611e8b565b505f516020612e765f395f51905f5290565b6001600160a01b03165f9081525f516020612e565f395f51905f52602052604090205490565b610cda611ba6565b610ce35f611ed4565b565b610ced611ba6565b6001600160a01b0382165f9081526003602052604090206004015460ff16610d275760405162461bcd60e51b8152600401610a1790612bf8565b6001600160a01b039091165f9081526003602081905260409091200155565b610d4e611ba6565b6001600160a01b0385165f9081526003602052604090206004015460ff1615610db95760405162461bcd60e51b815260206004820152601760248201527f546f6b656e20616c726561647920737570706f727465640000000000000000006044820152606401610a17565b612710831115610e015760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964206465706f7369742066656560681b6044820152606401610a17565b612710821115610e4c5760405162461bcd60e51b8152602060048201526016602482015275496e76616c6964207769746864726177616c2066656560501b6044820152606401610a17565b6040805160a08101825260ff95861681526020808201958652818301948552606082019384526001608083018181526001600160a01b039099165f81815260039384905294852093518454991660ff19998a1617845596518382015594516002830155925192810192909255945160049182018054911515919095161790935582549081018355919092527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319169091179055565b610f14611ba6565b6001600160a01b0381165f9081526003602052604090206004015460ff16610f4e5760405162461bcd60e51b8152600401610a1790612bf8565b6001600160a01b0381165f9081526003602081905260408220805460ff1990811682556001820184905560028201849055918101839055600401805490911690555b600454811015610c8d57816001600160a01b031660048281548110610fb757610fb7612c25565b5f918252602090912001546001600160a01b03160361107b5760048054610fe090600190612be5565b81548110610ff057610ff0612c25565b5f91825260209091200154600480546001600160a01b03909216918390811061101b5761101b612c25565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550600480548061105757611057612c39565b5f8281526020902081015f1990810180546001600160a01b03191690550190555050565b600101610f90565b61108b611ba6565b8060025f8581526020019081526020015f20836040516109279190612b5b565b6060805f6004805490506001600160401b038111156110cc576110cc6125fe565b6040519080825280602002602001820160405280156110f5578160200160208202803683370190505b5090505f5b6004548110156111ae576004818154811061111757611117612c25565b5f918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611165573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111899190612b98565b82828151811061119b5761119b612c25565b60209081029190910101526001016110fa565b506004818180548060200260200160405190810160405280929190818152602001828054801561120557602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116111e7575b5050505050915092509250509091565b600454606090819081905f816001600160401b03811115611238576112386125fe565b60405190808252806020026020018201604052801561129b57816020015b6112886040518060a001604052805f60ff1681526020015f81526020015f81526020015f81526020015f151581525090565b8152602001906001900390816112565790505b5090505f826001600160401b038111156112b7576112b76125fe565b6040519080825280602002602001820160405280156112e0578160200160208202803683370190505b5090505f5b83811015611413575f6004828154811061130157611301612c25565b5f9182526020808320909101546001600160a01b03168083526003808352604093849020845160a081018652815460ff90811682526001830154958201959095526002820154958101959095529081015460608501526004015490911615156080830152855190925085908490811061137c5761137c612c25565b60209081029190910101526040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113ed9190612b98565b8383815181106113ff576113ff612c25565b6020908102919091010152506001016112e5565b50600482828280548060200260200160405190810160405280929190818152602001828054801561146b57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161144d575b50505050509250955095509550505050909192565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060915f516020612e565f395f51905f529161083f90612b23565b5f546001600160a01b031633146114d3575f5ffd5b5f8481526002602052604080822090516114ee908690612b5b565b90815260200160405180910390205490508181116115585760405162461bcd60e51b815260206004820152602160248201527f5468697320746f6b656e20686173206e6f20617661696c61626c6520646562696044820152601d60fa1b6064820152608401610a17565b6115628282612be5565b5f8681526002602052604090819020905161157e908790612b5b565b90815260405190819003602001902055610a5a8383611cef565b6115a0611ba6565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b5f336108ce818585611b49565b5f6115ed5f516020612e765f395f51905f52546001600160a01b031690565b905090565b60048181548110611601575f80fd5b5f918252602090912001546001600160a01b0316905081565b611622611ba6565b6001600160a01b0384165f9081526003602052604090206004015460ff1661165c5760405162461bcd60e51b8152600401610a1790612bf8565b6127108311156116a45760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964206465706f7369742066656560681b6044820152606401610a17565b6127108211156116ef5760405162461bcd60e51b8152602060048201526016602482015275496e76616c6964207769746864726177616c2066656560501b6044820152606401610a17565b6001600160a01b039093165f908152600360208190526040909120600181019390935560028301919091550155565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f811580156117625750825b90505f826001600160401b0316600114801561177d5750303b155b90508115801561178b575080155b156117a95760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156117d357845460ff60401b1916600160401b1785555b6117dd8a8a611f44565b6117e633611f56565b6117ee611f67565b600580546001600160a01b03808b166001600160a01b031992831617909255600680548a84169083161790555f805492891692909116919091179055831561187057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b6001600160a01b039182165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b6118cd611ba6565b6001600160a01b03811661191b5760405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a5908199959481c9958da5c1a595b9d605a1b6044820152606401610a17565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b611945611ba6565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b61196f611ba6565b6001600160a01b03811661199857604051631e4fbdf760e01b81525f6004820152602401610a17565b6119a181611ed4565b50565b6001600160a01b0382165f908152600360205260409020600481015460ff16611a035760405162461bcd60e51b81526020600482015260116024820152702ab739bab83837b93a32b2103a37b5b2b760791b6044820152606401610a17565b5f8211611a525760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610a17565b611a5c3383611c01565b6002810154829015611aad575f612710836002015485611a7c9190612baf565b611a869190612bc6565b600554909150611a9f906001600160a01b031682611cef565b611aa98183612be5565b9150505b81545f90611abe9060ff1683611f6f565b9050610a5a6001600160a01b0386163383611f91565b611ae18383836001611fc2565b505050565b5f611af1848461187c565b90505f198114611b435781811015611b3557604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610a17565b611b4384848484035f611fc2565b50505050565b6001600160a01b038316611b7257604051634b637e8f60e11b81525f6004820152602401610a17565b6001600160a01b038216611b9b5760405163ec442f0560e01b81525f6004820152602401610a17565b611ae18383836120a5565b33611bd87f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610ce35760405163118cdaa760e01b8152336004820152602401610a17565b6001600160a01b038216611c2a57604051634b637e8f60e11b81525f6004820152602401610a17565b610c8d825f836120a5565b6040516001600160a01b038481166024830152838116604483015260648201839052611b439186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612177565b5f60128360ff1611611ccf57611cb3836012612c4d565b611cbe90600a612d49565b611cc89083612baf565b90506108d4565b611cda601284612c4d565b611ce590600a612d49565b611cc89083612bc6565b6001600160a01b038216611d185760405163ec442f0560e01b81525f6004820152602401610a17565b610c8d5f83836120a5565b306001600160a01b037f000000000000000000000000d87b1e8cf573176c52540e34505c00dc3614fb56161480611da957507f000000000000000000000000d87b1e8cf573176c52540e34505c00dc3614fb566001600160a01b0316611d9d5f516020612e765f395f51905f52546001600160a01b031690565b6001600160a01b031614155b15610ce35760405163703e46dd60e11b815260040160405180910390fd5b6119a1611ba6565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611e29575060408051601f3d908101601f19168201909252611e2691810190612b98565b60015b611e5157604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610a17565b5f516020612e765f395f51905f528114611e8157604051632a87526960e21b815260048101829052602401610a17565b611ae183836121e3565b306001600160a01b037f000000000000000000000000d87b1e8cf573176c52540e34505c00dc3614fb561614610ce35760405163703e46dd60e11b815260040160405180910390fd5b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b611f4c612238565b610c8d8282612281565b611f5e612238565b6119a1816122d1565b610ce3612238565b5f60128360ff1611611f8657611cda836012612c4d565b611cb3601284612c4d565b6040516001600160a01b03838116602483015260448201839052611ae191859182169063a9059cbb90606401611c6a565b5f516020612e565f395f51905f526001600160a01b038516611ff95760405163e602df0560e01b81525f6004820152602401610a17565b6001600160a01b03841661202257604051634a1406b160e11b81525f6004820152602401610a17565b6001600160a01b038086165f90815260018301602090815260408083209388168352929052208390558115610a5a57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258560405161209691815260200190565b60405180910390a35050505050565b6120b08383836122d9565b6006546001600160a01b0316630e2ba3b284846120cc82610cac565b6120d587610cac565b866120fe7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b6040516001600160e01b031960e089901b1681526001600160a01b03968716600482015295909416602486015260448501929092526064840152608483015260a482015260c4015f604051808303815f87803b15801561215c575f5ffd5b505af115801561216e573d5f5f3e3d5ffd5b50505050505050565b5f5f60205f8451602086015f885af180612196576040513d5f823e3d81fd5b50505f513d915081156121ad5780600114156121ba565b6001600160a01b0384163b155b15611b4357604051635274afe760e01b81526001600160a01b0385166004820152602401610a17565b6121ec82612412565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561223057611ae18282612475565b610c8d6124e7565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610ce357604051631afcd79f60e31b815260040160405180910390fd5b612289612238565b5f516020612e565f395f51905f527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036122c28482612d9b565b5060048101611b438382612d9b565b61196f612238565b5f516020612e565f395f51905f526001600160a01b0384166123135781816002015f8282546123089190612b85565b909155506123839050565b6001600160a01b0384165f90815260208290526040902054828110156123655760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610a17565b6001600160a01b0385165f9081526020839052604090209083900390555b6001600160a01b0383166123a15760028101805483900390556123bf565b6001600160a01b0383165f9081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161240491815260200190565b60405180910390a350505050565b806001600160a01b03163b5f0361244757604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610a17565b5f516020612e765f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b0316846040516124919190612b5b565b5f60405180830381855af49150503d805f81146124c9576040519150601f19603f3d011682016040523d82523d5f602084013e6124ce565b606091505b50915091506124de858383612506565b95945050505050565b3415610ce35760405163b398979f60e01b815260040160405180910390fd5b60608261251b5761251682612562565b6108f8565b815115801561253257506001600160a01b0384163b155b1561255b57604051639996b31560e01b81526001600160a01b0385166004820152602401610a17565b50806108f8565b8051156125725780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b03811681146119a1575f5ffd5b5f5f604083850312156125e5575f5ffd5b82356125f0816125c0565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112612621575f5ffd5b8135602083015f5f6001600160401b03841115612640576126406125fe565b50604051601f19601f85018116603f011681018181106001600160401b038211171561266e5761266e6125fe565b604052838152905080828401871015612685575f5ffd5b838360208301375f602085830101528094505050505092915050565b5f5f604083850312156126b2575f5ffd5b8235915060208301356001600160401b038111156126ce575f5ffd5b6126da85828601612612565b9150509250929050565b5f5f5f606084860312156126f6575f5ffd5b8335612701816125c0565b92506020840135612711816125c0565b929592945050506040919091013590565b5f5f5f60608486031215612734575f5ffd5b8335925060208401356001600160401b03811115612750575f5ffd5b61275c86828701612612565b93969395505050506040919091013590565b5f5f5f5f60808587031215612781575f5ffd5b843561278c816125c0565b9350602085013592506040850135915060608501356001600160401b038111156127b4575f5ffd5b6127c087828801612612565b91505092959194509250565b5f5f604083850312156127dd575f5ffd5b82356127e8816125c0565b915060208301356001600160401b038111156126ce575f5ffd5b5f60208284031215612812575f5ffd5b81356108f8816125c0565b5f5f5f5f5f60a08688031215612831575f5ffd5b853561283c816125c0565b9450602086013560ff81168114612851575f5ffd5b94979496505050506040830135926060810135926080909101359150565b5f8151808452602084019350602083015f5b828110156128a85781516001600160a01b0316865260209586019590910190600101612881565b5093949350505050565b5f8151808452602084019350602083015f5b828110156128a85781518652602095860195909101906001016128c4565b604081525f6128f4604083018561286f565b82810360208401526124de81856128b2565b606081525f612918606083018661286f565b82810360208401528085518083526020830191506020870192505f5b8181101561298757835160ff81511684526020810151602085015260408101516040850152606081015160608501526080810151151560808501525060a083019250602084019350600181019050612934565b5050838103604085015261299b81866128b2565b979650505050505050565b5f5f5f5f608085870312156129b9575f5ffd5b8435935060208501356001600160401b038111156129d5575f5ffd5b6129e187828801612612565b93505060408501356129f2816125c0565b9396929550929360600135925050565b5f60208284031215612a12575f5ffd5b5035919050565b5f5f5f5f60808587031215612a2c575f5ffd5b8435612a37816125c0565b966020860135965060408601359560600135945092505050565b5f5f5f5f5f60a08688031215612a65575f5ffd5b85356001600160401b03811115612a7a575f5ffd5b612a8688828901612612565b95505060208601356001600160401b03811115612aa1575f5ffd5b612aad88828901612612565b9450506040860135612abe816125c0565b92506060860135612ace816125c0565b91506080860135612ade816125c0565b809150509295509295909350565b5f5f60408385031215612afd575f5ffd5b8235612b08816125c0565b91506020830135612b18816125c0565b809150509250929050565b600181811c90821680612b3757607f821691505b602082108103612b5557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156108d4576108d4612b71565b5f60208284031215612ba8575f5ffd5b5051919050565b80820281158282048414176108d4576108d4612b71565b5f82612be057634e487b7160e01b5f52601260045260245ffd5b500490565b818103818111156108d4576108d4612b71565b602080825260139082015272151bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b60ff82811682821603908111156108d4576108d4612b71565b6001815b6001841115612ca157808504811115612c8557612c85612b71565b6001841615612c9357908102905b60019390931c928002612c6a565b935093915050565b5f82612cb7575060016108d4565b81612cc357505f6108d4565b8160018114612cd95760028114612ce357612cff565b60019150506108d4565b60ff841115612cf457612cf4612b71565b50506001821b6108d4565b5060208310610133831016604e8410600b8410161715612d22575081810a6108d4565b612d2e5f198484612c66565b805f1904821115612d4157612d41612b71565b029392505050565b5f6108f860ff841683612ca9565b601f821115611ae157805f5260205f20601f840160051c81016020851015612d7c5750805b601f840160051c820191505b81811015610a5a575f8155600101612d88565b81516001600160401b03811115612db457612db46125fe565b612dc881612dc28454612b23565b84612d57565b6020601f821160018114612dfa575f8315612de35750848201515b5f19600385901b1c1916600184901b178455610a5a565b5f84815260208120601f198516915b82811015612e295787850151825560209485019460019092019101612e09565b5084821015612e4657868401515f19600387901b60f8161c191681555b50505050600190811b0190555056fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122026ab6195d4b873eaf7aed1e1751ece39ff678d419ef4297c723548a64af27b4b64736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.