ERC-20
Liquid staking
Overview
Max Total Supply
114.991296041311387444 inETH
Holders
206
Market
Price
$3,980.29 @ 1.006185 ETH
Onchain Market Cap
$457,698.71
Circulating Supply Market Cap
$0.00
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
XERC20
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "../interfaces/IXERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { /** * @notice The duration it takes for the limits to fully replenish */ uint256 private constant _DURATION = 1 days; /** * @notice The address of the factory which deployed this contract */ address public immutable FACTORY; /** * @notice The address of the lockbox contract */ address public lockbox; /** * @notice Maps bridge address to bridge configurations */ mapping(address => Bridge) public bridges; /** * @param _name The name of the token * @param _symbol The symbol of the token * @param _factory The factory which deployed this contract */ constructor( string memory _name, string memory _symbol, address _factory ) ERC20(_name, _symbol) ERC20Permit(_name) { _transferOwnership(_factory); FACTORY = _factory; } /** * @notice Mints tokens for a user * @dev Can only be called by a bridge * @param _user The address of the user who needs tokens minted * @param _amount The amount of tokens being minted */ function mint(address _user, uint256 _amount) external { _mintWithCaller(msg.sender, _user, _amount); } /** * @notice Burns tokens for a user * @dev Can only be called by a bridge * @param _user The address of the user who needs tokens burned * @param _amount The amount of tokens being burned */ function burn(address _user, uint256 _amount) external { _burnWithCaller(msg.sender, _user, _amount); } /** * @notice Sets the lockbox address * @param _lockbox The address of the lockbox */ function setLockbox(address _lockbox) external { if (msg.sender != FACTORY) revert IXERC20_NotFactory(); lockbox = _lockbox; emit LockboxSet(_lockbox); } /** * @notice Updates the limits of any bridge * @dev Can only be called by the owner * @param _mintingLimit The updated minting limit we are setting to the bridge * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limits too */ function setBridgeLimits( address _bridge, uint256 _mintingLimit, uint256 _burningLimit ) external onlyOwner { _changeMinterLimit(_bridge, _mintingLimit); _changeBurnerLimit(_bridge, _burningLimit); emit BridgeLimitsSet(_mintingLimit, _burningLimit, _bridge); } /** * @notice Returns the max limit of a bridge * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function mintingMaxLimitOf( address _bridge ) external view returns (uint256 _limit) { _limit = bridges[_bridge].minterParams.maxLimit; } /** * @notice Returns the max limit of a bridge * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningMaxLimitOf( address _bridge ) external view returns (uint256 _limit) { _limit = bridges[_bridge].burnerParams.maxLimit; } /** * @notice Returns the current limit of a bridge * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function mintingCurrentLimitOf( address _bridge ) public view returns (uint256 _limit) { _limit = _getCurrentLimit( bridges[_bridge].minterParams.currentLimit, bridges[_bridge].minterParams.maxLimit, bridges[_bridge].minterParams.timestamp, bridges[_bridge].minterParams.ratePerSecond ); } /** * @notice Returns the current limit of a bridge * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningCurrentLimitOf( address _bridge ) public view returns (uint256 _limit) { _limit = _getCurrentLimit( bridges[_bridge].burnerParams.currentLimit, bridges[_bridge].burnerParams.maxLimit, bridges[_bridge].burnerParams.timestamp, bridges[_bridge].burnerParams.ratePerSecond ); } /** * @notice Uses the limit of any bridge * @param _bridge The address of the bridge who is being changed * @param _change The change in the limit */ function _useMinterLimits(address _bridge, uint256 _change) internal { uint256 _currentLimit = mintingCurrentLimitOf(_bridge); bridges[_bridge].minterParams.timestamp = block.timestamp; bridges[_bridge].minterParams.currentLimit = _currentLimit - _change; } /** * @notice Uses the limit of any bridge * @param _bridge The address of the bridge who is being changed * @param _change The change in the limit */ function _useBurnerLimits(address _bridge, uint256 _change) internal { uint256 _currentLimit = burningCurrentLimitOf(_bridge); bridges[_bridge].burnerParams.timestamp = block.timestamp; bridges[_bridge].burnerParams.currentLimit = _currentLimit - _change; } /** * @notice Updates the limit of any bridge * @dev Can only be called by the owner * @param _bridge The address of the bridge we are setting the limit too * @param _limit The updated limit we are setting to the bridge */ function _changeMinterLimit(address _bridge, uint256 _limit) internal { if (_limit < _DURATION && _limit > 0) revert IXERC20_WrongBridgeLimit(); uint256 _oldLimit = bridges[_bridge].minterParams.maxLimit; uint256 _currentLimit = mintingCurrentLimitOf(_bridge); bridges[_bridge].minterParams.maxLimit = _limit; bridges[_bridge].minterParams.currentLimit = _calculateNewCurrentLimit( _limit, _oldLimit, _currentLimit ); bridges[_bridge].minterParams.ratePerSecond = _limit / _DURATION; bridges[_bridge].minterParams.timestamp = block.timestamp; } /** * @notice Updates the limit of any bridge * @dev Can only be called by the owner * @param _bridge The address of the bridge we are setting the limit too * @param _limit The updated limit we are setting to the bridge */ function _changeBurnerLimit(address _bridge, uint256 _limit) internal { if (_limit < _DURATION && _limit > 0) revert IXERC20_WrongBridgeLimit(); uint256 _oldLimit = bridges[_bridge].burnerParams.maxLimit; uint256 _currentLimit = burningCurrentLimitOf(_bridge); bridges[_bridge].burnerParams.maxLimit = _limit; bridges[_bridge].burnerParams.currentLimit = _calculateNewCurrentLimit( _limit, _oldLimit, _currentLimit ); bridges[_bridge].burnerParams.ratePerSecond = _limit / _DURATION; bridges[_bridge].burnerParams.timestamp = block.timestamp; } /** * @param _limit The new limit * @param _oldLimit The old limit * @param _currentLimit The current limit * @return _newCurrentLimit The new current limit */ function _calculateNewCurrentLimit( uint256 _limit, uint256 _oldLimit, uint256 _currentLimit ) internal pure returns (uint256 _newCurrentLimit) { uint256 _difference; if (_oldLimit > _limit) { _difference = _oldLimit - _limit; _newCurrentLimit = _currentLimit > _difference ? _currentLimit - _difference : 0; } else { _difference = _limit - _oldLimit; _newCurrentLimit = _currentLimit + _difference; } } /** * @param _currentLimit The current limit * @param _maxLimit The max limit * @param _timestamp The timestamp of the last update * @param _ratePerSecond The rate per second * @return _limit The current limit */ function _getCurrentLimit( uint256 _currentLimit, uint256 _maxLimit, uint256 _timestamp, uint256 _ratePerSecond ) internal view returns (uint256 _limit) { _limit = _currentLimit; if (_limit == _maxLimit) { return _limit; } else if (_timestamp + _DURATION <= block.timestamp) { _limit = _maxLimit; } else if (_timestamp + _DURATION > block.timestamp) { uint256 _timePassed = block.timestamp - _timestamp; uint256 _calculatedLimit = _limit + (_timePassed * _ratePerSecond); _limit = _calculatedLimit > _maxLimit ? _maxLimit : _calculatedLimit; } } /** * @param _caller The caller address * @param _user The user address * @param _amount The amount to burn */ function _burnWithCaller( address _caller, address _user, uint256 _amount ) internal { if (_caller != lockbox) { uint256 _currentLimit = burningCurrentLimitOf(_caller); if (_currentLimit < _amount) revert IXERC20_NotHighEnoughLimits(); _useBurnerLimits(_caller, _amount); } _burn(_user, _amount); } /** * @param _caller The caller address * @param _user The user address * @param _amount The amount to mint */ function _mintWithCaller( address _caller, address _user, uint256 _amount ) internal { if (_caller != lockbox) { uint256 _currentLimit = mintingCurrentLimitOf(_caller); if (_currentLimit < _amount) revert IXERC20_NotHighEnoughLimits(); _useMinterLimits(_caller, _amount); } _mint(_user, _amount); } }
// 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) (utils/Pausable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: 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 v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ 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 v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../token/ERC20/extensions/IERC20Metadata.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.0; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @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. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; import "../Proxy.sol"; import "./ERC1967Upgrade.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializing the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) payable { _upgradeToAndCall(_logic, _data, false); } /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @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 EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ 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 EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol) pragma solidity ^0.8.0; import "./TransparentUpgradeableProxy.sol"; import "../../access/Ownable.sol"; /** * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. */ contract ProxyAdmin is Ownable { /** * @dev Returns the current implementation of `proxy`. * * Requirements: * * - This contract must be the admin of `proxy`. */ function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) { // We need to manually run the static call since the getter cannot be flagged as view // bytes4(keccak256("implementation()")) == 0x5c60da1b (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); require(success); return abi.decode(returndata, (address)); } /** * @dev Returns the current admin of `proxy`. * * Requirements: * * - This contract must be the admin of `proxy`. */ function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) { // We need to manually run the static call since the getter cannot be flagged as view // bytes4(keccak256("admin()")) == 0xf851a440 (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); require(success); return abi.decode(returndata, (address)); } /** * @dev Changes the admin of `proxy` to `newAdmin`. * * Requirements: * * - This contract must be the current admin of `proxy`. */ function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner { proxy.changeAdmin(newAdmin); } /** * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner { proxy.upgradeTo(implementation); } /** * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See * {TransparentUpgradeableProxy-upgradeToAndCall}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgradeAndCall( ITransparentUpgradeableProxy proxy, address implementation, bytes memory data ) public payable virtual onlyOwner { proxy.upgradeToAndCall{value: msg.value}(implementation, data); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.0; import "../ERC1967/ERC1967Proxy.sol"; /** * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} * does not implement this interface directly, and some of its functions are implemented by an internal dispatch * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not * include them in the ABI so this interface must be used to interact with it. */ interface ITransparentUpgradeableProxy is IERC1967 { function admin() external view returns (address); function implementation() external view returns (address); function changeAdmin(address) external; function upgradeTo(address) external; function upgradeToAndCall(address, bytes memory) external payable; } /** * @dev This contract implements a proxy that is upgradeable by an admin. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the * implementation. If the admin tries to call a function on the implementation it will fail with an error that says * "admin cannot fallback to proxy target". * * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due * to sudden errors when trying to call a function from the proxy implementation. * * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. * * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the * implementation. * * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. */ constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) { _changeAdmin(admin_); } /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. * * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the * implementation provides a function with the same selector. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior */ function _fallback() internal virtual override { if (msg.sender == _getAdmin()) { bytes memory ret; bytes4 selector = msg.sig; if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) { ret = _dispatchUpgradeTo(); } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) { ret = _dispatchUpgradeToAndCall(); } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) { ret = _dispatchChangeAdmin(); } else if (selector == ITransparentUpgradeableProxy.admin.selector) { ret = _dispatchAdmin(); } else if (selector == ITransparentUpgradeableProxy.implementation.selector) { ret = _dispatchImplementation(); } else { revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target"); } assembly { return(add(ret, 0x20), mload(ret)) } } else { super._fallback(); } } /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function _dispatchAdmin() private returns (bytes memory) { _requireZeroValue(); address admin = _getAdmin(); return abi.encode(admin); } /** * @dev Returns the current implementation. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _dispatchImplementation() private returns (bytes memory) { _requireZeroValue(); address implementation = _implementation(); return abi.encode(implementation); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _dispatchChangeAdmin() private returns (bytes memory) { _requireZeroValue(); address newAdmin = abi.decode(msg.data[4:], (address)); _changeAdmin(newAdmin); return ""; } /** * @dev Upgrade the implementation of the proxy. */ function _dispatchUpgradeTo() private returns (bytes memory) { _requireZeroValue(); address newImplementation = abi.decode(msg.data[4:], (address)); _upgradeToAndCall(newImplementation, bytes(""), false); return ""; } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. */ function _dispatchUpgradeToAndCall() private returns (bytes memory) { (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes)); _upgradeToAndCall(newImplementation, data, true); return ""; } /** * @dev Returns the current admin. * * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to * emulate some proxy functions being non-payable while still allowing value to pass through. */ function _requireZeroValue() private { require(msg.value == 0); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.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}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * 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 ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { 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 override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` 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 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * 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 `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `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. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` 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. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/ERC20Permit.sol) pragma solidity ^0.8.0; import "./IERC20Permit.sol"; import "../ERC20.sol"; import "../../../utils/cryptography/ECDSA.sol"; import "../../../utils/cryptography/EIP712.sol"; import "../../../utils/Counters.sol"; /** * @dev Implementation 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. * * _Available since v3.4._ */ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { using Counters for Counters.Counter; mapping(address => Counters.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /** * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. * However, to ensure consistency with the upgradeable transpiler, we will continue * to reserve a slot. * @custom:oz-renamed-from _PERMIT_TYPEHASH */ // solhint-disable-next-line var-name-mixedcase bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ constructor(string memory name) EIP712(name, "1") {} /** * @inheritdoc IERC20Permit */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual override { require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _approve(owner, spender, value); } /** * @inheritdoc IERC20Permit */ function nonces(address owner) public view virtual override returns (uint256) { return _nonces[owner].current(); } /** * @inheritdoc IERC20Permit */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } /** * @dev "Consume a nonce": return the current value and increment. * * _Available since v4.1._ */ function _useNonce(address owner) internal virtual returns (uint256 current) { Counters.Counter storage nonce = _nonces[owner]; current = nonce.current(); nonce.increment(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.8; import "./ECDSA.sol"; import "../ShortStrings.sol"; import "../../interfaces/IERC5267.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _name.toStringWithFallback(_nameFallback), _version.toStringWithFallback(_versionFallback), block.chainid, address(this), bytes32(0), new uint256[](0) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) pragma solidity ^0.8.8; import "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @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 ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 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) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { 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) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { 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) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; pragma abicoder v2; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts/interfaces/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./InceptionBridgeStorage.sol"; import "../interfaces/IInceptionBridge.sol"; import "../interfaces/IXERC20Lockbox.sol"; import "../lib/EthereumVerifier.sol"; import "../lib/ProofParser.sol"; import "../lib/Utils.sol"; /// @author The InceptionLRT team /// @title The InceptionBridge contract /// @notice Facilitates cross-chain token(asset) transfers using the burn-mint pattern. contract InceptionBridge is OwnableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, InceptionBridgeStorage, IInceptionBridge { using SafeERC20 for IERC20; /// @custom:oz-upgrades-unsafe-allow constructor /// @dev payable modifier reduces the deployment cost constructor() payable { _disableInitializers(); } function initialize( address initialOwner, address notary ) external initializer { __Ownable_init(initialOwner); __Pausable_init(); __ReentrancyGuard_init(); __initInceptionBridgeStorage(notary); } /*////////////////////////////// ////// Deposit functions ////// ////////////////////////////*/ /** * @dev Tokens on source and destination chains are linked with independent supplies. * Burns tokens on source chain (to later mint it on the destination chain). * @param fromToken is one of the many supported tokens on the current chain. * @param destinationChain is the destination chain ID. * @param receiver of `amount` on the destination chain. * @param amount of tokens to be transferred */ function deposit( address fromToken, uint256 destinationChain, address receiver, uint256 amount ) external override nonReentrant whenNotPaused { _beforeDeposit(); _updateDepositCaps(fromToken, amount); if (getDestination(fromToken, destinationChain) != address(0)) { _deposit(fromToken, destinationChain, receiver, amount); } else revert UnknownDestinationChain(); } function _deposit( address fromToken, uint256 destinationChain, address receiver, uint256 amount ) internal { if (_bridgeAddressByChainId[destinationChain] == address(0)) { revert UnknownDestinationChain(); } address sender = msg.sender; address lockbox = xerc20TokenRegistry[fromToken]; if (lockbox == address(0)) { _safeBurn(fromToken, sender, amount); } else { _depositIntoLockbox(lockbox, fromToken, sender, amount); } Metadata memory metaData = Metadata( Utils.stringToBytes32(IERC20Extra(fromToken).name()), Utils.stringToBytes32(IERC20Extra(fromToken).symbol()), 0, address(0) ); unchecked { ++_globalNonce; } emit Deposited( destinationChain, _bridgeAddressByChainId[destinationChain], sender, receiver, fromToken, getDestination(fromToken, destinationChain), amount, _globalNonce, metaData ); } function _depositIntoLockbox( address lockbox, address fromToken, address sender, uint256 amount ) internal { address xerc20 = address(IXERC20Lockbox(lockbox).XERC20()); if (xerc20 == address(0)) revert XERC20ZeroAddress(); /// deposit into the lockBox IERC20(fromToken).safeTransferFrom(sender, address(this), amount); IERC20(fromToken).safeApprove(lockbox, amount); IXERC20Lockbox(lockbox).deposit(amount); _safeBurn(xerc20, address(this), amount); } /*///////////////////////////////// ////// Withdrawal functions ////// ///////////////////////////////*/ /// @dev Serves the authorized (signed) withdrawal request by the bridge committee. /// @dev Mints the corresponding token to the `Deposited.receiver` address. /// `encodedProof` represents the RLP-encoded 'Deposited' receipt. /// @param rawReceipt is the raw deposit transaction receipt. /// @param proofSignature is the signature of keccak256(`encodedProof`) by the operator. function withdraw( /* encodedProof */ bytes calldata, bytes calldata rawReceipt, bytes memory proofSignature ) external override nonReentrant whenNotPaused { uint256 proofOffset; uint256 receiptOffset; assembly { proofOffset := add(0x4, calldataload(4)) receiptOffset := add(0x4, calldataload(36)) } ( EthereumVerifier.State memory state, EthereumVerifier.DepositType depositType ) = EthereumVerifier.parseTransactionReceipt(receiptOffset); if (state.chainId != block.chainid) revert ReceiptWrongChain(block.chainid, state.chainId); ProofParser.Proof memory proof = ProofParser.parseProof(proofOffset); if (state.contractAddress == address(0)) revert InvalidContractAddress(); if (state.destinationContract != address(this)) revert WrongDestinationBridge(); if (_bridgeAddressByChainId[proof.chainId] != state.contractAddress) revert UnknownBridge(); state.receiptHash = keccak256(rawReceipt); proof.status = 0x01; proof.receiptHash = state.receiptHash; bytes32 proofHash; assembly { proofHash := keccak256(proof, _PROOF_LENGTH) } if (ECDSA.recover(proofHash, proofSignature) != notary) revert WrongSignature(); _withdraw(state, depositType, proof, proofHash); } function _withdraw( EthereumVerifier.State memory state, EthereumVerifier.DepositType depositType, ProofParser.Proof memory proof, bytes32 payload ) internal { if (_usedProofs[payload]) { revert WithdrawalProofUsed(); } _usedProofs[payload] = true; if (depositType == EthereumVerifier.DepositType.TokenDeposit) { _withdraw(state, proof); } else revert InvalidAssetType(); } function _withdraw( EthereumVerifier.State memory state, ProofParser.Proof memory proof ) internal { if (state.fromToken == address(0)) revert InvalidFromTokenAddress(); if (getDestination(state.toToken, proof.chainId) != state.fromToken) revert UnknownDestination(); _updateWithdrawCaps(state.toToken, state.amount); address lockbox = xerc20TokenRegistry[state.toToken]; if (lockbox == address(0)) { _safeMint(state.toToken, state.receiver, state.amount); } else { address xerc20 = address(IXERC20Lockbox(lockbox).XERC20()); if (xerc20 == address(0)) revert XERC20ZeroAddress(); _safeMint(xerc20, address(this), state.amount); IXERC20Lockbox(lockbox).withdrawTo(state.receiver, state.amount); } emit Withdrawn( state.receiptHash, state.sender, state.receiver, state.fromToken, state.toToken, state.amount ); } function getDestination( address fromToken, uint256 destinationChain ) public view returns (address) { return _destinationTokens[ keccak256( abi.encodePacked( fromToken, block.chainid, _bridgeAddressByChainId[destinationChain], destinationChain ) ) ]; } /*////////////////////////// ////// SET functions ////// ////////////////////////*/ function setNotary(address notaryAddress) external onlyOwner { _setNotary(notaryAddress); } function setShortCap( address tokenAddress, uint256 amount ) external onlyOwner { _setShortCap(tokenAddress, amount); } function setShortCapDuration(uint256 duration) external onlyOwner { _setShortCapDuration(duration); } function setLongCapDuration(uint256 duration) external onlyOwner { _setLongCapDuration(duration); } function setLongCap(address token, uint256 amount) external onlyOwner { _setLongCap(token, amount); } function addBridge( address bridge, uint256 destinationChain ) external onlyOwner { _addBridge(bridge, destinationChain); } function removeBridge(uint256 destinationChain) external onlyOwner { _removeBridge(destinationChain); } function addDestination( address fromToken, uint256 destinationChain, address toToken ) external onlyOwner { _addDestination(fromToken, destinationChain, toToken); } function removeDestination( address fromToken, uint256 destinationChain, address toToken ) external onlyOwner { _removeDestination(fromToken, destinationChain, toToken); } function setXERC20Lockbox( address token, address xerc20Lockbox ) external onlyOwner { _setXERC20Lockbox(token, xerc20Lockbox); } /*/////////////////////////////// ////// Pausable functions ////// /////////////////////////////*/ function pause() external onlyOwner { _pause(); } function unpause() external onlyOwner { _unpause(); } /*/////////////////////////////// //////// Safe functions //////// /////////////////////////////*/ function _safeBurn( address token, address account, uint256 amount ) internal { uint256 balanceBefore = IERC20(token).balanceOf(account); IERC20Mintable(token).burn(account, amount); uint256 balanceAfter = IERC20(token).balanceOf(account); if (balanceAfter + amount != balanceBefore) { revert BurnFailed(); } } function _safeMint( address token, address account, uint256 amount ) internal { uint256 balanceBefore = IERC20(token).balanceOf(account); IERC20Mintable(token).mint(account, amount); uint256 balanceAfter = IERC20(token).balanceOf(account); if (balanceBefore + amount != balanceAfter) { revert MintFailed(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; pragma abicoder v2; import "../interfaces/IInceptionBridge.sol"; import "../interfaces/IInceptionBridgeErrors.sol"; /// @author The InceptionLRT team /// @title The InceptionBridgeStorage contract /// @notice Stores variables for the InceptionBridge contract and facilitates their updates. abstract contract InceptionBridgeStorage is IInceptionBridgeStorage, IInceptionBridgeErrors { uint256 internal constant _PROOF_LENGTH = 0x100; uint256 internal _globalNonce; address public notary; mapping(bytes32 => bool) internal _usedProofs; mapping(uint256 => address) internal _bridgeAddressByChainId; /// @dev keccak256(fromToken,fromChain,_bridgeAddressByChainId(destinationChain), destinationChain) => destinationToken mapping(bytes32 => address) internal _destinationTokens; uint256 public shortCapDuration; /// @dev token => Cap per 'shortCapTime' mapping(address => uint256) public shortCaps; /// @dev token => (epochTime/shortCapDuration) => Current Deposits mapping(address => mapping(uint256 => uint256)) public shortCapsDeposit; /// @dev token => (epochTime/shortCapDuration) => Current Withdraws mapping(address => mapping(uint256 => uint256)) public shortCapsWithdraw; uint256 public longCapDuration; /// @dev token => cap per 'longCapTime' mapping(address => uint256) public longCaps; /// @dev token => (epochTime/longCapDuration) => Current Deposits mapping(address => mapping(uint256 => uint256)) public longCapsDeposit; /// @dev token => (epochTime/longCapDuration) => Current Withdraws mapping(address => mapping(uint256 => uint256)) public longCapsWithdraw; address internal _previousSender; uint256 internal _previousDepositBlockNum; /// token -> lockbox mapping(address => address) public xerc20TokenRegistry; /// @notice WARNING: Keep it up-to-date uint256[50 - 16] private __gap; function __initInceptionBridgeStorage(address notaryAddress) internal { _setNotary(notaryAddress); _setDefaultCrosschainThreshold(); } function _beforeDeposit() internal { if (_previousSender != address(0) && _previousDepositBlockNum != 0) { if ( _previousSender == tx.origin && _previousDepositBlockNum == block.number ) { revert MultipleDeposits(); } } _previousSender = tx.origin; _previousDepositBlockNum = block.number; } function _updateDepositCaps(address fromToken, uint256 amount) internal { /// Short(default: per hour) if ( shortCapsDeposit[fromToken][getCurrentStamp(shortCapDuration)] + amount > shortCaps[fromToken] ) { revert ShortCapExceeded( shortCaps[fromToken], shortCapsDeposit[fromToken][getCurrentStamp(shortCapDuration)] + amount ); } shortCapsDeposit[fromToken][ getCurrentStamp(shortCapDuration) ] += amount; /// Long(default: per day) if ( longCapsDeposit[fromToken][getCurrentStamp(longCapDuration)] + amount > longCaps[fromToken] ) { revert LongCapExceeded( longCaps[fromToken], longCapsDeposit[fromToken][getCurrentStamp(longCapDuration)] + amount ); } longCapsDeposit[fromToken][getCurrentStamp(longCapDuration)] += amount; } function _updateWithdrawCaps(address token, uint256 amount) internal { /// Short(default: per hour) if ( shortCapsWithdraw[token][getCurrentStamp(shortCapDuration)] + amount > shortCaps[token] ) { revert ShortCapExceeded( shortCaps[token], shortCapsWithdraw[token][getCurrentStamp(shortCapDuration)] + amount ); } shortCapsWithdraw[token][getCurrentStamp(shortCapDuration)] += amount; /// Long(default: per day) if ( longCapsWithdraw[token][getCurrentStamp(longCapDuration)] + amount > longCaps[token] ) { revert LongCapExceeded( longCaps[token], longCapsWithdraw[token][getCurrentStamp(longCapDuration)] + amount ); } longCapsWithdraw[token][getCurrentStamp(longCapDuration)] += amount; } function _setNotary(address notaryAddress) internal { if (notaryAddress == address(0x0)) revert NullAddress(); emit NotaryChanged(notary, notaryAddress); notary = notaryAddress; } /*////////////////////////// ////// SET functions ////// ////////////////////////*/ function _setShortCap(address token, uint256 newValue) internal { if (token == address(0x0)) revert NullAddress(); uint256 prevValue = shortCaps[token]; emit ShortCapChanged(token, prevValue, newValue); shortCaps[token] = newValue; } function _setShortCapDuration(uint256 newValue) internal { emit ShortCapDurationChanged(shortCapDuration, newValue); shortCapDuration = newValue; } function _setLongCapDuration(uint256 newValue) internal { emit LongCapDurationChanged(longCapDuration, newValue); longCapDuration = newValue; } function _setLongCap(address token, uint256 newValue) internal { if (token == address(0x0)) { revert NullAddress(); } emit LongCapChanged(token, longCaps[token], newValue); longCaps[token] = newValue; } function _setDefaultCrosschainThreshold() internal { shortCapDuration = 1 hours; longCapDuration = 1 days; } function _addBridge(address bridge, uint256 destinationChain) internal { if (bridge == address(0x0)) { revert NullAddress(); } if (destinationChain == 0) { revert InvalidChain(); } if (_bridgeAddressByChainId[destinationChain] != address(0x00)) { revert BridgeAlreadyAdded(); } _bridgeAddressByChainId[destinationChain] = bridge; emit BridgeAdded(bridge, destinationChain); } function _removeBridge(uint256 destinationChain) internal { if (_bridgeAddressByChainId[destinationChain] == address(0x00)) { revert BridgeNotExist(); } address bridge = _bridgeAddressByChainId[destinationChain]; delete _bridgeAddressByChainId[destinationChain]; emit BridgeRemoved(bridge, destinationChain); } function _addDestination( address fromToken, uint256 destinationChain, address toToken ) internal { if (_bridgeAddressByChainId[destinationChain] == address(0)) revert UnknownDestinationChain(); if (fromToken == address(0) || toToken == address(0)) revert NullAddress(); bytes32 direction = keccak256( abi.encodePacked( fromToken, block.chainid, _bridgeAddressByChainId[destinationChain], destinationChain ) ); if (_destinationTokens[direction] != address(0)) revert DestinationAlreadyExists(); _destinationTokens[direction] = toToken; emit DestinationAdded(fromToken, toToken, destinationChain); } function _removeDestination( address fromToken, uint256 destinationChain, address toToken ) internal { if (_bridgeAddressByChainId[destinationChain] == address(0)) revert UnknownDestinationChain(); bytes32 direction = keccak256( abi.encodePacked( fromToken, block.chainid, _bridgeAddressByChainId[destinationChain], destinationChain ) ); if (_destinationTokens[direction] != toToken) revert UnknownDestination(); delete _destinationTokens[direction]; emit DestinationRemoved(fromToken, toToken, destinationChain); } function _setXERC20Lockbox(address token, address lockbox) internal { if (address(token) == address(0) || address(lockbox) == address(0)) revert NullAddress(); if (xerc20TokenRegistry[token] != address(0)) revert XERC20LockboxAlreadyAdded(); emit XERC20LockboxAdded(token, lockbox); xerc20TokenRegistry[token] = lockbox; } function getCurrentStamp(uint256 duration) public view returns (uint256) { return (block.timestamp / duration) * duration; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "solmate/src/utils/CREATE3.sol"; import "../XERC20/XERC20.sol"; import "../XERC20/XERC20Lockbox.sol"; import "../interfaces/IFactory.sol"; /// @author The InceptionLRT team /// @title The BridgeFactory Contract /// @notice Facilitates the deployment of contracts via CREATE2 and CREATE3 contract BridgeFactory is IFactory { /** ***************************************************************************** ****************************** CREATE2 FACTORY ****************************** ***************************************************************************** */ bytes32 public bridgeSalt = "InceptionLRT Factory"; function deployCreate2( bytes calldata creationCode ) external returns (address) { return _deployCreate2(creationCode, msg.sender); } function _deployCreate2( bytes memory bytecode, address _sender ) internal returns (address) { address addr = _create2(bytecode, _sender); emit ContractCreated(addr); return addr; } function _create2( bytes memory bytecode, address _sender ) internal returns (address) { address payable addr; bytes32 salt = _getSalt(_sender); assembly { addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt) if iszero(extcodesize(addr)) { revert(0, 0) } } return addr; } function getDeploymentCreate2Address( bytes memory bytecode, address _sender ) external view returns (address) { bytes32 salt = _getSalt(_sender); bytes32 rawAddress = keccak256( abi.encodePacked( bytes1(0xff), address(this), salt, keccak256(bytecode) ) ); return address(bytes20(rawAddress << 96)); } function _getSalt(address _sender) internal view returns (bytes32) { return keccak256(abi.encodePacked(bridgeSalt, _sender)); } /** **************************************************************************** ****************************** XERC20 FACTORY ****************************** **************************************************************************** */ /** * @notice Deploys an XERC20 contract using CREATE3 * @dev _limits and _minters must be the same length * @param _name The name of the token * @param _symbol The symbol of the token * @return _xerc20 The address of the xerc20 */ function deployXERC20( string memory _name, string memory _symbol ) external returns (address _xerc20) { _xerc20 = _deployXERC20(_name, _symbol); emit XERC20Deployed(_xerc20); } /** * @notice Deploys an XERC20Lockbox contract using CREATE3 * * @dev When deploying a lockbox for the gas token of the chain, then, the base token needs to be address(0) * @param _xerc20 The address of the xerc20 that you want to deploy a lockbox for * @param _baseToken The address of the base token that you want to lock * @param _isNative Whether or not the base token is the native (gas) token of the chain. Eg: MATIC for polygon chain * @return _lockbox The address of the lockbox */ function deployLockbox( address _xerc20, address _baseToken, bool _isNative ) external returns (address _lockbox) { if ( (_baseToken == address(0) && !_isNative) || (_isNative && _baseToken != address(0)) ) revert IXERC20Factory_BadTokenAddress(); if (XERC20(_xerc20).owner() != msg.sender) revert IXERC20Factory_NotOwner(); _lockbox = _deployLockbox(_xerc20, _baseToken, _isNative); emit LockboxDeployed(_lockbox); } /** * @notice Deploys an XERC20 contract using CREATE3 * @dev _limits and _minters must be the same length * @param _name The name of the token * @param _symbol The symbol of the token * @return _xerc20 The address of the xerc20 */ function _deployXERC20( string memory _name, string memory _symbol ) internal returns (address _xerc20) { address deployer = msg.sender; bytes32 _salt = keccak256(abi.encodePacked(_name, _symbol, deployer)); bytes memory _creation = type(XERC20).creationCode; bytes memory _bytecode = abi.encodePacked( _creation, abi.encode(_name, _symbol, address(this)) ); _xerc20 = CREATE3.deploy(_salt, _bytecode, 0); XERC20(_xerc20).transferOwnership(deployer); } /** * @notice Deploys an XERC20Lockbox contract using CREATE3 * * @dev When deploying a lockbox for the gas token of the chain, then, the base token needs to be address(0) * @param _xerc20 The address of the xerc20 that you want to deploy a lockbox for * @param _baseToken The address of the base token that you want to lock * @param _isNative Whether or not the base token is the native (gas) token of the chain. Eg: MATIC for polygon chain * @return _lockbox The address of the lockbox */ function _deployLockbox( address _xerc20, address _baseToken, bool _isNative ) internal returns (address _lockbox) { address deployer = msg.sender; bytes32 _salt = keccak256( abi.encodePacked(_xerc20, _baseToken, deployer) ); bytes memory _bytecode = abi.encodePacked( type(XERC20Lockbox).creationCode, abi.encode(_xerc20, _baseToken, _isNative) ); _lockbox = CREATE3.deploy(_salt, _bytecode, 0); XERC20(_xerc20).setLockbox(_lockbox); } function deployCreate3( bytes calldata creationCode, bytes32 _salt ) external returns (address) { return _deployCreate3(creationCode, _salt); } function _deployCreate3( bytes memory bytecode, bytes32 _salt ) internal returns (address) { address addr = CREATE3.deploy(_salt, bytecode, 0); emit ContractCreated(addr); return addr; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IERC20Mintable { function mint(address account, uint256 amount) external; function burn(address account, uint256 amount) external; function chargeFrom( address sender, address recipient, uint256 amount ) external returns (bool); } interface IERC20Pegged { function getOrigin() external view returns (uint256, address); } interface IERC20Extra { function name() external returns (string memory); function decimals() external returns (uint8); function symbol() external returns (string memory); } interface IERC20MetadataChangeable { event NameChanged(string prevValue, string newValue); event SymbolChanged(string prevValue, string newValue); function changeName(bytes32) external; function changeSymbol(bytes32) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface ICREATE2Factory { event ContractCreated(address indexed addr); function deployCreate2( bytes calldata creationCode ) external returns (address); } interface ICREATE3Factory { /** * @notice Emitted when a new XERC20 is deployed * @param _xerc20 The address of the xerc20 */ event XERC20Deployed(address _xerc20); /** * @notice Emitted when a new XERC20Lockbox is deployed * @param _lockbox The address of the lockbox */ event LockboxDeployed(address _lockbox); /** * @notice Reverts when a non-owner attempts to call */ error IXERC20Factory_NotOwner(); /** * @notice Reverts when a lockbox is trying to be deployed from a malicious address */ error IXERC20Factory_BadTokenAddress(); /** * @notice Reverts when a lockbox is already deployed */ error IXERC20Factory_LockboxAlreadyDeployed(); /** * @notice Reverts when a the length of arrays sent is incorrect */ error IXERC20Factory_InvalidLength(); function deployXERC20( string memory _name, string memory _symbol ) external returns (address _xerc20); function deployLockbox( address _xerc20, address _baseToken, bool _isNative ) external returns (address _lockbox); } interface IFactory is ICREATE2Factory, ICREATE3Factory {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./IERC20.sol"; interface IInceptionBridgeStorage { struct Metadata { bytes32 name; bytes32 symbol; uint256 originChain; address originAddress; } event ShortCapChanged( address indexed token, uint256 prevValue, uint256 newValue ); event LongCapChanged( address indexed token, uint256 prevValue, uint256 newValue ); event ShortCapDurationChanged(uint256 prevValue, uint256 newValue); event LongCapDurationChanged(uint256 prevValue, uint256 newValue); event BridgeAdded(address indexed bridge, uint256 destinationChain); event BridgeRemoved(address indexed bridge, uint256 destinationChain); event DestinationAdded( address indexed fromToken, address indexed toToken, uint256 toChain ); event DestinationRemoved( address indexed fromToken, address indexed toToken, uint256 toChain ); event NotaryChanged(address indexed prevValue, address indexed newValue); event XERC20LockboxAdded(address indexed token, address indexed lockbox); } interface IInceptionBridge { event Deposited( uint256 destinationChain, address indexed destinationBridge, address indexed sender, address indexed receiver, address fromToken, address toToken, uint256 amount, uint256 nonce, IInceptionBridgeStorage.Metadata metadata ); event Withdrawn( bytes32 receiptHash, address indexed sender, address indexed receiver, address fromToken, address toToken, uint256 amount ); function deposit( address fromToken, uint256 destinationChain, address receiver, uint256 amount ) external; function withdraw( bytes calldata encodedProof, bytes calldata rawReceipt, bytes memory receiptRootSignature ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IInceptionBridgeErrors { /// @dev error ShortCapExceeded(uint256 limit, uint256 current); /// @dev error LongCapExceeded(uint256 limit, uint256 current); /// @dev error BridgeAlreadyAdded(); error BridgeNotExist(); error InvalidChain(); error MultipleDeposits(); /// @dev error ReceiptWrongChain(uint256 required, uint256 provided); /// @dev error InvalidContractAddress(); error NullAddress(); /// @dev error UnknownBridge(); /// @dev error WrongSignature(); error WithdrawalProofUsed(); error InvalidAssetType(); error InvalidFromTokenAddress(); error UnknownDestination(); error WrongDestinationBridge(); error XERC20LockboxAlreadyAdded(); error XERC20ZeroAddress(); /// @notice non-existing-bridge error UnknownDestinationChain(); error DestinationAlreadyExists(); error BurnFailed(); error MintFailed(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IERC20Errors { /** * @notice Reverts when a user with too low of a limit tries to call mint/burn */ error IXERC20_NotHighEnoughLimits(); /** * @notice Reverts when caller is not the factory */ error IXERC20_NotFactory(); /** * @notice Reverts when caller sets too small _limit */ error IXERC20_WrongBridgeLimit(); } interface IXERC20 is IERC20Errors { /** * @notice Contains the full minting and burning data for a particular bridge * * @param minterParams The minting parameters for the bridge * @param burnerParams The burning parameters for the bridge */ struct Bridge { BridgeParameters minterParams; BridgeParameters burnerParams; } /** * @notice Emits when a lockbox is set * * @param _lockbox The address of the lockbox */ event LockboxSet(address _lockbox); /** * @notice Emits when a limit is set * * @param _mintingLimit The updated minting limit we are setting to the bridge * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limit too */ event BridgeLimitsSet( uint256 _mintingLimit, uint256 _burningLimit, address indexed _bridge ); /** * @notice Contains the mint or burn parameters for a bridge * * @param timestamp The timestamp of the last mint/burn * @param ratePerSecond The rate per second of the bridge * @param maxLimit The max limit of the bridge * @param currentLimit The current limit of the bridge */ struct BridgeParameters { uint256 timestamp; uint256 ratePerSecond; uint256 maxLimit; uint256 currentLimit; } /** * @notice Sets the lockbox address * * @param _lockbox The address of the lockbox */ function setLockbox(address _lockbox) external; /** * @notice Updates the limits of any bridge * @dev Can only be called by the owner * @param _mintingLimit The updated minting limit we are setting to the bridge * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limits too */ function setBridgeLimits( address _bridge, uint256 _mintingLimit, uint256 _burningLimit ) external; /** * @notice Returns the max limit of a minter * * @param _minter The minter we are viewing the limits of * @return _limit The limit the minter has */ function mintingMaxLimitOf( address _minter ) external view returns (uint256 _limit); /** * @notice Returns the max limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningMaxLimitOf( address _bridge ) external view returns (uint256 _limit); /** * @notice Returns the current limit of a minter * * @param _minter The minter we are viewing the limits of * @return _limit The limit the minter has */ function mintingCurrentLimitOf( address _minter ) external view returns (uint256 _limit); /** * @notice Returns the current limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningCurrentLimitOf( address _bridge ) external view returns (uint256 _limit); /** * @notice Mints tokens for a user * @dev Can only be called by a minter * @param _user The address of the user who needs tokens minted * @param _amount The amount of tokens being minted */ function mint(address _user, uint256 _amount) external; /** * @notice Burns tokens for a user * @dev Can only be called by a minter * @param _user The address of the user who needs tokens burned * @param _amount The amount of tokens being burned */ function burn(address _user, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/interfaces/IERC20.sol"; import "./IXERC20.sol"; interface IXERC20LockboxErrors { /// @notice Reverts when a user tries to deposit native tokens on a non-native lockbox error IXERC20Lockbox_NotNative(); /// @notice Reverts when a user tries to deposit non-native tokens on a native lockbox error IXERC20Lockbox_Native(); /// @notice Reverts when a user tries to withdraw and the call fails error IXERC20Lockbox_WithdrawFailed(); /// @notice Reverts when a user tries to withdraw to the XERC20Lockbox itself error IXERC20Lockbox_WrongReceiver(); } interface IXERC20Lockbox is IXERC20LockboxErrors { /** * @notice Emitted when tokens are deposited into the lockbox * * @param _sender The address of the user who deposited * @param _amount The amount of tokens deposited */ event Deposit(address _sender, uint256 _amount); /** * @notice Emitted when tokens are withdrawn from the lockbox * * @param _sender The address of the user who withdrew * @param _amount The amount of tokens withdrawn */ event Withdraw(address _sender, uint256 _amount); function XERC20() external view returns (IXERC20 xerc20); function ERC20() external view returns (IERC20 erc20); /** * @notice Deposit ERC20 tokens into the lockbox * * @param _amount The amount of tokens to deposit */ function deposit(uint256 _amount) external; /** * @notice Deposit ERC20 tokens into the lockbox, and send the XERC20 to a user * * @param _user The user to send the XERC20 to * @param _amount The amount of tokens to deposit */ function depositTo(address _user, uint256 _amount) external; /** * @notice Deposit the native asset into the lockbox, and send the XERC20 to a user * * @param _user The user to send the XERC20 to */ function depositNativeTo(address _user) external payable; /** * @notice Withdraw ERC20 tokens from the lockbox * * @param _amount The amount of tokens to withdraw */ function withdraw(uint256 _amount) external; /** * @notice Withdraw ERC20 tokens from the lockbox * * @param _user The user to withdraw to * @param _amount The amount of tokens to withdraw */ function withdrawTo(address _user, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library CallDataRLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; function beginIteration( uint256 listOffset ) internal pure returns (uint256 iter) { return listOffset + _payloadOffset(listOffset); } function next(uint256 iter) internal pure returns (uint256 nextIter) { return iter + itemLength(iter); } function payloadLen( uint256 ptr, uint256 len ) internal pure returns (uint256) { return len - _payloadOffset(ptr); } function receiver(uint256 ptr) internal pure returns (address) { return address(uint160(toUint(ptr, 21))); } function toUint(uint256 ptr, uint256 len) internal pure returns (uint256) { require(len > 0 && len <= 33); uint256 offset = _payloadOffset(ptr); uint256 numLen = len - offset; uint256 result; assembly { result := calldataload(add(ptr, offset)) // cut off redundant bytes result := shr(mul(8, sub(32, numLen)), result) } return result; } function toUintStrict(uint256 ptr) internal pure returns (uint256) { // one byte prefix uint256 result; assembly { result := calldataload(add(ptr, 1)) } return result; } function rawDataPtr(uint256 ptr) internal pure returns (uint256) { return ptr + _payloadOffset(ptr); } /// @return entire rlp item byte length function itemLength(uint256 callDataPtr) internal pure returns (uint256) { uint256 itemLen; uint256 byte0; assembly { byte0 := byte(0, calldataload(callDataPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is callDataPtr := add(callDataPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := shr( mul(8, sub(32, byteLen)), calldataload(callDataPtr) ) itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) callDataPtr := add(callDataPtr, 1) let dataLen := shr( mul(8, sub(32, byteLen)), calldataload(callDataPtr) ) itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } /// @return number of bytes until the data function _payloadOffset( uint256 callDataPtr ) private pure returns (uint256) { uint256 byte0; assembly { byte0 := byte(0, calldataload(callDataPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if ( byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START) ) return 1; else if (byte0 < LIST_SHORT_START) return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./CallDataRLPReader.sol"; import "./Utils.sol"; import "../interfaces/IInceptionBridge.sol"; library EthereumVerifier { bytes32 constant TOPIC_DEPOSITED = keccak256( "Deposited(uint256,address,address,address,address,address,uint256,uint256,(bytes32,bytes32,uint256,address))" ); enum DepositType { None, TokenDeposit } struct State { bytes32 receiptHash; address contractAddress; address destinationContract; uint256 chainId; address sender; address receiver; address fromToken; address toToken; uint256 amount; uint256 nonce; // metadata fields (we can't use Metadata struct here because of Solidity struct memory layout) bytes32 symbol; bytes32 name; uint256 originChain; address originToken; } function getMetadata( State memory state ) internal pure returns (IInceptionBridgeStorage.Metadata memory) { IInceptionBridgeStorage.Metadata memory metadata; assembly { metadata := add(state, 0x120) } return metadata; } function parseTransactionReceipt( uint256 receiptOffset ) internal pure returns (State memory state, DepositType depositType) { uint256 iter = CallDataRLPReader.beginIteration(receiptOffset + 0x20); { /* postStateOrStatus - we must ensure that tx is not reverted */ uint256 statusOffset = iter; iter = CallDataRLPReader.next(iter); require( CallDataRLPReader.payloadLen( statusOffset, iter - statusOffset ) == 1, "EthereumVerifier: tx is reverted" ); } /* skip cumulativeGasUsed */ iter = CallDataRLPReader.next(iter); /* logs - we need to find our logs */ uint256 logs = iter; iter = CallDataRLPReader.next(iter); uint256 logsIter = CallDataRLPReader.beginIteration(logs); for (; logsIter < iter; ) { uint256 log = logsIter; logsIter = CallDataRLPReader.next(logsIter); /* make sure there is only one peg-in event in logs */ DepositType logType = _decodeReceiptLogs(state, log); if (logType != DepositType.None) { require( depositType == DepositType.None, "EthereumVerifier: multiple logs" ); depositType = logType; } } /* don't allow to process if peg-in type is unknown */ require( depositType != DepositType.None, "EthereumVerifier: missing logs" ); return (state, depositType); } function _decodeReceiptLogs( State memory state, uint256 log ) internal pure returns (DepositType depositType) { uint256 logIter = CallDataRLPReader.beginIteration(log); address contractAddress; { /* parse smart contract address */ uint256 addressOffset = logIter; logIter = CallDataRLPReader.next(logIter); contractAddress = CallDataRLPReader.receiver(addressOffset); } /* topics */ bytes32 mainTopic; address destinationContract; address sender; address receiver; { uint256 topicsIter = logIter; logIter = CallDataRLPReader.next(logIter); // Must be 4 topics RLP encoded: event signature, destinationContract, sender, receiver // Each topic RLP encoded is 33 bytes (0xa0[32 bytes data]) // Total payload: 132 bytes. Since it's list with total size bigger than 55 bytes we need 2 bytes prefix (0xf863) // So total size of RLP encoded topics array must be 134 if (CallDataRLPReader.itemLength(topicsIter) != 134) { return DepositType.None; } topicsIter = CallDataRLPReader.beginIteration(topicsIter); mainTopic = bytes32(CallDataRLPReader.toUintStrict(topicsIter)); topicsIter = CallDataRLPReader.next(topicsIter); destinationContract = address( bytes20(uint160(CallDataRLPReader.toUintStrict(topicsIter))) ); topicsIter = CallDataRLPReader.next(topicsIter); sender = address( bytes20(uint160(CallDataRLPReader.toUintStrict(topicsIter))) ); topicsIter = CallDataRLPReader.next(topicsIter); receiver = address( bytes20(uint160(CallDataRLPReader.toUintStrict(topicsIter))) ); topicsIter = CallDataRLPReader.next(topicsIter); require(topicsIter == logIter); // safety check that iteration is finished } uint256 ptr = CallDataRLPReader.rawDataPtr(logIter); logIter = CallDataRLPReader.next(logIter); uint256 len = logIter - ptr; { // parse logs based on topic type and check that event data has correct length uint256 expectedLen; if (mainTopic == TOPIC_DEPOSITED) { expectedLen = 0x120; depositType = DepositType.TokenDeposit; } else { return DepositType.None; } if (len != expectedLen) { return DepositType.None; } } { // read chain id separately and verify that contract that emitted event is relevant uint256 chainId; assembly { chainId := calldataload(ptr) } // if (chainId != Utils.currentChain()) return DepositType.None; // All checks are passed after this point, no errors allowed and we can modify state state.chainId = chainId; ptr += 0x20; len -= 0x20; } { uint256 structOffset; assembly { // skip 6 fields: receiptHash, destinationContract, contractAddress, chainId, sender, receiver structOffset := add(state, 0xc0) calldatacopy(structOffset, ptr, len) } } state.destinationContract = destinationContract; state.contractAddress = contractAddress; state.sender = sender; state.receiver = receiver; return depositType; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./CallDataRLPReader.sol"; import "./Utils.sol"; library ProofParser { // Proof is message format signed by the protocol. It contains somewhat redundant information, so only part // of the proof could be passed into the contract and other part can be inferred from transaction receipt struct Proof { uint256 chainId; uint256 status; bytes32 transactionHash; uint256 blockNumber; bytes32 blockHash; uint256 transactionIndex; bytes32 receiptHash; uint256 transferAmount; } function parseProof( uint256 proofOffset ) internal pure returns (Proof memory) { Proof memory proof; uint256 dataOffset = proofOffset + 0x20; assembly { calldatacopy(proof, dataOffset, 0x20) // 1 field (chainId) dataOffset := add(dataOffset, 0x40) calldatacopy(add(proof, 0x40), dataOffset, 0x80) // 4 fields * 0x20 = 0x80 dataOffset := add(dataOffset, 0xa0) calldatacopy(add(proof, 0xe0), dataOffset, 0x20) // transferAmount } return proof; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library Utils { function currentChain() internal view returns (uint256) { uint256 chain; assembly { chain := chainid() } return chain; } function stringToBytes32( string memory source ) internal pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } function saturatingMultiply( uint256 a, uint256 b ) internal pure returns (uint256) { unchecked { if (a == 0) return 0; uint256 c = a * b; if (c / a != b) return type(uint256).max; return c; } } function saturatingAdd( uint256 a, uint256 b ) internal pure returns (uint256) { unchecked { uint256 c = a + b; if (c < a) return type(uint256).max; return c; } } // Preconditions: // 1. a may be arbitrary (up to 2 ** 256 - 1) // 2. b * c < 2 ** 256 // Returned value: min(floor((a * b) / c), 2 ** 256 - 1) function multiplyAndDivideFloor( uint256 a, uint256 b, uint256 c ) internal pure returns (uint256) { return saturatingAdd( saturatingMultiply(a / c, b), ((a % c) * b) / c // can't fail because of assumption 2. ); } // Preconditions: // 1. a may be arbitrary (up to 2 ** 256 - 1) // 2. b * c < 2 ** 256 // Returned value: min(ceil((a * b) / c), 2 ** 256 - 1) function multiplyAndDivideCeil( uint256 a, uint256 b, uint256 c ) internal pure returns (uint256) { return saturatingAdd( saturatingMultiply(a / c, b), ((a % c) * b + (c - 1)) / c // can't fail because of assumption 2. ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/proxy/Proxy.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; /// @dev The original OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol), but /// constructor() was removed contract InitializableERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import "./InitializableERC1967Proxy.sol"; contract InceptionProxyAdmin is ProxyAdmin {} /// @dev The original OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol) /// with replacement constructor by initializer contract InitializableTransparentUpgradeableProxy is InitializableERC1967Proxy { /** * Contract initializer. * @param _logic address of the initial implementation. * @param admin_ Address of the proxy administrator. * @param _data Data to send as msg.data to the implementation to initialize the proxied contract */ function initialize( address _logic, address admin_, bytes memory _data ) external payable { require( _implementation() == address(0), "implementation has already been set" ); _upgradeToAndCall(_logic, _data, false); _changeAdmin(admin_); } /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. * * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the * implementation provides a function with the same selector. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior */ function _fallback() internal virtual override { if (msg.sender == _getAdmin()) { bytes memory ret; bytes4 selector = msg.sig; if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) { ret = _dispatchUpgradeTo(); } else if ( selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector ) { ret = _dispatchUpgradeToAndCall(); } else if ( selector == ITransparentUpgradeableProxy.changeAdmin.selector ) { ret = _dispatchChangeAdmin(); } else if ( selector == ITransparentUpgradeableProxy.admin.selector ) { ret = _dispatchAdmin(); } else if ( selector == ITransparentUpgradeableProxy.implementation.selector ) { ret = _dispatchImplementation(); } else { revert( "TransparentUpgradeableProxy: admin cannot fallback to proxy target" ); } assembly { return(add(ret, 0x20), mload(ret)) } } else { super._fallback(); } } /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function _dispatchAdmin() private returns (bytes memory) { _requireZeroValue(); address admin = _getAdmin(); return abi.encode(admin); } /** * @dev Returns the current implementation. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _dispatchImplementation() private returns (bytes memory) { _requireZeroValue(); address implementation = _implementation(); return abi.encode(implementation); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _dispatchChangeAdmin() private returns (bytes memory) { _requireZeroValue(); address newAdmin = abi.decode(msg.data[4:], (address)); _changeAdmin(newAdmin); return ""; } /** * @dev Upgrade the implementation of the proxy. */ function _dispatchUpgradeTo() private returns (bytes memory) { _requireZeroValue(); address newImplementation = abi.decode(msg.data[4:], (address)); _upgradeToAndCall(newImplementation, bytes(""), false); return ""; } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. */ function _dispatchUpgradeToAndCall() private returns (bytes memory) { (address newImplementation, bytes memory data) = abi.decode( msg.data[4:], (address, bytes) ); _upgradeToAndCall(newImplementation, data, true); return ""; } /** * @dev Returns the current admin. * * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to * emulate some proxy functions being non-payable while still allowing value to pass through. */ function _requireZeroValue() private { require(msg.value == 0, "zero value is required"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; contract ERC20Mintable is ERC20 { constructor( string memory name_, string memory symbol_ ) payable ERC20(name_, symbol_) {} function mint(address usr, uint wad) external { _mint(usr, wad); } function burn(address usr, uint wad) external { _burn(usr, wad); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/interfaces/IERC20.sol"; import "../interfaces/IInceptionBridge.sol"; contract MultipleDepositor { IInceptionBridge internal _bridge; constructor(IInceptionBridge bridge) { _bridge = bridge; } function deposit( address fromToken, uint256 destinationChain, address receiver, uint256 amount, uint256 numOfDeposits ) external { IERC20(fromToken).transferFrom( msg.sender, address(this), numOfDeposits * amount ); IERC20(fromToken).approve(address(_bridge), numOfDeposits * amount); for (uint256 i = 0; i < numOfDeposits; i++) { _bridge.deposit(fromToken, destinationChain, receiver, amount); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "../interfaces/IXERC20Lockbox.sol"; import "../interfaces/IXERC20.sol"; contract XERC20Lockbox is IXERC20Lockbox { using SafeERC20 for IERC20; using SafeCast for uint256; /** * @notice The XERC20 token of this contract */ IXERC20 public immutable XERC20; /** * @notice The ERC20 token of this contract */ IERC20 public immutable ERC20; /** * @notice Whether the ERC20 token is the native gas token of this chain */ bool public immutable IS_NATIVE; /** * @param _xerc20 The address of the XERC20 contract * @param _erc20 The address of the ERC20 contract * @param _isNative Whether the ERC20 token is the native gas token of this chain or not */ constructor(address _xerc20, address _erc20, bool _isNative) payable { XERC20 = IXERC20(_xerc20); ERC20 = IERC20(_erc20); IS_NATIVE = _isNative; } /** * @notice Deposit native tokens into the lockbox */ function depositNative() public payable { if (!IS_NATIVE) revert IXERC20Lockbox_NotNative(); _deposit(msg.sender, msg.value); } /** * @notice Deposit ERC20 tokens into the lockbox * @param _amount The amount of tokens to deposit */ function deposit(uint256 _amount) external { if (IS_NATIVE) revert IXERC20Lockbox_Native(); _deposit(msg.sender, _amount); } /** * @notice Deposit ERC20 tokens into the lockbox, and send the XERC20 to a user * @param _to The user to send the XERC20 to * @param _amount The amount of tokens to deposit */ function depositTo(address _to, uint256 _amount) external { if (IS_NATIVE) revert IXERC20Lockbox_Native(); _deposit(_to, _amount); } /** * @notice Deposit the native asset into the lockbox, and send the XERC20 to a user * @param _to The user to send the XERC20 to */ function depositNativeTo(address _to) external payable { if (!IS_NATIVE) revert IXERC20Lockbox_NotNative(); _deposit(_to, msg.value); } /** * @notice Withdraw ERC20 tokens from the lockbox * @param _amount The amount of tokens to withdraw */ function withdraw(uint256 _amount) external { _withdraw(msg.sender, _amount); } /** * @notice Withdraw tokens from the lockbox * @param _to The user to withdraw to * @param _amount The amount of tokens to withdraw */ function withdrawTo(address _to, uint256 _amount) external { _withdraw(_to, _amount); } /** * @notice Withdraw tokens from the lockbox * @param _to The user to withdraw to * @param _amount The amount of tokens to withdraw */ function _withdraw(address _to, uint256 _amount) internal { if (_to == address(this)) revert IXERC20Lockbox_WrongReceiver(); XERC20.burn(msg.sender, _amount); if (IS_NATIVE) { (bool _success, ) = payable(_to).call{value: _amount}(""); if (!_success) revert IXERC20Lockbox_WithdrawFailed(); } else { ERC20.safeTransfer(_to, _amount); } emit Withdraw(_to, _amount); } /** * @notice Deposit tokens into the lockbox * @param _to The address to send the XERC20 to * @param _amount The amount of tokens to deposit */ function _deposit(address _to, uint256 _amount) internal { if (_to == address(this)) revert IXERC20Lockbox_WrongReceiver(); if (!IS_NATIVE) ERC20.safeTransferFrom(msg.sender, address(this), _amount); XERC20.mint(_to, _amount); emit Deposit(_to, _amount); } /** * @notice Fallback function to deposit native tokens */ receive() external payable { depositNative(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Library for converting between addresses and bytes32 values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol) library Bytes32AddressLib { function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { return address(uint160(uint256(bytesValue))); } function fillLast12Bytes(address addressValue) internal pure returns (bytes32) { return bytes32(bytes20(addressValue)); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {Bytes32AddressLib} from "./Bytes32AddressLib.sol"; /// @notice Deploy to deterministic addresses without an initcode factor. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol) /// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol) library CREATE3 { using Bytes32AddressLib for bytes32; //--------------------------------------------------------------------------------// // Opcode | Opcode + Arguments | Description | Stack View // //--------------------------------------------------------------------------------// // 0x36 | 0x36 | CALLDATASIZE | size // // 0x3d | 0x3d | RETURNDATASIZE | 0 size // // 0x3d | 0x3d | RETURNDATASIZE | 0 0 size // // 0x37 | 0x37 | CALLDATACOPY | // // 0x36 | 0x36 | CALLDATASIZE | size // // 0x3d | 0x3d | RETURNDATASIZE | 0 size // // 0x34 | 0x34 | CALLVALUE | value 0 size // // 0xf0 | 0xf0 | CREATE | newContract // //--------------------------------------------------------------------------------// // Opcode | Opcode + Arguments | Description | Stack View // //--------------------------------------------------------------------------------// // 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode // // 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode // // 0x52 | 0x52 | MSTORE | // // 0x60 | 0x6008 | PUSH1 08 | 8 // // 0x60 | 0x6018 | PUSH1 18 | 24 8 // // 0xf3 | 0xf3 | RETURN | // //--------------------------------------------------------------------------------// bytes internal constant PROXY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3"; bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE); function deploy( bytes32 salt, bytes memory creationCode, uint256 value ) internal returns (address deployed) { bytes memory proxyChildBytecode = PROXY_BYTECODE; address proxy; /// @solidity memory-safe-assembly assembly { // Deploy a new contract with our pre-made bytecode via CREATE2. // We start 32 bytes into the code to avoid copying the byte length. proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), salt) } require(proxy != address(0), "DEPLOYMENT_FAILED"); deployed = getDeployed(salt); (bool success, ) = proxy.call{value: value}(creationCode); require(success && deployed.code.length != 0, "INITIALIZATION_FAILED"); } function getDeployed(bytes32 salt) internal view returns (address) { address proxy = keccak256( abi.encodePacked( // Prefix: bytes1(0xFF), // Creator: address(this), // Salt: salt, // Bytecode hash: PROXY_BYTECODE_HASH ) ).fromLast20Bytes(); return keccak256( abi.encodePacked( // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01) // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) hex"d6_94", proxy, hex"01" // Nonce of the proxy contract (1) ) ).fromLast20Bytes(); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"IXERC20_NotFactory","type":"error"},{"inputs":[],"name":"IXERC20_NotHighEnoughLimits","type":"error"},{"inputs":[],"name":"IXERC20_WrongBridgeLimit","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","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":"uint256","name":"_mintingLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_burningLimit","type":"uint256"},{"indexed":true,"internalType":"address","name":"_bridge","type":"address"}],"name":"BridgeLimitsSet","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_lockbox","type":"address"}],"name":"LockboxSet","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"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTORY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"amount","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":"address","name":"","type":"address"}],"name":"bridges","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"currentLimit","type":"uint256"}],"internalType":"struct IXERC20.BridgeParameters","name":"minterParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"currentLimit","type":"uint256"}],"internalType":"struct IXERC20.BridgeParameters","name":"burnerParams","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"burningCurrentLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"burningMaxLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"mintingCurrentLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"mintingMaxLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"},{"internalType":"uint256","name":"_mintingLimit","type":"uint256"},{"internalType":"uint256","name":"_burningLimit","type":"uint256"}],"name":"setBridgeLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lockbox","type":"address"}],"name":"setLockbox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"amount","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":"amount","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"}]
Contract Creation Code
6101806040523480156200001257600080fd5b50604051620022d0380380620022d083398101604081905262000035916200030c565b6040805180820190915260018152603160f81b6020820152839081908185600362000061838262000428565b50600462000070828262000428565b5050506200008d620000876200016460201b60201c565b62000168565b6200009a826006620001ba565b61012052620000ab816007620001ba565b61014052815160208084019190912060e052815190820120610100524660a0526200013960e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506200014e8162000168565b6001600160a01b031661016052506200054e9050565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602083511015620001da57620001d283620001f3565b9050620001ed565b81620001e7848262000428565b5060ff90505b92915050565b600080829050601f815111156200022a578260405163305a27a960e01b8152600401620002219190620004f4565b60405180910390fd5b8051620002378262000529565b179392505050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200027257818101518382015260200162000258565b50506000910152565b600082601f8301126200028d57600080fd5b81516001600160401b0380821115620002aa57620002aa6200023f565b604051601f8301601f19908116603f01168101908282118183101715620002d557620002d56200023f565b81604052838152866020858801011115620002ef57600080fd5b6200030284602083016020890162000255565b9695505050505050565b6000806000606084860312156200032257600080fd5b83516001600160401b03808211156200033a57600080fd5b62000348878388016200027b565b945060208601519150808211156200035f57600080fd5b506200036e868287016200027b565b604086015190935090506001600160a01b03811681146200038e57600080fd5b809150509250925092565b600181811c90821680620003ae57607f821691505b602082108103620003cf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200042357600081815260208120601f850160051c81016020861015620003fe5750805b601f850160051c820191505b818110156200041f578281556001016200040a565b5050505b505050565b81516001600160401b038111156200044457620004446200023f565b6200045c8162000455845462000399565b84620003d5565b602080601f8311600181146200049457600084156200047b5750858301515b600019600386901b1c1916600185901b1785556200041f565b600085815260208120601f198616915b82811015620004c557888601518255948401946001909101908401620004a4565b5085821015620004e45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082518060208401526200051581604085016020870162000255565b601f01601f19169190910160400192915050565b80516020808301519190811015620003cf5760001960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051611d15620005bb6000396000818161026f015261060c015260006107a20152600061077701526000610f0001526000610ed801526000610e3301526000610e5d01526000610e870152611d156000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a08231116101045780639dc29fac116100a2578063ced67f0c11610071578063ced67f0c14610424578063d505accf146104b6578063dd62ed3e146104c9578063f2fde38b146104dc57600080fd5b80639dc29fac146103bf578063a457c2d7146103d2578063a9059cbb146103e5578063c1eb7137146103f857600080fd5b806384b0196e116100de57806384b0196e146103785780638da5cb5b1461039357806395d89b41146103a4578063998955d3146103ac57600080fd5b806370a0823114610334578063715018a61461035d5780637ecebe001461036557600080fd5b80633644e51511610171578063435350b71161014b578063435350b7146102e857806363a0daac146102fb578063651fd2681461030e57806366cc57021461032157600080fd5b80633644e515146102b857806339509351146102c057806340c10f19146102d357600080fd5b806318160ddd116101ad57806318160ddd1461024f57806323b872dd146102575780632dd310001461026a578063313ce567146102a957600080fd5b806306fdde03146101d4578063095ea7b3146101f25780630c05f82c14610215575b600080fd5b6101dc6104ef565b6040516101e991906119b5565b60405180910390f35b6102056102003660046119e4565b610581565b60405190151581526020016101e9565b610241610223366004611a0e565b6001600160a01b03166000908152600b602052604090206002015490565b6040519081526020016101e9565b600254610241565b610205610265366004611a29565b61059b565b6102917f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101e9565b604051601281526020016101e9565b6102416105c1565b6102056102ce3660046119e4565b6105d0565b6102e66102e13660046119e4565b6105f2565b005b6102e66102f6366004611a0e565b610601565b6102e6610309366004611a65565b61069e565b61024161031c366004611a0e565b610703565b600a54610291906001600160a01b031681565b610241610342366004611a0e565b6001600160a01b031660009081526020819052604090205490565b6102e6610737565b610241610373366004611a0e565b61074b565b610380610769565b6040516101e99796959493929190611a98565b6005546001600160a01b0316610291565b6101dc6107f2565b6102416103ba366004611a0e565b610801565b6102e66103cd3660046119e4565b610838565b6102056103e03660046119e4565b610843565b6102056103f33660046119e4565b6108ce565b610241610406366004611a0e565b6001600160a01b03166000908152600b602052604090206006015490565b6104a8610432366004611a0e565b600b602090815260009182526040918290208251608080820185528254825260018301548285015260028301548286015260038301546060808401919091528551918201865260048401548252600584015494820194909452600683015494810194909452600790910154918301919091529082565b6040516101e9929190611b2e565b6102e66104c4366004611b7a565b6108dc565b6102416104d7366004611bed565b610a40565b6102e66104ea366004611a0e565b610a6b565b6060600380546104fe90611c20565b80601f016020809104026020016040519081016040528092919081815260200182805461052a90611c20565b80156105775780601f1061054c57610100808354040283529160200191610577565b820191906000526020600020905b81548152906001019060200180831161055a57829003601f168201915b5050505050905090565b60003361058f818585610ae4565b60019150505b92915050565b6000336105a9858285610c08565b6105b4858585610c82565b60019150505b9392505050565b60006105cb610e26565b905090565b60003361058f8185856105e38383610a40565b6105ed9190611c6a565b610ae4565b6105fd338383610f51565b5050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461064a57604051632029e52560e01b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040519081527ffa2e15ea41196e438f0593ecdd6036acd83bdfcd39d627b77c17eab43f376a399060200160405180910390a150565b6106a6610faf565b6106b08383611009565b6106ba83826110dd565b60408051838152602081018390526001600160a01b038516917f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c944910160405180910390a2505050565b6001600160a01b0381166000908152600b6020526040812060038101546002820154825460019093015461059593906111b7565b61073f610faf565b610749600061122f565b565b6001600160a01b038116600090815260086020526040812054610595565b60006060808280808361079d7f00000000000000000000000000000000000000000000000000000000000000006006611281565b6107c87f00000000000000000000000000000000000000000000000000000000000000006007611281565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6060600480546104fe90611c20565b6001600160a01b0381166000908152600b6020526040812060078101546006820154600483015460059093015461059593906111b7565b6105fd33838361132c565b600033816108518286610a40565b9050838110156108b65760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6108c38286868403610ae4565b506001949350505050565b60003361058f818585610c82565b8342111561092c5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016108ad565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861095b8c611385565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006109b6826113ad565b905060006109c6828787876113da565b9050896001600160a01b0316816001600160a01b031614610a295760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016108ad565b610a348a8a8a610ae4565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b610a73610faf565b6001600160a01b038116610ad85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108ad565b610ae18161122f565b50565b6001600160a01b038316610b465760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016108ad565b6001600160a01b038216610ba75760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016108ad565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610c148484610a40565b90506000198114610c7c5781811015610c6f5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016108ad565b610c7c8484848403610ae4565b50505050565b6001600160a01b038316610ce65760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016108ad565b6001600160a01b038216610d485760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016108ad565b6001600160a01b03831660009081526020819052604090205481811015610dc05760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016108ad565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610c7c565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015610e7f57507f000000000000000000000000000000000000000000000000000000000000000046145b15610ea957507f000000000000000000000000000000000000000000000000000000000000000090565b6105cb604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600a546001600160a01b03848116911614610fa0576000610f7184610703565b905081811015610f94576040516305b4215560e11b815260040160405180910390fd5b610f9e8483611402565b505b610faa8282611458565b505050565b6005546001600160a01b031633146107495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108ad565b620151808110801561101b5750600081115b156110395760405163827ca4c160e01b815260040160405180910390fd5b6001600160a01b0382166000908152600b60205260408120600201549061105f84610703565b6001600160a01b0385166000908152600b60205260409020600201849055905061108a838383611517565b6001600160a01b0385166000908152600b60205260409020600301556110b36201518084611c7d565b6001600160a01b039094166000908152600b60205260409020600181019490945550504290915550565b62015180811080156110ef5750600081115b1561110d5760405163827ca4c160e01b815260040160405180910390fd5b6001600160a01b0382166000908152600b60205260408120600601549061113384610801565b6001600160a01b0385166000908152600b60205260409020600601849055905061115e838383611517565b6001600160a01b0385166000908152600b60205260409020600701556111876201518084611c7d565b6001600160a01b039094166000908152600b60205260409020600581019490945550504260049092019190915550565b8383811461122757426111cd6201518085611c6a565b116111d9575082611227565b426111e76201518085611c6a565b11156112275760006111f98442611c9f565b905060006112078483611cb2565b6112119084611c6a565b90508581116112205780611222565b855b925050505b949350505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606060ff831461129b576112948361156e565b9050610595565b8180546112a790611c20565b80601f01602080910402602001604051908101604052809291908181526020018280546112d390611c20565b80156113205780601f106112f557610100808354040283529160200191611320565b820191906000526020600020905b81548152906001019060200180831161130357829003601f168201915b50505050509050610595565b600a546001600160a01b0384811691161461137b57600061134c84610801565b90508181101561136f576040516305b4215560e11b815260040160405180910390fd5b61137984836115ad565b505b610faa8282611607565b6001600160a01b03811660009081526008602052604090208054600181018255905b50919050565b60006105956113ba610e26565b8360405161190160f01b8152600281019290925260228201526042902090565b60008060006113eb87878787611739565b915091506113f8816117fd565b5095945050505050565b600061140d83610703565b6001600160a01b0384166000908152600b6020526040902042905590506114348282611c9f565b6001600160a01b039093166000908152600b60205260409020600301929092555050565b6001600160a01b0382166114ae5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016108ad565b80600260008282546114c09190611c6a565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000808484111561154d5761152c8585611c9f565b905080831161153c576000611546565b6115468184611c9f565b9150611566565b6115578486611c9f565b90506115638184611c6a565b91505b509392505050565b6060600061157b83611947565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b60006115b883610801565b6001600160a01b0384166000908152600b602052604090204260049091015590506115e38282611c9f565b6001600160a01b039093166000908152600b60205260409020600701929092555050565b6001600160a01b0382166116675760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016108ad565b6001600160a01b038216600090815260208190526040902054818110156116db5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016108ad565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561177057506000905060036117f4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156117c4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166117ed576000600192509250506117f4565b9150600090505b94509492505050565b600081600481111561181157611811611cc9565b036118195750565b600181600481111561182d5761182d611cc9565b0361187a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108ad565b600281600481111561188e5761188e611cc9565b036118db5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108ad565b60038160048111156118ef576118ef611cc9565b03610ae15760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016108ad565b600060ff8216601f81111561059557604051632cd44ac360e21b815260040160405180910390fd5b6000815180845260005b8181101561199557602081850181015186830182015201611979565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006105ba602083018461196f565b80356001600160a01b03811681146119df57600080fd5b919050565b600080604083850312156119f757600080fd5b611a00836119c8565b946020939093013593505050565b600060208284031215611a2057600080fd5b6105ba826119c8565b600080600060608486031215611a3e57600080fd5b611a47846119c8565b9250611a55602085016119c8565b9150604084013590509250925092565b600080600060608486031215611a7a57600080fd5b611a83846119c8565b95602085013595506040909401359392505050565b60ff60f81b881681526000602060e081840152611ab860e084018a61196f565b8381036040850152611aca818a61196f565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015611b1c57835183529284019291840191600101611b00565b50909c9b505050505050505050505050565b82518152602080840151818301526040808501518184015260608086015181850152845160808501529184015160a084015283015160c083015282015160e082015261010081016105ba565b600080600080600080600060e0888a031215611b9557600080fd5b611b9e886119c8565b9650611bac602089016119c8565b95506040880135945060608801359350608088013560ff81168114611bd057600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611c0057600080fd5b611c09836119c8565b9150611c17602084016119c8565b90509250929050565b600181811c90821680611c3457607f821691505b6020821081036113a757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561059557610595611c54565b600082611c9a57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561059557610595611c54565b808202811582820484141761059557610595611c54565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220d92acc530753a19696d3bd33c34277734b40da73f34ff04b709f57d8cc6d4a4964736f6c63430008140033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000db04b09a1330d79dd94c440ef13ceeea644355820000000000000000000000000000000000000000000000000000000000000019496e63657074696f6e4c52542072657374616b656420455448000000000000000000000000000000000000000000000000000000000000000000000000000005696e455448000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c806370a08231116101045780639dc29fac116100a2578063ced67f0c11610071578063ced67f0c14610424578063d505accf146104b6578063dd62ed3e146104c9578063f2fde38b146104dc57600080fd5b80639dc29fac146103bf578063a457c2d7146103d2578063a9059cbb146103e5578063c1eb7137146103f857600080fd5b806384b0196e116100de57806384b0196e146103785780638da5cb5b1461039357806395d89b41146103a4578063998955d3146103ac57600080fd5b806370a0823114610334578063715018a61461035d5780637ecebe001461036557600080fd5b80633644e51511610171578063435350b71161014b578063435350b7146102e857806363a0daac146102fb578063651fd2681461030e57806366cc57021461032157600080fd5b80633644e515146102b857806339509351146102c057806340c10f19146102d357600080fd5b806318160ddd116101ad57806318160ddd1461024f57806323b872dd146102575780632dd310001461026a578063313ce567146102a957600080fd5b806306fdde03146101d4578063095ea7b3146101f25780630c05f82c14610215575b600080fd5b6101dc6104ef565b6040516101e991906119b5565b60405180910390f35b6102056102003660046119e4565b610581565b60405190151581526020016101e9565b610241610223366004611a0e565b6001600160a01b03166000908152600b602052604090206002015490565b6040519081526020016101e9565b600254610241565b610205610265366004611a29565b61059b565b6102917f000000000000000000000000db04b09a1330d79dd94c440ef13ceeea6443558281565b6040516001600160a01b0390911681526020016101e9565b604051601281526020016101e9565b6102416105c1565b6102056102ce3660046119e4565b6105d0565b6102e66102e13660046119e4565b6105f2565b005b6102e66102f6366004611a0e565b610601565b6102e6610309366004611a65565b61069e565b61024161031c366004611a0e565b610703565b600a54610291906001600160a01b031681565b610241610342366004611a0e565b6001600160a01b031660009081526020819052604090205490565b6102e6610737565b610241610373366004611a0e565b61074b565b610380610769565b6040516101e99796959493929190611a98565b6005546001600160a01b0316610291565b6101dc6107f2565b6102416103ba366004611a0e565b610801565b6102e66103cd3660046119e4565b610838565b6102056103e03660046119e4565b610843565b6102056103f33660046119e4565b6108ce565b610241610406366004611a0e565b6001600160a01b03166000908152600b602052604090206006015490565b6104a8610432366004611a0e565b600b602090815260009182526040918290208251608080820185528254825260018301548285015260028301548286015260038301546060808401919091528551918201865260048401548252600584015494820194909452600683015494810194909452600790910154918301919091529082565b6040516101e9929190611b2e565b6102e66104c4366004611b7a565b6108dc565b6102416104d7366004611bed565b610a40565b6102e66104ea366004611a0e565b610a6b565b6060600380546104fe90611c20565b80601f016020809104026020016040519081016040528092919081815260200182805461052a90611c20565b80156105775780601f1061054c57610100808354040283529160200191610577565b820191906000526020600020905b81548152906001019060200180831161055a57829003601f168201915b5050505050905090565b60003361058f818585610ae4565b60019150505b92915050565b6000336105a9858285610c08565b6105b4858585610c82565b60019150505b9392505050565b60006105cb610e26565b905090565b60003361058f8185856105e38383610a40565b6105ed9190611c6a565b610ae4565b6105fd338383610f51565b5050565b336001600160a01b037f000000000000000000000000db04b09a1330d79dd94c440ef13ceeea64435582161461064a57604051632029e52560e01b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0383169081179091556040519081527ffa2e15ea41196e438f0593ecdd6036acd83bdfcd39d627b77c17eab43f376a399060200160405180910390a150565b6106a6610faf565b6106b08383611009565b6106ba83826110dd565b60408051838152602081018390526001600160a01b038516917f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c944910160405180910390a2505050565b6001600160a01b0381166000908152600b6020526040812060038101546002820154825460019093015461059593906111b7565b61073f610faf565b610749600061122f565b565b6001600160a01b038116600090815260086020526040812054610595565b60006060808280808361079d7f496e63657074696f6e4c52542072657374616b656420455448000000000000196006611281565b6107c87f31000000000000000000000000000000000000000000000000000000000000016007611281565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6060600480546104fe90611c20565b6001600160a01b0381166000908152600b6020526040812060078101546006820154600483015460059093015461059593906111b7565b6105fd33838361132c565b600033816108518286610a40565b9050838110156108b65760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6108c38286868403610ae4565b506001949350505050565b60003361058f818585610c82565b8342111561092c5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e6500000060448201526064016108ad565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861095b8c611385565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006109b6826113ad565b905060006109c6828787876113da565b9050896001600160a01b0316816001600160a01b031614610a295760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e6174757265000060448201526064016108ad565b610a348a8a8a610ae4565b50505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b610a73610faf565b6001600160a01b038116610ad85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108ad565b610ae18161122f565b50565b6001600160a01b038316610b465760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016108ad565b6001600160a01b038216610ba75760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016108ad565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610c148484610a40565b90506000198114610c7c5781811015610c6f5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016108ad565b610c7c8484848403610ae4565b50505050565b6001600160a01b038316610ce65760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016108ad565b6001600160a01b038216610d485760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016108ad565b6001600160a01b03831660009081526020819052604090205481811015610dc05760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016108ad565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610c7c565b6000306001600160a01b037f0000000000000000000000005a7a183b6b44dc4ec2e3d2ef43f98c5152b1d76d16148015610e7f57507f000000000000000000000000000000000000000000000000000000000000e70846145b15610ea957507f53160e1c5443b768f5d589c675f18260ae48dd80f852553617cee42347b797f190565b6105cb604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fd3ab79e64c2c41d90ebb486f3d8a57a39a9cceb0d75afe23c25d845d2a6ce1c3918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600a546001600160a01b03848116911614610fa0576000610f7184610703565b905081811015610f94576040516305b4215560e11b815260040160405180910390fd5b610f9e8483611402565b505b610faa8282611458565b505050565b6005546001600160a01b031633146107495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108ad565b620151808110801561101b5750600081115b156110395760405163827ca4c160e01b815260040160405180910390fd5b6001600160a01b0382166000908152600b60205260408120600201549061105f84610703565b6001600160a01b0385166000908152600b60205260409020600201849055905061108a838383611517565b6001600160a01b0385166000908152600b60205260409020600301556110b36201518084611c7d565b6001600160a01b039094166000908152600b60205260409020600181019490945550504290915550565b62015180811080156110ef5750600081115b1561110d5760405163827ca4c160e01b815260040160405180910390fd5b6001600160a01b0382166000908152600b60205260408120600601549061113384610801565b6001600160a01b0385166000908152600b60205260409020600601849055905061115e838383611517565b6001600160a01b0385166000908152600b60205260409020600701556111876201518084611c7d565b6001600160a01b039094166000908152600b60205260409020600581019490945550504260049092019190915550565b8383811461122757426111cd6201518085611c6a565b116111d9575082611227565b426111e76201518085611c6a565b11156112275760006111f98442611c9f565b905060006112078483611cb2565b6112119084611c6a565b90508581116112205780611222565b855b925050505b949350505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606060ff831461129b576112948361156e565b9050610595565b8180546112a790611c20565b80601f01602080910402602001604051908101604052809291908181526020018280546112d390611c20565b80156113205780601f106112f557610100808354040283529160200191611320565b820191906000526020600020905b81548152906001019060200180831161130357829003601f168201915b50505050509050610595565b600a546001600160a01b0384811691161461137b57600061134c84610801565b90508181101561136f576040516305b4215560e11b815260040160405180910390fd5b61137984836115ad565b505b610faa8282611607565b6001600160a01b03811660009081526008602052604090208054600181018255905b50919050565b60006105956113ba610e26565b8360405161190160f01b8152600281019290925260228201526042902090565b60008060006113eb87878787611739565b915091506113f8816117fd565b5095945050505050565b600061140d83610703565b6001600160a01b0384166000908152600b6020526040902042905590506114348282611c9f565b6001600160a01b039093166000908152600b60205260409020600301929092555050565b6001600160a01b0382166114ae5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016108ad565b80600260008282546114c09190611c6a565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6000808484111561154d5761152c8585611c9f565b905080831161153c576000611546565b6115468184611c9f565b9150611566565b6115578486611c9f565b90506115638184611c6a565b91505b509392505050565b6060600061157b83611947565b604080516020808252818301909252919250600091906020820181803683375050509182525060208101929092525090565b60006115b883610801565b6001600160a01b0384166000908152600b602052604090204260049091015590506115e38282611c9f565b6001600160a01b039093166000908152600b60205260409020600701929092555050565b6001600160a01b0382166116675760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016108ad565b6001600160a01b038216600090815260208190526040902054818110156116db5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016108ad565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561177057506000905060036117f4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156117c4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166117ed576000600192509250506117f4565b9150600090505b94509492505050565b600081600481111561181157611811611cc9565b036118195750565b600181600481111561182d5761182d611cc9565b0361187a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108ad565b600281600481111561188e5761188e611cc9565b036118db5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108ad565b60038160048111156118ef576118ef611cc9565b03610ae15760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016108ad565b600060ff8216601f81111561059557604051632cd44ac360e21b815260040160405180910390fd5b6000815180845260005b8181101561199557602081850181015186830182015201611979565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006105ba602083018461196f565b80356001600160a01b03811681146119df57600080fd5b919050565b600080604083850312156119f757600080fd5b611a00836119c8565b946020939093013593505050565b600060208284031215611a2057600080fd5b6105ba826119c8565b600080600060608486031215611a3e57600080fd5b611a47846119c8565b9250611a55602085016119c8565b9150604084013590509250925092565b600080600060608486031215611a7a57600080fd5b611a83846119c8565b95602085013595506040909401359392505050565b60ff60f81b881681526000602060e081840152611ab860e084018a61196f565b8381036040850152611aca818a61196f565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015611b1c57835183529284019291840191600101611b00565b50909c9b505050505050505050505050565b82518152602080840151818301526040808501518184015260608086015181850152845160808501529184015160a084015283015160c083015282015160e082015261010081016105ba565b600080600080600080600060e0888a031215611b9557600080fd5b611b9e886119c8565b9650611bac602089016119c8565b95506040880135945060608801359350608088013560ff81168114611bd057600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611c0057600080fd5b611c09836119c8565b9150611c17602084016119c8565b90509250929050565b600181811c90821680611c3457607f821691505b6020821081036113a757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561059557610595611c54565b600082611c9a57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561059557610595611c54565b808202811582820484141761059557610595611c54565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220d92acc530753a19696d3bd33c34277734b40da73f34ff04b709f57d8cc6d4a4964736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000db04b09a1330d79dd94c440ef13ceeea644355820000000000000000000000000000000000000000000000000000000000000019496e63657074696f6e4c52542072657374616b656420455448000000000000000000000000000000000000000000000000000000000000000000000000000005696e455448000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): InceptionLRT restaked ETH
Arg [1] : _symbol (string): inETH
Arg [2] : _factory (address): 0xdb04b09A1330d79DD94c440eF13CeEeA64435582
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 000000000000000000000000db04b09a1330d79dd94c440ef13ceeea64435582
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [4] : 496e63657074696f6e4c52542072657374616b65642045544800000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 696e455448000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
277:9901:34:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2158:98:17;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4444:197;;;;;;:::i;:::-;;:::i;:::-;;;1269:14:55;;1262:22;1244:41;;1232:2;1217:18;4444:197:17;1104:187:55;3043:161:34;;;;;;:::i;:::-;-1:-1:-1;;;;;3159:16:34;3124:14;3159:16;;;:7;:16;;;;;:38;;;;3043:161;;;;1633:25:55;;;1621:2;1606:18;3043:161:34;1487:177:55;3255:106:17;3342:12;;3255:106;;5203:256;;;;;;:::i;:::-;;:::i;563:32:34:-;;;;;;;;-1:-1:-1;;;;;2166:32:55;;;2148:51;;2136:2;2121:18;563:32:34;2002:203:55;3104:91:17;;;3186:2;2352:36:55;;2340:2;2325:18;3104:91:17;2210:184:55;2836:113:19;;;:::i;5854:234:17:-;;;;;;:::i;:::-;;:::i;1436:115:34:-;;;;;;:::i;:::-;;:::i;:::-;;2006:182;;;;;;:::i;:::-;;:::i;2546:317::-;;;;;;:::i;:::-;;:::i;3729:369::-;;;;;;:::i;:::-;;:::i;669:22::-;;;;;-1:-1:-1;;;;;669:22:34;;;3419:125:17;;;;;;:::i;:::-;-1:-1:-1;;;;;3519:18:17;3493:7;3519:18;;;;;;;;;;;;3419:125;1824:101:5;;;:::i;2603:126:19:-;;;;;;:::i;:::-;;:::i;5021:633:30:-;;;:::i;:::-;;;;;;;;;;;;;:::i;1201:85:5:-;1273:6;;-1:-1:-1;;;;;1273:6:5;1201:85;;2369:102:17;;;:::i;4282:369:34:-;;;;;;:::i;:::-;;:::i;1779:115::-;;;;;;:::i;:::-;;:::i;6575:427:17:-;;;;;;:::i;:::-;;:::i;3740:189::-;;;;;;:::i;:::-;;:::i;3384:161:34:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3500:16:34;3465:14;3500:16;;;:7;:16;;;;;:38;;;;3384:161;774:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1923:626:19:-;;;;;;:::i;:::-;;:::i;3987:149:17:-;;;;;;:::i;:::-;;:::i;2074:198:5:-;;;;;;:::i;:::-;;:::i;2158:98:17:-;2212:13;2244:5;2237:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2158:98;:::o;4444:197::-;4527:4;734:10:24;4581:32:17;734:10:24;4597:7:17;4606:6;4581:8;:32::i;:::-;4630:4;4623:11;;;4444:197;;;;;:::o;5203:256::-;5300:4;734:10:24;5356:38:17;5372:4;734:10:24;5387:6:17;5356:15;:38::i;:::-;5404:27;5414:4;5420:2;5424:6;5404:9;:27::i;:::-;5448:4;5441:11;;;5203:256;;;;;;:::o;2836:113:19:-;2896:7;2922:20;:18;:20::i;:::-;2915:27;;2836:113;:::o;5854:234:17:-;5942:4;734:10:24;5996:64:17;734:10:24;6012:7:17;6049:10;6021:25;734:10:24;6012:7:17;6021:9;:25::i;:::-;:38;;;;:::i;:::-;5996:8;:64::i;1436:115:34:-;1501:43;1517:10;1529:5;1536:7;1501:15;:43::i;:::-;1436:115;;:::o;2006:182::-;2067:10;-1:-1:-1;;;;;2081:7:34;2067:21;;2063:54;;2097:20;;-1:-1:-1;;;2097:20:34;;;;;;;;;;;2063:54;2127:7;:18;;-1:-1:-1;;;;;;2127:18:34;-1:-1:-1;;;;;2127:18:34;;;;;;;;2161:20;;2148:51:55;;;2161:20:34;;2136:2:55;2121:18;2161:20:34;;;;;;;2006:182;:::o;2546:317::-;1094:13:5;:11;:13::i;:::-;2693:42:34::1;2712:7;2721:13;2693:18;:42::i;:::-;2745;2764:7;2773:13;2745:18;:42::i;:::-;2802:54;::::0;;6681:25:55;;;6737:2;6722:18;;6715:34;;;-1:-1:-1;;;;;2802:54:34;::::1;::::0;::::1;::::0;6654:18:55;2802:54:34::1;;;;;;;2546:317:::0;;;:::o;3729:369::-;-1:-1:-1;;;;;3877:16:34;;3812:14;3877:16;;;:7;:16;;;;;:42;;;;3933:38;;;;3985:39;;4038:43;;;;;3847:244;;3985:39;3847:16;:244::i;1824:101:5:-;1094:13;:11;:13::i;:::-;1888:30:::1;1915:1;1888:18;:30::i;:::-;1824:101::o:0;2603:126:19:-;-1:-1:-1;;;;;2698:14:19;;2672:7;2698:14;;;:7;:14;;;;;918::25;2698:24:19;827:112:25;5021:633:30;5136:13;5163:18;;5136:13;;;5163:18;5427:41;:5;5454:13;5427:26;:41::i;:::-;5482:47;:8;5512:16;5482:29;:47::i;:::-;5621:16;;;5605:1;5621:16;;;;;;;;;-1:-1:-1;;;5376:271:30;;;-1:-1:-1;5376:271:30;;-1:-1:-1;5543:13:30;;-1:-1:-1;5578:4:30;;-1:-1:-1;5605:1:30;-1:-1:-1;5621:16:30;-1:-1:-1;5376:271:30;-1:-1:-1;5021:633:30:o;2369:102:17:-;2425:13;2457:7;2450:14;;;;;:::i;4282:369:34:-;-1:-1:-1;;;;;4430:16:34;;4365:14;4430:16;;;:7;:16;;;;;:42;;;;4486:38;;;;4430:29;;;4538:39;4591:43;;;;;4400:244;;4538:39;4400:16;:244::i;1779:115::-;1844:43;1860:10;1872:5;1879:7;1844:15;:43::i;6575:427:17:-;6668:4;734:10:24;6668:4:17;6749:25;734:10:24;6766:7:17;6749:9;:25::i;:::-;6722:52;;6812:15;6792:16;:35;;6784:85;;;;-1:-1:-1;;;6784:85:17;;7094:2:55;6784:85:17;;;7076:21:55;7133:2;7113:18;;;7106:30;7172:34;7152:18;;;7145:62;-1:-1:-1;;;7223:18:55;;;7216:35;7268:19;;6784:85:17;;;;;;;;;6903:60;6912:5;6919:7;6947:15;6928:16;:34;6903:8;:60::i;:::-;-1:-1:-1;6991:4:17;;6575:427;-1:-1:-1;;;;6575:427:17:o;3740:189::-;3819:4;734:10:24;3873:28:17;734:10:24;3890:2:17;3894:6;3873:9;:28::i;1923:626:19:-;2158:8;2139:15;:27;;2131:69;;;;-1:-1:-1;;;2131:69:19;;7500:2:55;2131:69:19;;;7482:21:55;7539:2;7519:18;;;7512:30;7578:31;7558:18;;;7551:59;7627:18;;2131:69:19;7298:353:55;2131:69:19;2211:18;1125:95;2271:5;2278:7;2287:5;2294:16;2304:5;2294:9;:16::i;:::-;2242:79;;;;;;7943:25:55;;;;-1:-1:-1;;;;;8042:15:55;;;8022:18;;;8015:43;8094:15;;;;8074:18;;;8067:43;8126:18;;;8119:34;8169:19;;;8162:35;8213:19;;;8206:35;;;7915:19;;2242:79:19;;;;;;;;;;;;2232:90;;;;;;2211:111;;2333:12;2348:28;2365:10;2348:16;:28::i;:::-;2333:43;;2387:14;2404:28;2418:4;2424:1;2427;2430;2404:13;:28::i;:::-;2387:45;;2460:5;-1:-1:-1;;;;;2450:15:19;:6;-1:-1:-1;;;;;2450:15:19;;2442:58;;;;-1:-1:-1;;;2442:58:19;;8454:2:55;2442:58:19;;;8436:21:55;8493:2;8473:18;;;8466:30;8532:32;8512:18;;;8505:60;8582:18;;2442:58:19;8252:354:55;2442:58:19;2511:31;2520:5;2527:7;2536:5;2511:8;:31::i;:::-;2121:428;;;1923:626;;;;;;;:::o;3987:149:17:-;-1:-1:-1;;;;;4102:18:17;;;4076:7;4102:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3987:149::o;2074:198:5:-;1094:13;:11;:13::i;:::-;-1:-1:-1;;;;;2162:22:5;::::1;2154:73;;;::::0;-1:-1:-1;;;2154:73:5;;8813:2:55;2154:73:5::1;::::0;::::1;8795:21:55::0;8852:2;8832:18;;;8825:30;8891:34;8871:18;;;8864:62;-1:-1:-1;;;8942:18:55;;;8935:36;8988:19;;2154:73:5::1;8611:402:55::0;2154:73:5::1;2237:28;2256:8;2237:18;:28::i;:::-;2074:198:::0;:::o;10457:340:17:-;-1:-1:-1;;;;;10558:19:17;;10550:68;;;;-1:-1:-1;;;10550:68:17;;9220:2:55;10550:68:17;;;9202:21:55;9259:2;9239:18;;;9232:30;9298:34;9278:18;;;9271:62;-1:-1:-1;;;9349:18:55;;;9342:34;9393:19;;10550:68:17;9018:400:55;10550:68:17;-1:-1:-1;;;;;10636:21:17;;10628:68;;;;-1:-1:-1;;;10628:68:17;;9625:2:55;10628:68:17;;;9607:21:55;9664:2;9644:18;;;9637:30;9703:34;9683:18;;;9676:62;-1:-1:-1;;;9754:18:55;;;9747:32;9796:19;;10628:68:17;9423:398:55;10628:68:17;-1:-1:-1;;;;;10707:18:17;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10758:32;;1633:25:55;;;10758:32:17;;1606:18:55;10758:32:17;;;;;;;10457:340;;;:::o;11078:411::-;11178:24;11205:25;11215:5;11222:7;11205:9;:25::i;:::-;11178:52;;-1:-1:-1;;11244:16:17;:37;11240:243;;11325:6;11305:16;:26;;11297:68;;;;-1:-1:-1;;;11297:68:17;;10028:2:55;11297:68:17;;;10010:21:55;10067:2;10047:18;;;10040:30;10106:31;10086:18;;;10079:59;10155:18;;11297:68:17;9826:353:55;11297:68:17;11407:51;11416:5;11423:7;11451:6;11432:16;:25;11407:8;:51::i;:::-;11168:321;11078:411;;;:::o;7456:788::-;-1:-1:-1;;;;;7552:18:17;;7544:68;;;;-1:-1:-1;;;7544:68:17;;10386:2:55;7544:68:17;;;10368:21:55;10425:2;10405:18;;;10398:30;10464:34;10444:18;;;10437:62;-1:-1:-1;;;10515:18:55;;;10508:35;10560:19;;7544:68:17;10184:401:55;7544:68:17;-1:-1:-1;;;;;7630:16:17;;7622:64;;;;-1:-1:-1;;;7622:64:17;;10792:2:55;7622:64:17;;;10774:21:55;10831:2;10811:18;;;10804:30;10870:34;10850:18;;;10843:62;-1:-1:-1;;;10921:18:55;;;10914:33;10964:19;;7622:64:17;10590:399:55;7622:64:17;-1:-1:-1;;;;;7768:15:17;;7746:19;7768:15;;;;;;;;;;;7801:21;;;;7793:72;;;;-1:-1:-1;;;7793:72:17;;11196:2:55;7793:72:17;;;11178:21:55;11235:2;11215:18;;;11208:30;11274:34;11254:18;;;11247:62;-1:-1:-1;;;11325:18:55;;;11318:36;11371:19;;7793:72:17;10994:402:55;7793:72:17;-1:-1:-1;;;;;7899:15:17;;;:9;:15;;;;;;;;;;;7917:20;;;7899:38;;8114:13;;;;;;;;;;:23;;;;;;8163:26;;1633:25:55;;;8114:13:17;;8163:26;;1606:18:55;8163:26:17;;;;;;;8200:37;9786:390:34;3695:262:30;3748:7;3779:4;-1:-1:-1;;;;;3788:11:30;3771:28;;:63;;;;;3820:14;3803:13;:31;3771:63;3767:184;;;-1:-1:-1;3857:22:30;;3695:262::o;3767:184::-;3917:23;4054:81;;;1929:95;4054:81;;;12549:25:55;4077:11:30;12590:18:55;;;12583:34;;;;4090:14:30;12633:18:55;;;12626:34;4106:13:30;12676:18:55;;;12669:34;4129:4:30;12719:19:55;;;12712:61;4018:7:30;;12521:19:55;;4054:81:30;;;;;;;;;;;;4044:92;;;;;;4037:99;;3963:180;;9786:390:34;9924:7;;-1:-1:-1;;;;;9913:18:34;;;9924:7;;9913:18;9909:230;;9947:21;9971:30;9993:7;9971:21;:30::i;:::-;9947:54;;10035:7;10019:13;:23;10015:65;;;10051:29;;-1:-1:-1;;;10051:29:34;;;;;;;;;;;10015:65;10094:34;10111:7;10120;10094:16;:34::i;:::-;9933:206;9909:230;10148:21;10154:5;10161:7;10148:5;:21::i;:::-;9786:390;;;:::o;1359:130:5:-;1273:6;;-1:-1:-1;;;;;1273:6:5;734:10:24;1422:23:5;1414:68;;;;-1:-1:-1;;;1414:68:5;;11603:2:55;1414:68:5;;;11585:21:55;;;11622:18;;;11615:30;11681:34;11661:18;;;11654:62;11733:18;;1414:68:5;11401:356:55;5841:651:34;463:6;5925;:18;:32;;;;;5956:1;5947:6;:10;5925:32;5921:71;;;5966:26;;-1:-1:-1;;;5966:26:34;;;;;;;;;;;5921:71;-1:-1:-1;;;;;6023:16:34;;6003:17;6023:16;;;:7;:16;;;;;:38;;;;6095:30;6031:7;6095:21;:30::i;:::-;-1:-1:-1;;;;;6135:16:34;;;;;;:7;:16;;;;;:38;;:47;;;6071:54;-1:-1:-1;6238:105:34;6176:6;6297:9;6071:54;6238:25;:105::i;:::-;-1:-1:-1;;;;;6193:16:34;;;;;;:7;:16;;;;;:42;;:150;6400:18;463:6;6400;:18;:::i;:::-;-1:-1:-1;;;;;6354:16:34;;;;;;;:7;:16;;;;;:43;;;:64;;;;-1:-1:-1;;6470:15:34;6428:57;;;-1:-1:-1;5841:651:34:o;6750:::-;463:6;6834;:18;:32;;;;;6865:1;6856:6;:10;6834:32;6830:71;;;6875:26;;-1:-1:-1;;;6875:26:34;;;;;;;;;;;6830:71;-1:-1:-1;;;;;6932:16:34;;6912:17;6932:16;;;:7;:16;;;;;:38;;;;7004:30;6940:7;7004:21;:30::i;:::-;-1:-1:-1;;;;;7044:16:34;;;;;;:7;:16;;;;;:38;;:47;;;6980:54;-1:-1:-1;7147:105:34;7085:6;7206:9;6980:54;7147:25;:105::i;:::-;-1:-1:-1;;;;;7102:16:34;;;;;;:7;:16;;;;;:42;;:150;7309:18;463:6;7309;:18;:::i;:::-;-1:-1:-1;;;;;7263:16:34;;;;;;;:7;:16;;;;;:43;;;:64;;;;-1:-1:-1;;7379:15:34;7263:29;;;;7337:57;;;;-1:-1:-1;6750:651:34:o;8397:717::-;8605:13;8628:480;;;8667:13;8628:480;8727:15;8701:22;463:6;8701:10;:22;:::i;:::-;:41;8697:411;;-1:-1:-1;8767:9:34;8697:411;;;8822:15;8797:22;463:6;8797:10;:22;:::i;:::-;:40;8793:315;;;8853:19;8875:28;8893:10;8875:15;:28;:::i;:::-;8853:50;-1:-1:-1;8917:24:34;8954:28;8968:14;8853:50;8954:28;:::i;:::-;8944:39;;:6;:39;:::i;:::-;8917:66;;9025:9;9006:16;:28;:91;;9081:16;9006:91;;;9053:9;9006:91;8997:100;;8839:269;;8793:315;8397:717;;;;;;:::o;2426:187:5:-;2518:6;;;-1:-1:-1;;;;;2534:17:5;;;-1:-1:-1;;;;;;2534:17:5;;;;;;;2566:40;;2518:6;;;2534:17;2518:6;;2566:40;;2499:16;;2566:40;2489:124;2426:187;:::o;3367:268:26:-;3461:13;1371:66;3490:47;;3486:143;;3560:15;3569:5;3560:8;:15::i;:::-;3553:22;;;;3486:143;3613:5;3606:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9255:390:34;9393:7;;-1:-1:-1;;;;;9382:18:34;;;9393:7;;9382:18;9378:230;;9416:21;9440:30;9462:7;9440:21;:30::i;:::-;9416:54;;9504:7;9488:13;:23;9484:65;;;9520:29;;-1:-1:-1;;;9520:29:34;;;;;;;;;;;9484:65;9563:34;9580:7;9589;9563:16;:34::i;:::-;9402:206;9378:230;9617:21;9623:5;9630:7;9617:5;:21::i;3080:203:19:-;-1:-1:-1;;;;;3200:14:19;;3140:15;3200:14;;;:7;:14;;;;;918::25;;1050:1;1032:19;;;;918:14;3259:17:19;3157:126;3080:203;;;:::o;4768:165:30:-;4845:7;4871:55;4893:20;:18;:20::i;:::-;4915:10;8536:4:29;8530:11;-1:-1:-1;;;8554:23:29;;8606:4;8597:14;;8590:39;;;;8658:4;8649:14;;8642:34;8712:4;8697:20;;;8336:397;6598:232;6683:7;6703:17;6722:18;6744:25;6755:4;6761:1;6764;6767;6744:10;:25::i;:::-;6702:67;;;;6779:18;6791:5;6779:11;:18::i;:::-;-1:-1:-1;6814:9:29;6598:232;-1:-1:-1;;;;;6598:232:29:o;4832:285:34:-;4911:21;4935:30;4957:7;4935:21;:30::i;:::-;-1:-1:-1;;;;;4975:16:34;;;;;;:7;:16;;;;;5017:15;4975:57;;4911:54;-1:-1:-1;5087:23:34;5103:7;4911:54;5087:23;:::i;:::-;-1:-1:-1;;;;;5042:16:34;;;;;;;:7;:16;;;;;:42;;:68;;;;-1:-1:-1;;4832:285:34:o;8520:535:17:-;-1:-1:-1;;;;;8603:21:17;;8595:65;;;;-1:-1:-1;;;8595:65:17;;12986:2:55;8595:65:17;;;12968:21:55;13025:2;13005:18;;;12998:30;13064:33;13044:18;;;13037:61;13115:18;;8595:65:17;12784:355:55;8595:65:17;8747:6;8731:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;8899:18:17;;:9;:18;;;;;;;;;;;:28;;;;;;8952:37;1633:25:55;;;8952:37:17;;1606:18:55;8952:37:17;;;;;;;1436:115:34;;:::o;7596:548::-;7742:24;7778:19;7824:6;7812:9;:18;7808:330;;;7860:18;7872:6;7860:9;:18;:::i;:::-;7846:32;;7927:11;7911:13;:27;:93;;8003:1;7911:93;;;7957:27;7973:11;7957:13;:27;:::i;:::-;7892:112;;7808:330;;;8049:18;8058:9;8049:6;:18;:::i;:::-;8035:32;-1:-1:-1;8100:27:34;8035:32;8100:13;:27;:::i;:::-;8081:46;;7808:330;7768:376;7596:548;;;;;:::o;2059:405:26:-;2118:13;2143:11;2157:16;2168:4;2157:10;:16::i;:::-;2281:14;;;2292:2;2281:14;;;;;;;;;2143:30;;-1:-1:-1;2261:17:26;;2281:14;;;;;;;;;-1:-1:-1;;;2371:16:26;;;-1:-1:-1;2416:4:26;2407:14;;2400:28;;;;-1:-1:-1;2371:16:26;2059:405::o;5298:285:34:-;5377:21;5401:30;5423:7;5401:21;:30::i;:::-;-1:-1:-1;;;;;5441:16:34;;;;;;:7;:16;;;;;5483:15;5441:29;;;;:57;5377:54;-1:-1:-1;5553:23:34;5569:7;5377:54;5553:23;:::i;:::-;-1:-1:-1;;;;;5508:16:34;;;;;;;:7;:16;;;;;:42;;:68;;;;-1:-1:-1;;5298:285:34:o;9375:659:17:-;-1:-1:-1;;;;;9458:21:17;;9450:67;;;;-1:-1:-1;;;9450:67:17;;13346:2:55;9450:67:17;;;13328:21:55;13385:2;13365:18;;;13358:30;13424:34;13404:18;;;13397:62;-1:-1:-1;;;13475:18:55;;;13468:31;13516:19;;9450:67:17;13144:397:55;9450:67:17;-1:-1:-1;;;;;9613:18:17;;9588:22;9613:18;;;;;;;;;;;9649:24;;;;9641:71;;;;-1:-1:-1;;;9641:71:17;;13748:2:55;9641:71:17;;;13730:21:55;13787:2;13767:18;;;13760:30;13826:34;13806:18;;;13799:62;-1:-1:-1;;;13877:18:55;;;13870:32;13919:19;;9641:71:17;13546:398:55;9641:71:17;-1:-1:-1;;;;;9746:18:17;;:9;:18;;;;;;;;;;;9767:23;;;9746:44;;9883:12;:22;;;;;;;9931:37;1633:25:55;;;9746:9:17;;:18;9931:37;;1606:18:55;9931:37:17;;;;;;;9786:390:34;;;:::o;5009:1456:29:-;5097:7;;6021:66;6008:79;;6004:161;;;-1:-1:-1;6119:1:29;;-1:-1:-1;6123:30:29;6103:51;;6004:161;6276:24;;;6259:14;6276:24;;;;;;;;;14176:25:55;;;14249:4;14237:17;;14217:18;;;14210:45;;;;14271:18;;;14264:34;;;14314:18;;;14307:34;;;6276:24:29;;14148:19:55;;6276:24:29;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6276:24:29;;-1:-1:-1;;6276:24:29;;;-1:-1:-1;;;;;;;6314:20:29;;6310:101;;6366:1;6370:29;6350:50;;;;;;;6310:101;6429:6;-1:-1:-1;6437:20:29;;-1:-1:-1;5009:1456:29;;;;;;;;:::o;570:511::-;647:20;638:5;:29;;;;;;;;:::i;:::-;;634:441;;570:511;:::o;634:441::-;743:29;734:5;:38;;;;;;;;:::i;:::-;;730:345;;788:34;;-1:-1:-1;;;788:34:29;;14686:2:55;788:34:29;;;14668:21:55;14725:2;14705:18;;;14698:30;14764:26;14744:18;;;14737:54;14808:18;;788:34:29;14484:348:55;730:345:29;852:35;843:5;:44;;;;;;;;:::i;:::-;;839:236;;903:41;;-1:-1:-1;;;903:41:29;;15039:2:55;903:41:29;;;15021:21:55;15078:2;15058:18;;;15051:30;15117:33;15097:18;;;15090:61;15168:18;;903:41:29;14837:355:55;839:236:29;974:30;965:5;:39;;;;;;;;:::i;:::-;;961:114;;1020:44;;-1:-1:-1;;;1020:44:29;;15399:2:55;1020:44:29;;;15381:21:55;15438:2;15418:18;;;15411:30;15477:34;15457:18;;;15450:62;-1:-1:-1;;;15528:18:55;;;15521:32;15570:19;;1020:44:29;15197:398:55;2536:245:26;2597:7;2669:4;2633:40;;2696:2;2687:11;;2683:69;;;2721:20;;-1:-1:-1;;;2721:20:26;;;;;;;;;;;14:423:55;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;667:173::-;735:20;;-1:-1:-1;;;;;784:31:55;;774:42;;764:70;;830:1;827;820:12;764:70;667:173;;;:::o;845:254::-;913:6;921;974:2;962:9;953:7;949:23;945:32;942:52;;;990:1;987;980:12;942:52;1013:29;1032:9;1013:29;:::i;:::-;1003:39;1089:2;1074:18;;;;1061:32;;-1:-1:-1;;;845:254:55:o;1296:186::-;1355:6;1408:2;1396:9;1387:7;1383:23;1379:32;1376:52;;;1424:1;1421;1414:12;1376:52;1447:29;1466:9;1447:29;:::i;1669:328::-;1746:6;1754;1762;1815:2;1803:9;1794:7;1790:23;1786:32;1783:52;;;1831:1;1828;1821:12;1783:52;1854:29;1873:9;1854:29;:::i;:::-;1844:39;;1902:38;1936:2;1925:9;1921:18;1902:38;:::i;:::-;1892:48;;1987:2;1976:9;1972:18;1959:32;1949:42;;1669:328;;;;;:::o;2581:322::-;2658:6;2666;2674;2727:2;2715:9;2706:7;2702:23;2698:32;2695:52;;;2743:1;2740;2733:12;2695:52;2766:29;2785:9;2766:29;:::i;:::-;2756:39;2842:2;2827:18;;2814:32;;-1:-1:-1;2893:2:55;2878:18;;;2865:32;;2581:322;-1:-1:-1;;;2581:322:55:o;2908:1259::-;3314:3;3309;3305:13;3297:6;3293:26;3282:9;3275:45;3256:4;3339:2;3377:3;3372:2;3361:9;3357:18;3350:31;3404:46;3445:3;3434:9;3430:19;3422:6;3404:46;:::i;:::-;3498:9;3490:6;3486:22;3481:2;3470:9;3466:18;3459:50;3532:33;3558:6;3550;3532:33;:::i;:::-;3596:2;3581:18;;3574:34;;;-1:-1:-1;;;;;3645:32:55;;3639:3;3624:19;;3617:61;3665:3;3694:19;;3687:35;;;3759:22;;;3753:3;3738:19;;3731:51;3831:13;;3853:22;;;3929:15;;;;-1:-1:-1;3891:15:55;;;;-1:-1:-1;3972:169:55;3986:6;3983:1;3980:13;3972:169;;;4047:13;;4035:26;;4116:15;;;;4081:12;;;;4008:1;4001:9;3972:169;;;-1:-1:-1;4158:3:55;;2908:1259;-1:-1:-1;;;;;;;;;;;;2908:1259:55:o;4446:446::-;4254:12;;4242:25;;4316:4;4305:16;;;4299:23;4283:14;;;4276:47;4372:4;4361:16;;;4355:23;4339:14;;;4332:47;4428:4;4417:16;;;4411:23;4395:14;;;4388:47;4254:12;;4881:3;4866:19;;4242:25;4305:16;;;4299:23;4283:14;;;4276:47;4361:16;;4355:23;4339:14;;;4332:47;4417:16;;4411:23;4395:14;;;4388:47;4748:3;4733:19;;4823:63;4172:269;4897:693;5008:6;5016;5024;5032;5040;5048;5056;5109:3;5097:9;5088:7;5084:23;5080:33;5077:53;;;5126:1;5123;5116:12;5077:53;5149:29;5168:9;5149:29;:::i;:::-;5139:39;;5197:38;5231:2;5220:9;5216:18;5197:38;:::i;:::-;5187:48;;5282:2;5271:9;5267:18;5254:32;5244:42;;5333:2;5322:9;5318:18;5305:32;5295:42;;5387:3;5376:9;5372:19;5359:33;5432:4;5425:5;5421:16;5414:5;5411:27;5401:55;;5452:1;5449;5442:12;5401:55;4897:693;;;;-1:-1:-1;4897:693:55;;;;5475:5;5527:3;5512:19;;5499:33;;-1:-1:-1;5579:3:55;5564:19;;;5551:33;;4897:693;-1:-1:-1;;4897:693:55:o;5595:260::-;5663:6;5671;5724:2;5712:9;5703:7;5699:23;5695:32;5692:52;;;5740:1;5737;5730:12;5692:52;5763:29;5782:9;5763:29;:::i;:::-;5753:39;;5811:38;5845:2;5834:9;5830:18;5811:38;:::i;:::-;5801:48;;5595:260;;;;;:::o;5860:380::-;5939:1;5935:12;;;;5982;;;6003:61;;6057:4;6049:6;6045:17;6035:27;;6003:61;6110:2;6102:6;6099:14;6079:18;6076:38;6073:161;;6156:10;6151:3;6147:20;6144:1;6137:31;6191:4;6188:1;6181:15;6219:4;6216:1;6209:15;6245:127;6306:10;6301:3;6297:20;6294:1;6287:31;6337:4;6334:1;6327:15;6361:4;6358:1;6351:15;6377:125;6442:9;;;6463:10;;;6460:36;;;6476:18;;:::i;11762:217::-;11802:1;11828;11818:132;;11872:10;11867:3;11863:20;11860:1;11853:31;11907:4;11904:1;11897:15;11935:4;11932:1;11925:15;11818:132;-1:-1:-1;11964:9:55;;11762:217::o;11984:128::-;12051:9;;;12072:11;;;12069:37;;;12086:18;;:::i;12117:168::-;12190:9;;;12221;;12238:15;;;12232:22;;12218:37;12208:71;;12259:18;;:::i;14352:127::-;14413:10;14408:3;14404:20;14401:1;14394:31;14444:4;14441:1;14434:15;14468:4;14465:1;14458:15
Swarm Source
ipfs://d92acc530753a19696d3bd33c34277734b40da73f34ff04b709f57d8cc6d4a49
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.