Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Portal
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.24; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IReceiveApproval.sol"; contract Portal is Ownable2StepUpgradeable, IReceiveApproval { using SafeERC20 for IERC20; /// @notice Supported token ability defines what can be done with /// a given token. Some tokens can be deposited but can not be locked. enum TokenAbility { None, Deposit, DepositAndLock } /// @notice Supported token struct to pair a token address with its ability /// @dev This an auxiliary struct is used to initialize the contract with /// the supported tokens and for governance to add new supported tokens. struct SupportedToken { address token; TokenAbility tokenAbility; } /// @notice DepositInfo keeps track of the deposit balance and unlock time. /// Each deposit is tracked separately and associated with a specific /// token. Some tokens can be deposited but can not be locked - in /// that case the unlockAt is the block timestamp of when the deposit /// was created. The same is true for tokens that can be locked but /// the depositor decided not to lock them. struct DepositInfo { uint96 balance; uint32 unlockAt; } /// @notice Mapping of the details of all the deposited funds: /// depositor address -> token address -> deposit id -> DepositInfo mapping(address => mapping(address => mapping(uint256 => DepositInfo))) public deposits; /// @notice The number of deposits created. Includes the deposits that // were fully withdrawn. This is also the identifier of the next // deposit to be created. uint256 public depositCount; /// @notice List of tokens enabled for deposit or for deposit and lock. mapping(address => TokenAbility) public tokenAbility; /// @notice Minimum time a deposit can be locked. uint32 public minLockPeriod; /// @notice Maximum time a deposit can be locked. uint32 public maxLockPeriod; event Deposited( address indexed depositor, address indexed token, uint256 indexed depositId, uint256 amount ); event Withdrawn( address indexed depositor, address indexed token, uint256 indexed depositId, uint256 amount ); event Locked( address indexed depositor, address indexed token, uint256 indexed depositId, uint32 unlockAt, uint32 lockPeriod ); event SupportedTokenAdded(address indexed token, TokenAbility tokenAbility); event MaxLockPeriodUpdated(uint32 maxLockPeriod); event MinLockPeriodUpdated(uint32 minLockPeriod); error IncorrectTokenAddress(address token); error IncorrectTokenAbility(TokenAbility ability); error IncorrectDepositor(address depositor); error IncorrectAmount(uint256 amount); error InsufficientDepositAmount(uint256 amount, uint256 depositBalance); error TokenNotSupported(address token); error TokenAlreadySupported(address token, TokenAbility tokenAbility); error InsufficientTokenAbility(address token, TokenAbility tokenAbility); error LockPeriodOutOfRange(uint32 lockPeriod); error IncorrectLockPeriod(uint256 lockPeriod); error LockPeriodTooShort( uint32 lockPeriod, uint32 newUnlockAt, uint32 existingUnlockAt ); error DepositLocked(uint32 unlockAt); error DepositNotFound(); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @notice Initialize the contract with the supported tokens and their /// abilities. /// @dev We are using OpenZeppelin's initializer pattern to initialize /// the contract. This function is called only once during the contract /// deployment. /// @param supportedTokens List of supported tokens and their abilities function initialize( SupportedToken[] memory supportedTokens ) external initializer { __Ownable_init(msg.sender); minLockPeriod = 4 weeks; maxLockPeriod = 39 weeks; depositCount = 0; for (uint256 i = 0; i < supportedTokens.length; i++) { address token = supportedTokens[i].token; TokenAbility ability = supportedTokens[i].tokenAbility; if (token == address(0)) { revert IncorrectTokenAddress(token); } tokenAbility[token] = ability; } } /// @notice Add a new supported token and define its ability. /// @dev Only the owner can add a new supported token. /// @param supportedToken Supported token and its ability function addSupportedToken( SupportedToken calldata supportedToken ) external onlyOwner { address token = supportedToken.token; TokenAbility ability = supportedToken.tokenAbility; if (token == address(0)) { revert IncorrectTokenAddress(token); } if (ability == TokenAbility.None) { revert IncorrectTokenAbility(ability); } if (tokenAbility[token] != TokenAbility.None) { revert TokenAlreadySupported(token, tokenAbility[token]); } tokenAbility[token] = ability; emit SupportedTokenAdded(token, ability); } /// @notice Set the minimum lock period for deposits. /// @dev Only the owner can update the minimum lock period. The new value /// must be normalized to weeks, non-zero, and not higher than the /// maximum lock period. /// @param _minLockPeriod new minimum lock period function setMinLockPeriod(uint32 _minLockPeriod) external onlyOwner { uint32 normalizedLockPeriod = _normalizeLockPeriod(_minLockPeriod); if ( _minLockPeriod != normalizedLockPeriod || normalizedLockPeriod == 0 || _minLockPeriod > maxLockPeriod ) { revert IncorrectLockPeriod(_minLockPeriod); } minLockPeriod = _minLockPeriod; emit MinLockPeriodUpdated(_minLockPeriod); } /// @notice Set the maximum lock period for deposits. Maximum lock /// period is used as a limit to prevent users from accidentally /// locking their deposits for too long. /// @dev Only the owner can update the maximum lock period. The new value /// must be normalized to weeks and not lower than the minimum lock /// period. /// @param _maxLockPeriod new maximum lock period function setMaxLockPeriod(uint32 _maxLockPeriod) external onlyOwner { if ( _maxLockPeriod != _normalizeLockPeriod(_maxLockPeriod) || _maxLockPeriod < minLockPeriod ) { revert IncorrectLockPeriod(_maxLockPeriod); } maxLockPeriod = _maxLockPeriod; emit MaxLockPeriodUpdated(_maxLockPeriod); } /// @notice Get the balance and unlock time of a given deposit. /// @param depositor depositor address /// @param token token address to get the balance /// @param depositId id of the deposit function getDeposit( address depositor, address token, uint256 depositId ) external view returns (DepositInfo memory) { return deposits[depositor][token][depositId]; } /// @notice Withdraw deposited tokens. /// Deposited lockable tokens can be withdrawn at any time if /// there is no lock set on the deposit or the lock period has passed. /// There is no way to withdraw locked deposit. Tokens that are not /// lockable can be withdrawn at any time. Deposit can be withdrawn /// partially. /// @param token deposited token address /// @param depositId id of the deposit /// @param amount amount of the token to be withdrawn from the deposit function withdraw( address token, uint256 depositId, uint96 amount ) external { TokenAbility ability = tokenAbility[token]; if (amount == 0) { revert IncorrectAmount(amount); } if (ability == TokenAbility.None) { revert TokenNotSupported(token); } DepositInfo memory selectedDeposit = deposits[msg.sender][token][ depositId ]; if ( ability == TokenAbility.DepositAndLock && // solhint-disable-next-line not-rely-on-time block.timestamp < selectedDeposit.unlockAt ) { revert DepositLocked(selectedDeposit.unlockAt); } uint96 depositedAmount = selectedDeposit.balance; if (depositedAmount == 0) { revert DepositNotFound(); } if (amount > depositedAmount) { revert InsufficientDepositAmount(amount, depositedAmount); } emit Withdrawn(msg.sender, token, depositId, amount); if (amount == depositedAmount) { delete deposits[msg.sender][token][depositId]; } else { deposits[msg.sender][token][depositId].balance = depositedAmount - amount; } IERC20(token).safeTransfer(msg.sender, amount); } /// @notice Receive approval from a token contract and deposit the tokens in /// one transaction. If the the token is lockable and lock period is /// greater than 0, the deposit will be locked for the given period. /// @dev This function is called by the token following the `approveAndCall` /// pattern. // Encoded lock period is counted in seconds, will be normalized to /// weeks. If non-zero, it must not be shorter than the minimum lock /// period and must not be longer than the maximum lock period. To not /// lock the deposit, the lock period must be 0. /// @param from address which approved and sent the tokens /// @param amount amount of tokens sent /// @param token address of the token contract /// @param data encoded lock period function receiveApproval( address from, uint256 amount, address token, bytes calldata data ) external override { if (token != msg.sender) { revert IncorrectTokenAddress(token); } if (amount > type(uint96).max) { revert IncorrectAmount(amount); } uint32 lockPeriod = abi.decode(data, (uint32)); _depositFor(from, from, token, uint96(amount), lockPeriod); } /// @notice Deposit and optionally lock tokens for the given period. /// @dev Lock period will be normalized to weeks. If non-zero, it must not /// be shorter than the minimum lock period and must not be longer than /// the maximum lock period. /// @param token token address to deposit /// @param amount amount of tokens to deposit /// @param lockPeriod lock period in seconds, 0 to not lock the deposit function deposit(address token, uint96 amount, uint32 lockPeriod) external { _depositFor(msg.sender, msg.sender, token, amount, lockPeriod); } /// @notice Deposit and optionally lock tokens to the contract on behalf of /// someone else. /// @dev Lock period will be normalized to weeks. If non-zero, it must not /// be shorter than the minimum lock period and must not be longer than /// the maximum lock period. /// @param depositOwner address that will be able to withdraw the deposit /// @param token token address to deposit /// @param amount amount of tokens to deposit /// @param lockPeriod lock period in seconds, 0 to not lock the deposit function depositFor( address depositOwner, address token, uint96 amount, uint32 lockPeriod ) external { _depositFor(depositOwner, msg.sender, token, amount, lockPeriod); } /// @notice Lock existing deposit for a given period. This function can be /// used to lock a deposit that was not locked when it was created or /// to extend the lock period of an already locked deposit. /// @param token address of the deposited token /// @param depositId id of the deposit /// @param lockPeriod new lock period in seconds function lock( address token, uint256 depositId, uint32 lockPeriod ) external { DepositInfo storage depositInfo = deposits[msg.sender][token][ depositId ]; if (depositInfo.balance == 0) { revert DepositNotFound(); } TokenAbility ability = tokenAbility[token]; if (ability != TokenAbility.DepositAndLock) { revert InsufficientTokenAbility(token, ability); } uint32 existingUnlockAt = depositInfo.unlockAt; uint32 newUnlockAt = _calculateUnlockTime( msg.sender, token, depositId, lockPeriod ); if (newUnlockAt <= existingUnlockAt) { revert LockPeriodTooShort( lockPeriod, newUnlockAt, existingUnlockAt ); } depositInfo.unlockAt = newUnlockAt; } /// @notice Internal deposit function to deposit tokens on behalf of a given /// address - sender or someone else. If the lock period passed as /// a parameter is non-zero, the function will lock the deposit. /// @param depositOwner address that will be able to withdraw the deposit /// @param token token address to deposit /// @param amount amount of tokens to deposit /// @param lockPeriod lock period in seconds, 0 to not lock the deposit function _depositFor( address depositOwner, address depositFunder, address token, uint96 amount, uint32 lockPeriod ) internal { TokenAbility ability = tokenAbility[token]; if (ability == TokenAbility.None) { revert TokenNotSupported(token); } if (lockPeriod > 0 && ability == TokenAbility.Deposit) { revert InsufficientTokenAbility(token, ability); } if (depositOwner == address(0)) { revert IncorrectDepositor(depositOwner); } if (amount == 0) { revert IncorrectAmount(amount); } depositCount++; uint256 depositId = depositCount; emit Deposited(depositOwner, token, depositId, amount); deposits[depositOwner][token][depositId] = DepositInfo({ balance: amount, // solhint-disable-next-line not-rely-on-time unlockAt: _calculateUnlockTime( depositOwner, token, depositId, lockPeriod ) }); IERC20(token).safeTransferFrom(depositFunder, address(this), amount); } /// @notice Calculates the unlock time normalizing the lock time value and /// making sure it is in the allowed range. Returns the timestamp at /// which the deposit can be unlocked. /// @dev This function DOES NOT check if the deposit exists and if the /// existing deposit already has a lock time. Please validate it before /// calling this function. /// @param depositor depositor address /// @param token token of the deposit that will be locked /// @param depositId id of the deposit that will be locked /// @param lockPeriod lock period in seconds function _calculateUnlockTime( address depositor, address token, uint depositId, uint32 lockPeriod ) internal returns (uint32) { // Short-circuit if there is no intention to lock. There is no need to // check the minimum/maximum lock time or normalize the lock period. if (lockPeriod == 0) { // solhint-disable-next-line not-rely-on-time return uint32(block.timestamp); } uint32 normalizedLockPeriod = _normalizeLockPeriod(lockPeriod); if ( normalizedLockPeriod == 0 || normalizedLockPeriod < minLockPeriod || normalizedLockPeriod > maxLockPeriod ) { revert LockPeriodOutOfRange(lockPeriod); } // solhint-disable-next-line not-rely-on-time uint32 unlockAt = uint32(block.timestamp) + normalizedLockPeriod; // It is gas-cheaper to pass the required parameters and emit the event // here instead of checking the result and emit the event in the calling // function. Keep in mind internal functions are inlined. emit Locked( depositor, token, depositId, unlockAt, normalizedLockPeriod ); return unlockAt; } /// @notice Normalizes the lock period to weeks. Will round down if not /// normalized. /// @param lockPeriod the lock period to be normalized function _normalizeLockPeriod( uint32 lockPeriod ) internal pure returns (uint32) { // slither-disable-next-line divide-before-multiply return (lockPeriod / 1 weeks) * 1 weeks; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {OwnableUpgradeable} from "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step struct Ownable2StepStorage { address _pendingOwner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00; function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) { assembly { $.slot := Ownable2StepStorageLocation } } event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); return $._pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); $._pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); delete $._pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// 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.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.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.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the 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.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 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. */ 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. */ 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. */ 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 Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { 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 silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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 AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 * {FailedInnerCall} 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 AddressInsufficientBalance(address(this)); } (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 {FailedInnerCall}) 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 {FailedInnerCall} 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 {FailedInnerCall}. */ 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.24; /// @notice An interface that should be implemented by contracts supporting /// `approveAndCall`/`receiveApproval` pattern. interface IReceiveApproval { /// @notice Receives approval to spend tokens. Called as a result of /// `approveAndCall` call on the token. function receiveApproval( address from, uint256 amount, address token, bytes calldata extraData ) external; }
{ "optimizer": { "enabled": true, "runs": 10000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"uint32","name":"unlockAt","type":"uint32"}],"name":"DepositLocked","type":"error"},{"inputs":[],"name":"DepositNotFound","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"IncorrectAmount","type":"error"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"}],"name":"IncorrectDepositor","type":"error"},{"inputs":[{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"IncorrectLockPeriod","type":"error"},{"inputs":[{"internalType":"enum Portal.TokenAbility","name":"ability","type":"uint8"}],"name":"IncorrectTokenAbility","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"IncorrectTokenAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"depositBalance","type":"uint256"}],"name":"InsufficientDepositAmount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"enum Portal.TokenAbility","name":"tokenAbility","type":"uint8"}],"name":"InsufficientTokenAbility","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[{"internalType":"uint32","name":"lockPeriod","type":"uint32"}],"name":"LockPeriodOutOfRange","type":"error"},{"inputs":[{"internalType":"uint32","name":"lockPeriod","type":"uint32"},{"internalType":"uint32","name":"newUnlockAt","type":"uint32"},{"internalType":"uint32","name":"existingUnlockAt","type":"uint32"}],"name":"LockPeriodTooShort","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":[{"internalType":"address","name":"token","type":"address"},{"internalType":"enum Portal.TokenAbility","name":"tokenAbility","type":"uint8"}],"name":"TokenAlreadySupported","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"TokenNotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","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":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"unlockAt","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"lockPeriod","type":"uint32"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"maxLockPeriod","type":"uint32"}],"name":"MaxLockPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"minLockPeriod","type":"uint32"}],"name":"MinLockPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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":"token","type":"address"},{"indexed":false,"internalType":"enum Portal.TokenAbility","name":"tokenAbility","type":"uint8"}],"name":"SupportedTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"enum Portal.TokenAbility","name":"tokenAbility","type":"uint8"}],"internalType":"struct Portal.SupportedToken","name":"supportedToken","type":"tuple"}],"name":"addSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint32","name":"lockPeriod","type":"uint32"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositOwner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint32","name":"lockPeriod","type":"uint32"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"deposits","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint32","name":"unlockAt","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"depositId","type":"uint256"}],"name":"getDeposit","outputs":[{"components":[{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint32","name":"unlockAt","type":"uint32"}],"internalType":"struct Portal.DepositInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"enum Portal.TokenAbility","name":"tokenAbility","type":"uint8"}],"internalType":"struct Portal.SupportedToken[]","name":"supportedTokens","type":"tuple[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"depositId","type":"uint256"},{"internalType":"uint32","name":"lockPeriod","type":"uint32"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxLockPeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minLockPeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"receiveApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_maxLockPeriod","type":"uint32"}],"name":"setMaxLockPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_minLockPeriod","type":"uint32"}],"name":"setMinLockPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenAbility","outputs":[{"internalType":"enum Portal.TokenAbility","name":"","type":"uint8"}],"stateMutability":"view","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":"depositId","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061001961001e565b6100d0565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006e5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cd5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b61212d80620000e06000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c806373ae54b5116100cd578063dfb6c2d211610081578063f2fde38b11610066578063f2fde38b1461037a578063f5e8d3271461038d578063f64a6c90146103a057600080fd5b8063dfb6c2d21461035f578063e30c39781461037257600080fd5b80638da5cb5b116100b25780638da5cb5b146103195780638f4ffcb11461033957806392673f551461034c57600080fd5b806373ae54b51461030157806379ba50971461031157600080fd5b8063563170e3116101245780636292ab35116101095780636292ab35146102b65780636572c5dd146102c9578063715018a6146102f957600080fd5b8063563170e3146101f55780635d93a3fc1461023757600080fd5b80632dfdf0b5116101555780632dfdf0b51461019957806331645d4e146101b55780634b1d29b4146101c857600080fd5b80630908c7dc146101715780632c4b24ae14610186575b600080fd5b61018461017f366004611aa5565b6103b3565b005b610184610194366004611b8f565b6105a7565b6101a260015481565b6040519081526020015b60405180910390f35b6101846101c3366004611c9b565b61086d565b6003546101e090640100000000900463ffffffff1681565b60405163ffffffff90911681526020016101ac565b610208610203366004611cde565b61087f565b6040805182516bffffffffffffffffffffffff16815260209283015163ffffffff1692810192909252016101ac565b61028d610245366004611cde565b600060208181529381526040808220855292815282812090935282529020546bffffffffffffffffffffffff8116906c01000000000000000000000000900463ffffffff1682565b604080516bffffffffffffffffffffffff909316835263ffffffff9091166020830152016101ac565b6101846102c4366004611d1a565b6108f6565b6102ec6102d7366004611d4d565b60026020526000908152604090205460ff1681565b6040516101ac9190611dd2565b610184610c9d565b6003546101e09063ffffffff1681565b610184610cb1565b610321610d12565b6040516001600160a01b0390911681526020016101ac565b610184610347366004611de0565b610d47565b61018461035a366004611e7b565b610dfa565b61018461036d366004611e96565b610ef5565b610321610f08565b610184610388366004611d4d565b610f31565b61018461039b366004611eea565b610fce565b6101846103ae366004611e7b565b61117d565b6103bb611265565b60006103ca6020830183611d4d565b905060006103de6040840160208501611f1d565b90506001600160a01b038216610430576040517f6a2e6fbf0000000000000000000000000000000000000000000000000000000081526001600160a01b03831660048201526024015b60405180910390fd5b600081600281111561044457610444611d68565b0361047d57806040517fd6a8a3da0000000000000000000000000000000000000000000000000000000081526004016104279190611dd2565b6001600160a01b038216600090815260026020819052604082205460ff16908111156104ab576104ab611d68565b14610504576001600160a01b038216600090815260026020526040908190205490517f71265fe200000000000000000000000000000000000000000000000000000000815261042791849160ff90911690600401611f38565b6001600160a01b0382166000908152600260208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690600190849081111561055c5761055c611d68565b0217905550816001600160a01b03167f29dd5553eda23e846a442697aeea6662a9699d1a79bb82afba4ba8994898b92c8260405161059a9190611dd2565b60405180910390a2505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156105f25750825b905060008267ffffffffffffffff16600114801561060f5750303b155b90508115801561061d575080155b15610654576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156106b55784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6106be336112b0565b600380547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016670167e9800024ea00179055600060018190555b865181101561080357600087828151811061071557610715611f55565b6020026020010151600001519050600088838151811061073757610737611f55565b602002602001015160200151905060006001600160a01b0316826001600160a01b03160361079c576040517f6a2e6fbf0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610427565b6001600160a01b0382166000908152600260208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169060019084908111156107f4576107f4611d68565b021790555050506001016106f8565b5083156108655784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b61087a33338585856112c1565b505050565b604080518082018252600080825260209182018190526001600160a01b0386811682528183528382209086168252825282812084825282528290208251808401909352546bffffffffffffffffffffffff811683526c01000000000000000000000000900463ffffffff16908201525b9392505050565b6001600160a01b03831660009081526002602052604081205460ff16906bffffffffffffffffffffffff8316900361096a576040517f88967d2f0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff83166004820152602401610427565b600081600281111561097e5761097e611d68565b036109c0576040517f06439c6b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610427565b336000908152602081815260408083206001600160a01b038816845282528083208684528252918290208251808401909352546bffffffffffffffffffffffff811683526c01000000000000000000000000900463ffffffff16908201526002826002811115610a3257610a32611d68565b148015610a485750806020015163ffffffff1642105b15610a8d5760208101516040517fced227db00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610427565b80516bffffffffffffffffffffffff8116600003610ad7576040517f411321ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806bffffffffffffffffffffffff16846bffffffffffffffffffffffff161115610b45576040517f40683b8e0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff808616600483015282166024820152604401610427565b6040516bffffffffffffffffffffffff8516815285906001600160a01b0388169033907f91fb9d98b786c57d74c099ccd2beca1739e9f6a81fb49001ca465c4b7591bbe29060200160405180910390a4806bffffffffffffffffffffffff16846bffffffffffffffffffffffff1603610c0c57336000908152602081815260408083206001600160a01b038a1684528252808320888452909152902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055610c7b565b610c168482611fb3565b336000908152602081815260408083206001600160a01b038b1684528252808320898452909152902080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff929092169190911790555b6108656001600160a01b038716336bffffffffffffffffffffffff8716611579565b610ca5611265565b610caf60006115ed565b565b3380610cbb610f08565b6001600160a01b031614610d06576040517f118cdaa70000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610427565b610d0f816115ed565b50565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b6001600160a01b0383163314610d94576040517f6a2e6fbf0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610427565b6bffffffffffffffffffffffff841115610ddd576040517f88967d2f00000000000000000000000000000000000000000000000000000000815260048101859052602401610427565b6000610deb82840184611e7b565b905061086586878688856112c1565b610e02611265565b6000610e0d82611641565b90508063ffffffff168263ffffffff16141580610e2e575063ffffffff8116155b80610e4c575060035463ffffffff6401000000009091048116908316115b15610e8b576040517f74af145000000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610427565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff84169081179091556040519081527f4c35d0e4acd88f9d47ba71b6a74a890a34499d0af9d7536e5b46c2b190ea18be9060200160405180910390a15050565b610f0284338585856112c1565b50505050565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00610d37565b610f39611265565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081178255610f95610d12565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b336000908152602081815260408083206001600160a01b038716845282528083208584529091528120805490916bffffffffffffffffffffffff9091169003611043576040517f411321ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03841660009081526002602081905260409091205460ff169081600281111561107557611075611d68565b146110b05784816040517ff8d3a936000000000000000000000000000000000000000000000000000000008152600401610427929190611f38565b81546c01000000000000000000000000900463ffffffff1660006110d633888888611663565b90508163ffffffff168163ffffffff1611611135576040517f9e03653a00000000000000000000000000000000000000000000000000000000815263ffffffff8087166004830152808316602483015283166044820152606401610427565b835463ffffffff9091166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff909116179092555050505050565b611185611265565b61118e81611641565b63ffffffff168163ffffffff161415806111b3575060035463ffffffff908116908216105b156111f2576040517f74af145000000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610427565b600380547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff1664010000000063ffffffff8416908102919091179091556040519081527fe02644567ab9266166c374f84f05396b070729fc139339e70d0237bb37e59dc59060200160405180910390a150565b3361126e610d12565b6001600160a01b031614610caf576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610427565b6112b861177c565b610d0f816117e3565b6001600160a01b03831660009081526002602052604081205460ff16908160028111156112f0576112f0611d68565b03611332576040517f06439c6b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610427565b60008263ffffffff161180156113595750600181600281111561135757611357611d68565b145b156113945783816040517ff8d3a936000000000000000000000000000000000000000000000000000000008152600401610427929190611f38565b6001600160a01b0386166113df576040517f9c64f6a10000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610427565b826bffffffffffffffffffffffff16600003611437576040517f88967d2f0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff84166004820152602401610427565b6001805490600061144783611fdf565b90915550506001546040516bffffffffffffffffffffffff8516815281906001600160a01b0380881691908a16907ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c59060200160405180910390a46040518060400160405280856bffffffffffffffffffffffff1681526020016114cd89888588611663565b63ffffffff9081169091526001600160a01b03808a16600090815260208181526040808320938b16808452938252808320878452825290912084518154959092015184166c01000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009095166bffffffffffffffffffffffff9283161794909417909355611570929091899130919089169061182e16565b50505050505050565b6040516001600160a01b0383811660248301526044820183905261087a91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611867565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815561163d826118e3565b5050565b600061165062093a8083612017565b61165d9062093a80612061565b92915050565b60008163ffffffff1660000361167a575042611774565b600061168583611641565b905063ffffffff811615806116a5575060035463ffffffff908116908216105b806116c3575060035463ffffffff6401000000009091048116908216115b15611702576040517f8dbf963f00000000000000000000000000000000000000000000000000000000815263ffffffff84166004820152602401610427565b600061170e8242612089565b905084866001600160a01b0316886001600160a01b03167f8b65b80ac62fde507cb8196bad6c93c114c2babc6ac846aae39ed6943ad36c49848660405161176892919063ffffffff92831681529116602082015260400190565b60405180910390a49150505b949350505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610caf576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117eb61177c565b6001600160a01b038116610d06576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610427565b6040516001600160a01b038481166024830152838116604483015260648201839052610f029186918216906323b872dd906084016115a6565b600061187c6001600160a01b0384168361196c565b905080516000141580156118a157508080602001905181019061189f91906120a6565b155b1561087a576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610427565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff000000000000000000000000000000000000000081166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60606108ef8383600084600080856001600160a01b0316848660405161199291906120c8565b60006040518083038185875af1925050503d80600081146119cf576040519150601f19603f3d011682016040523d82523d6000602084013e6119d4565b606091505b50915091506119e48683836119ee565b9695505050505050565b606082611a03576119fe82611a63565b6108ef565b8151158015611a1a57506001600160a01b0384163b155b15611a5c576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610427565b50806108ef565b805115611a735780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060408284031215611ab757600080fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b0f57611b0f611abd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b5c57611b5c611abd565b604052919050565b80356001600160a01b0381168114611b7b57600080fd5b919050565b803560038110611b7b57600080fd5b60006020808385031215611ba257600080fd5b823567ffffffffffffffff80821115611bba57600080fd5b818501915085601f830112611bce57600080fd5b813581811115611be057611be0611abd565b611bee848260051b01611b15565b818152848101925060069190911b830184019087821115611c0e57600080fd5b928401925b81841015611c605760408489031215611c2c5760008081fd5b611c34611aec565b611c3d85611b64565b8152611c4a868601611b80565b8187015283526040939093019291840191611c13565b979650505050505050565b80356bffffffffffffffffffffffff81168114611b7b57600080fd5b803563ffffffff81168114611b7b57600080fd5b600080600060608486031215611cb057600080fd5b611cb984611b64565b9250611cc760208501611c6b565b9150611cd560408501611c87565b90509250925092565b600080600060608486031215611cf357600080fd5b611cfc84611b64565b9250611d0a60208501611b64565b9150604084013590509250925092565b600080600060608486031215611d2f57600080fd5b611d3884611b64565b925060208401359150611cd560408501611c6b565b600060208284031215611d5f57600080fd5b6108ef82611b64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611dce577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161165d8284611d97565b600080600080600060808688031215611df857600080fd5b611e0186611b64565b945060208601359350611e1660408701611b64565b9250606086013567ffffffffffffffff80821115611e3357600080fd5b818801915088601f830112611e4757600080fd5b813581811115611e5657600080fd5b896020828501011115611e6857600080fd5b9699959850939650602001949392505050565b600060208284031215611e8d57600080fd5b6108ef82611c87565b60008060008060808587031215611eac57600080fd5b611eb585611b64565b9350611ec360208601611b64565b9250611ed160408601611c6b565b9150611edf60608601611c87565b905092959194509250565b600080600060608486031215611eff57600080fd5b611f0884611b64565b925060208401359150611cd560408501611c87565b600060208284031215611f2f57600080fd5b6108ef82611b80565b6001600160a01b0383168152604081016108ef6020830184611d97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115611fd857611fd8611f84565b5092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361201057612010611f84565b5060010190565b600063ffffffff80841680612055577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b63ffffffff81811683821602808216919082811461208157612081611f84565b505092915050565b63ffffffff818116838216019080821115611fd857611fd8611f84565b6000602082840312156120b857600080fd5b815180151581146108ef57600080fd5b6000825160005b818110156120e957602081860181015185830152016120cf565b50600092019182525091905056fea264697066735822122073940cb6d868c921af08a0b03a650ffcd9915be2d2552a0e40452058f7b176c564736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061016c5760003560e01c806373ae54b5116100cd578063dfb6c2d211610081578063f2fde38b11610066578063f2fde38b1461037a578063f5e8d3271461038d578063f64a6c90146103a057600080fd5b8063dfb6c2d21461035f578063e30c39781461037257600080fd5b80638da5cb5b116100b25780638da5cb5b146103195780638f4ffcb11461033957806392673f551461034c57600080fd5b806373ae54b51461030157806379ba50971461031157600080fd5b8063563170e3116101245780636292ab35116101095780636292ab35146102b65780636572c5dd146102c9578063715018a6146102f957600080fd5b8063563170e3146101f55780635d93a3fc1461023757600080fd5b80632dfdf0b5116101555780632dfdf0b51461019957806331645d4e146101b55780634b1d29b4146101c857600080fd5b80630908c7dc146101715780632c4b24ae14610186575b600080fd5b61018461017f366004611aa5565b6103b3565b005b610184610194366004611b8f565b6105a7565b6101a260015481565b6040519081526020015b60405180910390f35b6101846101c3366004611c9b565b61086d565b6003546101e090640100000000900463ffffffff1681565b60405163ffffffff90911681526020016101ac565b610208610203366004611cde565b61087f565b6040805182516bffffffffffffffffffffffff16815260209283015163ffffffff1692810192909252016101ac565b61028d610245366004611cde565b600060208181529381526040808220855292815282812090935282529020546bffffffffffffffffffffffff8116906c01000000000000000000000000900463ffffffff1682565b604080516bffffffffffffffffffffffff909316835263ffffffff9091166020830152016101ac565b6101846102c4366004611d1a565b6108f6565b6102ec6102d7366004611d4d565b60026020526000908152604090205460ff1681565b6040516101ac9190611dd2565b610184610c9d565b6003546101e09063ffffffff1681565b610184610cb1565b610321610d12565b6040516001600160a01b0390911681526020016101ac565b610184610347366004611de0565b610d47565b61018461035a366004611e7b565b610dfa565b61018461036d366004611e96565b610ef5565b610321610f08565b610184610388366004611d4d565b610f31565b61018461039b366004611eea565b610fce565b6101846103ae366004611e7b565b61117d565b6103bb611265565b60006103ca6020830183611d4d565b905060006103de6040840160208501611f1d565b90506001600160a01b038216610430576040517f6a2e6fbf0000000000000000000000000000000000000000000000000000000081526001600160a01b03831660048201526024015b60405180910390fd5b600081600281111561044457610444611d68565b0361047d57806040517fd6a8a3da0000000000000000000000000000000000000000000000000000000081526004016104279190611dd2565b6001600160a01b038216600090815260026020819052604082205460ff16908111156104ab576104ab611d68565b14610504576001600160a01b038216600090815260026020526040908190205490517f71265fe200000000000000000000000000000000000000000000000000000000815261042791849160ff90911690600401611f38565b6001600160a01b0382166000908152600260208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911690600190849081111561055c5761055c611d68565b0217905550816001600160a01b03167f29dd5553eda23e846a442697aeea6662a9699d1a79bb82afba4ba8994898b92c8260405161059a9190611dd2565b60405180910390a2505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156105f25750825b905060008267ffffffffffffffff16600114801561060f5750303b155b90508115801561061d575080155b15610654576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156106b55784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6106be336112b0565b600380547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016670167e9800024ea00179055600060018190555b865181101561080357600087828151811061071557610715611f55565b6020026020010151600001519050600088838151811061073757610737611f55565b602002602001015160200151905060006001600160a01b0316826001600160a01b03160361079c576040517f6a2e6fbf0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610427565b6001600160a01b0382166000908152600260208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169060019084908111156107f4576107f4611d68565b021790555050506001016106f8565b5083156108655784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b61087a33338585856112c1565b505050565b604080518082018252600080825260209182018190526001600160a01b0386811682528183528382209086168252825282812084825282528290208251808401909352546bffffffffffffffffffffffff811683526c01000000000000000000000000900463ffffffff16908201525b9392505050565b6001600160a01b03831660009081526002602052604081205460ff16906bffffffffffffffffffffffff8316900361096a576040517f88967d2f0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff83166004820152602401610427565b600081600281111561097e5761097e611d68565b036109c0576040517f06439c6b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610427565b336000908152602081815260408083206001600160a01b038816845282528083208684528252918290208251808401909352546bffffffffffffffffffffffff811683526c01000000000000000000000000900463ffffffff16908201526002826002811115610a3257610a32611d68565b148015610a485750806020015163ffffffff1642105b15610a8d5760208101516040517fced227db00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610427565b80516bffffffffffffffffffffffff8116600003610ad7576040517f411321ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806bffffffffffffffffffffffff16846bffffffffffffffffffffffff161115610b45576040517f40683b8e0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff808616600483015282166024820152604401610427565b6040516bffffffffffffffffffffffff8516815285906001600160a01b0388169033907f91fb9d98b786c57d74c099ccd2beca1739e9f6a81fb49001ca465c4b7591bbe29060200160405180910390a4806bffffffffffffffffffffffff16846bffffffffffffffffffffffff1603610c0c57336000908152602081815260408083206001600160a01b038a1684528252808320888452909152902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055610c7b565b610c168482611fb3565b336000908152602081815260408083206001600160a01b038b1684528252808320898452909152902080547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff929092169190911790555b6108656001600160a01b038716336bffffffffffffffffffffffff8716611579565b610ca5611265565b610caf60006115ed565b565b3380610cbb610f08565b6001600160a01b031614610d06576040517f118cdaa70000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610427565b610d0f816115ed565b50565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b6001600160a01b0383163314610d94576040517f6a2e6fbf0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610427565b6bffffffffffffffffffffffff841115610ddd576040517f88967d2f00000000000000000000000000000000000000000000000000000000815260048101859052602401610427565b6000610deb82840184611e7b565b905061086586878688856112c1565b610e02611265565b6000610e0d82611641565b90508063ffffffff168263ffffffff16141580610e2e575063ffffffff8116155b80610e4c575060035463ffffffff6401000000009091048116908316115b15610e8b576040517f74af145000000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610427565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff84169081179091556040519081527f4c35d0e4acd88f9d47ba71b6a74a890a34499d0af9d7536e5b46c2b190ea18be9060200160405180910390a15050565b610f0284338585856112c1565b50505050565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00610d37565b610f39611265565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081178255610f95610d12565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b336000908152602081815260408083206001600160a01b038716845282528083208584529091528120805490916bffffffffffffffffffffffff9091169003611043576040517f411321ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03841660009081526002602081905260409091205460ff169081600281111561107557611075611d68565b146110b05784816040517ff8d3a936000000000000000000000000000000000000000000000000000000008152600401610427929190611f38565b81546c01000000000000000000000000900463ffffffff1660006110d633888888611663565b90508163ffffffff168163ffffffff1611611135576040517f9e03653a00000000000000000000000000000000000000000000000000000000815263ffffffff8087166004830152808316602483015283166044820152606401610427565b835463ffffffff9091166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff909116179092555050505050565b611185611265565b61118e81611641565b63ffffffff168163ffffffff161415806111b3575060035463ffffffff908116908216105b156111f2576040517f74af145000000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610427565b600380547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff1664010000000063ffffffff8416908102919091179091556040519081527fe02644567ab9266166c374f84f05396b070729fc139339e70d0237bb37e59dc59060200160405180910390a150565b3361126e610d12565b6001600160a01b031614610caf576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610427565b6112b861177c565b610d0f816117e3565b6001600160a01b03831660009081526002602052604081205460ff16908160028111156112f0576112f0611d68565b03611332576040517f06439c6b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610427565b60008263ffffffff161180156113595750600181600281111561135757611357611d68565b145b156113945783816040517ff8d3a936000000000000000000000000000000000000000000000000000000008152600401610427929190611f38565b6001600160a01b0386166113df576040517f9c64f6a10000000000000000000000000000000000000000000000000000000081526001600160a01b0387166004820152602401610427565b826bffffffffffffffffffffffff16600003611437576040517f88967d2f0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff84166004820152602401610427565b6001805490600061144783611fdf565b90915550506001546040516bffffffffffffffffffffffff8516815281906001600160a01b0380881691908a16907ff5681f9d0db1b911ac18ee83d515a1cf1051853a9eae418316a2fdf7dea427c59060200160405180910390a46040518060400160405280856bffffffffffffffffffffffff1681526020016114cd89888588611663565b63ffffffff9081169091526001600160a01b03808a16600090815260208181526040808320938b16808452938252808320878452825290912084518154959092015184166c01000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009095166bffffffffffffffffffffffff9283161794909417909355611570929091899130919089169061182e16565b50505050505050565b6040516001600160a01b0383811660248301526044820183905261087a91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611867565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815561163d826118e3565b5050565b600061165062093a8083612017565b61165d9062093a80612061565b92915050565b60008163ffffffff1660000361167a575042611774565b600061168583611641565b905063ffffffff811615806116a5575060035463ffffffff908116908216105b806116c3575060035463ffffffff6401000000009091048116908216115b15611702576040517f8dbf963f00000000000000000000000000000000000000000000000000000000815263ffffffff84166004820152602401610427565b600061170e8242612089565b905084866001600160a01b0316886001600160a01b03167f8b65b80ac62fde507cb8196bad6c93c114c2babc6ac846aae39ed6943ad36c49848660405161176892919063ffffffff92831681529116602082015260400190565b60405180910390a49150505b949350505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610caf576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117eb61177c565b6001600160a01b038116610d06576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610427565b6040516001600160a01b038481166024830152838116604483015260648201839052610f029186918216906323b872dd906084016115a6565b600061187c6001600160a01b0384168361196c565b905080516000141580156118a157508080602001905181019061189f91906120a6565b155b1561087a576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610427565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff000000000000000000000000000000000000000081166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60606108ef8383600084600080856001600160a01b0316848660405161199291906120c8565b60006040518083038185875af1925050503d80600081146119cf576040519150601f19603f3d011682016040523d82523d6000602084013e6119d4565b606091505b50915091506119e48683836119ee565b9695505050505050565b606082611a03576119fe82611a63565b6108ef565b8151158015611a1a57506001600160a01b0384163b155b15611a5c576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610427565b50806108ef565b805115611a735780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060408284031215611ab757600080fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b0f57611b0f611abd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b5c57611b5c611abd565b604052919050565b80356001600160a01b0381168114611b7b57600080fd5b919050565b803560038110611b7b57600080fd5b60006020808385031215611ba257600080fd5b823567ffffffffffffffff80821115611bba57600080fd5b818501915085601f830112611bce57600080fd5b813581811115611be057611be0611abd565b611bee848260051b01611b15565b818152848101925060069190911b830184019087821115611c0e57600080fd5b928401925b81841015611c605760408489031215611c2c5760008081fd5b611c34611aec565b611c3d85611b64565b8152611c4a868601611b80565b8187015283526040939093019291840191611c13565b979650505050505050565b80356bffffffffffffffffffffffff81168114611b7b57600080fd5b803563ffffffff81168114611b7b57600080fd5b600080600060608486031215611cb057600080fd5b611cb984611b64565b9250611cc760208501611c6b565b9150611cd560408501611c87565b90509250925092565b600080600060608486031215611cf357600080fd5b611cfc84611b64565b9250611d0a60208501611b64565b9150604084013590509250925092565b600080600060608486031215611d2f57600080fd5b611d3884611b64565b925060208401359150611cd560408501611c6b565b600060208284031215611d5f57600080fd5b6108ef82611b64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611dce577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161165d8284611d97565b600080600080600060808688031215611df857600080fd5b611e0186611b64565b945060208601359350611e1660408701611b64565b9250606086013567ffffffffffffffff80821115611e3357600080fd5b818801915088601f830112611e4757600080fd5b813581811115611e5657600080fd5b896020828501011115611e6857600080fd5b9699959850939650602001949392505050565b600060208284031215611e8d57600080fd5b6108ef82611c87565b60008060008060808587031215611eac57600080fd5b611eb585611b64565b9350611ec360208601611b64565b9250611ed160408601611c6b565b9150611edf60608601611c87565b905092959194509250565b600080600060608486031215611eff57600080fd5b611f0884611b64565b925060208401359150611cd560408501611c87565b600060208284031215611f2f57600080fd5b6108ef82611b80565b6001600160a01b0383168152604081016108ef6020830184611d97565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6bffffffffffffffffffffffff828116828216039080821115611fd857611fd8611f84565b5092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361201057612010611f84565b5060010190565b600063ffffffff80841680612055577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b63ffffffff81811683821602808216919082811461208157612081611f84565b505092915050565b63ffffffff818116838216019080821115611fd857611fd8611f84565b6000602082840312156120b857600080fd5b815180151581146108ef57600080fd5b6000825160005b818110156120e957602081860181015185830152016120cf565b50600092019182525091905056fea264697066735822122073940cb6d868c921af08a0b03a650ffcd9915be2d2552a0e40452058f7b176c564736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.