Source Code
Overview
S Balance
S Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PersonalVault
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at SonicScan.org on 2025-11-23 */ // Sources flattened with hardhat v2.26.0 https://hardhat.org // SPDX-License-Identifier: MIT // File @openzeppelin/contracts/utils/introspection/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol) pragma solidity >=0.4.16; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File @openzeppelin/contracts/interfaces/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol) pragma solidity >=0.4.16; // File @openzeppelin/contracts/token/ERC20/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol) pragma solidity >=0.4.16; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // File @openzeppelin/contracts/interfaces/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol) pragma solidity >=0.4.16; // File @openzeppelin/contracts/interfaces/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol) pragma solidity >=0.6.2; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); } // File @openzeppelin/contracts/token/ERC20/utils/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } } // File @openzeppelin/contracts/proxy/utils/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.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 reinitialization) 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 Pointer to storage slot. Allows integrators to override it with a custom storage location. * * NOTE: Consider following the ERC-7201 formula to derive storage locations. */ function _initializableStorageSlot() internal pure virtual returns (bytes32) { return INITIALIZABLE_STORAGE; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { bytes32 slot = _initializableStorageSlot(); assembly { $.slot := slot } } } // File @openzeppelin/contracts/utils/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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 EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * 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 ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } } // File contracts/PersonalVault.sol // Original license: SPDX_License_Identifier: MIT pragma solidity 0.8.20; interface IYieldProvider { function deposit(uint256 assets) external; function withdraw(uint256 assets, address receiver) external returns (uint256); function totalAssets() external view returns (uint256); } /** * @title PersonalVault * @notice Per-user vault for USDC yield generation with 10% fee on profits * @dev Each SmartAccount gets its own vault instance * Compatible with EIP-1167 minimal proxy pattern for gas-efficient deployment */ contract PersonalVault is ReentrancyGuard, Initializable { using SafeERC20 for IERC20; // Configuration (converted from immutable for clone compatibility) address public owner; IERC20 public asset; // USDC IYieldProvider public yieldProvider; address public feeRecipient; // Vault state uint256 public principal; // Total principal deposited (net of withdrawals) uint256 public totalShares; // Total shares in this vault uint256 public constant FEE_BASIS_POINTS = 1000; // 10% fee on yield only event Deposit(uint256 assets, uint256 shares); event Withdraw(uint256 assets, uint256 assetsReceived, uint256 fee, uint256 principalReturned); modifier onlyOwner() { require(msg.sender == owner, "PersonalVault: caller is not owner"); _; } /** * @notice Initialize the PersonalVault (replaces constructor for clones) * @param _owner SmartAccount that owns this vault * @param _asset USDC token address * @param _yieldProvider Yield provider address (Aave or mock) * @param _feeRecipient Address to receive protocol fees * @dev Can only be called once. Protected by OpenZeppelin's Initializable * Gas fees are automatically attributed to the PersonalVaultFactory (FeeM Project ID: 237) */ function initialize( address _owner, address _asset, address _yieldProvider, address _feeRecipient ) external initializer { require(_owner != address(0), "PersonalVault: owner cannot be zero"); require(_asset != address(0), "PersonalVault: asset cannot be zero"); require(_yieldProvider != address(0), "PersonalVault: yieldProvider cannot be zero"); require(_feeRecipient != address(0), "PersonalVault: feeRecipient cannot be zero"); owner = _owner; asset = IERC20(_asset); yieldProvider = IYieldProvider(_yieldProvider); feeRecipient = _feeRecipient; } /** * @notice Deposit USDC and receive shares * @param assets Amount of USDC to deposit * @return sharesOut Amount of shares minted */ function deposit(uint256 assets) external onlyOwner nonReentrant returns (uint256 sharesOut) { require(assets > 0, "PersonalVault: cannot deposit zero"); // Transfer USDC from SmartAccount asset.safeTransferFrom(msg.sender, address(this), assets); // Calculate shares to mint sharesOut = convertToShares(assets); // Update state totalShares += sharesOut; principal += assets; // Deposit to yield provider asset.safeIncreaseAllowance(address(yieldProvider), assets); yieldProvider.deposit(assets); emit Deposit(assets, sharesOut); } /** * @notice Withdraw USDC, charging 10% fee on yield only * @param assets Amount of USDC to withdraw * @return assetsReceived Amount of USDC received by owner (after fee) */ function withdraw(uint256 assets) external onlyOwner nonReentrant returns (uint256 assetsReceived) { require(assets > 0, "PersonalVault: cannot withdraw zero"); require(totalShares > 0, "PersonalVault: no shares"); // Calculate total vault value uint256 vaultValue = totalAssets(); require(assets <= vaultValue, "PersonalVault: insufficient balance"); // Calculate proportional principal being withdrawn // usedPrincipal = principal * assets / totalAssets() uint256 usedPrincipal = (principal * assets) / vaultValue; // Clamp to available principal to handle rounding if (usedPrincipal > principal) { usedPrincipal = principal; } // Calculate shares to burn uint256 sharesToBurn = (totalShares * assets) / vaultValue; // Clamp to available shares if (sharesToBurn > totalShares) { sharesToBurn = totalShares; } // Burn shares and reduce principal BEFORE withdrawal totalShares -= sharesToBurn; principal -= usedPrincipal; // Zero out dust when fully exiting if (totalShares == 0) { principal = 0; } // Withdraw from yield provider uint256 actualWithdrawn = yieldProvider.withdraw(assets, address(this)); // Calculate fee based on profit // profit = max(actualWithdrawn - usedPrincipal, 0) uint256 profit = 0; uint256 feeAmount = 0; if (actualWithdrawn > usedPrincipal) { profit = actualWithdrawn - usedPrincipal; feeAmount = (profit * FEE_BASIS_POINTS) / 10000; // 10% of profit } // Amount owner receives (actualWithdrawn - fee) assetsReceived = actualWithdrawn - feeAmount; // Transfer net amount to owner if (assetsReceived > 0) { asset.safeTransfer(owner, assetsReceived); } // Transfer fee to feeRecipient if (feeAmount > 0) { asset.safeTransfer(feeRecipient, feeAmount); } emit Withdraw(assets, assetsReceived, feeAmount, usedPrincipal); } /** * @notice Get total assets in vault (including yield) * @return Total USDC managed by this vault */ function totalAssets() public view returns (uint256) { return yieldProvider.totalAssets(); } /** * @notice Convert assets to shares * @param assets Amount of USDC * @return Amount of shares */ function convertToShares(uint256 assets) public view returns (uint256) { uint256 supply = totalShares; if (supply == 0) { return assets; // 1:1 on first deposit } return (assets * supply) / totalAssets(); } /** * @notice Convert shares to assets * @param sharesAmount Amount of shares * @return Amount of USDC */ function convertToAssets(uint256 sharesAmount) public view returns (uint256) { uint256 supply = totalShares; if (supply == 0) { return sharesAmount; } return (sharesAmount * totalAssets()) / supply; } /** * @notice Get vault statistics * @return currentValue Total value in vault * @return unrealizedYield Yield earned but not yet withdrawn * @return principalAmount Principal deposited */ function getStats() external view returns ( uint256 currentValue, uint256 unrealizedYield, uint256 principalAmount ) { currentValue = totalAssets(); principalAmount = principal; if (currentValue > principalAmount) { unrealizedYield = currentValue - principalAmount; } else { unrealizedYield = 0; } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetsReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"principalReturned","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"FEE_BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"sharesOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStats","outputs":[{"internalType":"uint256","name":"currentValue","type":"uint256"},{"internalType":"uint256","name":"unrealizedYield","type":"uint256"},{"internalType":"uint256","name":"principalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_yieldProvider","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"principal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"assetsReceived","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yieldProvider","outputs":[{"internalType":"contract IYieldProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506001600055610f2c806100256000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063a525ad3c1161008c578063ba5d307811610066578063ba5d3078146101b9578063c59d4847146101c2578063c6e6f592146101e5578063f8c8765e146101f857600080fd5b8063a525ad3c1461018a578063a82250a814610193578063b6b55f25146101a657600080fd5b806338d52e0f116100c857806338d52e0f146101305780633a98ef391461015b57806346904840146101645780638da5cb5b1461017757600080fd5b806301e1d114146100ef57806307a2d13a1461010a5780632e1a7d4d1461011d575b600080fd5b6100f761020d565b6040519081526020015b60405180910390f35b6100f7610118366004610da2565b61027f565b6100f761012b366004610da2565b6102b7565b600254610143906001600160a01b031681565b6040516001600160a01b039091168152602001610101565b6100f760065481565b600454610143906001600160a01b031681565b600154610143906001600160a01b031681565b6100f76103e881565b600354610143906001600160a01b031681565b6100f76101b4366004610da2565b6105fb565b6100f760055481565b6101ca61079d565b60408051938452602084019290925290820152606001610101565b6100f76101f3366004610da2565b6107d3565b61020b610206366004610dd2565b6107f9565b005b600354604080516278744560e21b815290516000926001600160a01b0316916301e1d1149160048083019260209291908290030181865afa158015610256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027a9190610e26565b905090565b600654600090808203610293575090919050565b8061029c61020d565b6102a69085610e55565b6102b09190610e6c565b9392505050565b6001546000906001600160a01b031633146102ed5760405162461bcd60e51b81526004016102e490610e8e565b60405180910390fd5b6102f5610ad0565b600082116103515760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a2063616e6e6f74207769746864726177207a60448201526265726f60e81b60648201526084016102e4565b6000600654116103a35760405162461bcd60e51b815260206004820152601860248201527f506572736f6e616c5661756c743a206e6f20736861726573000000000000000060448201526064016102e4565b60006103ad61020d565b90508083111561040b5760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a20696e73756666696369656e742062616c616044820152626e636560e81b60648201526084016102e4565b6000818460055461041c9190610e55565b6104269190610e6c565b905060055481111561043757506005545b600082856006546104489190610e55565b6104529190610e6c565b905060065481111561046357506006545b80600660008282546104759190610ed0565b92505081905550816005600082825461048e9190610ed0565b90915550506006546000036104a35760006005555b600354604051627b8a6760e11b8152600481018790523060248201526000916001600160a01b03169062f714ce906044016020604051808303816000875af11580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105179190610e26565b90506000808483111561054c5761052e8584610ed0565b915061271061053f6103e884610e55565b6105499190610e6c565b90505b6105568184610ed0565b9650861561057b5760015460025461057b916001600160a01b03918216911689610afa565b801561059e5760045460025461059e916001600160a01b03918216911683610afa565b6040805189815260208101899052908101829052606081018690527fb088a38065873c9d2da855cf4a2e4aa012b28e45ead53c5b9edbcf71614cfb239060800160405180910390a15050505050506105f66001600055565b919050565b6001546000906001600160a01b031633146106285760405162461bcd60e51b81526004016102e490610e8e565b610630610ad0565b6000821161068b5760405162461bcd60e51b815260206004820152602260248201527f506572736f6e616c5661756c743a2063616e6e6f74206465706f736974207a65604482015261726f60f01b60648201526084016102e4565b6002546106a3906001600160a01b0316333085610b5e565b6106ac826107d3565b905080600660008282546106c09190610ee3565b9250508190555081600560008282546106d99190610ee3565b90915550506003546002546106fb916001600160a01b03918216911684610b9d565b60035460405163b6b55f2560e01b8152600481018490526001600160a01b039091169063b6b55f2590602401600060405180830381600087803b15801561074157600080fd5b505af1158015610755573d6000803e3d6000fd5b505060408051858152602081018590527fa3af609bf46297028ce551832669030f9effef2b02606d02cbbcc40fe6b47c55935001905060405180910390a16105f66001600055565b60008060006107aa61020d565b92506005549050808311156107ca576107c38184610ed0565b9150909192565b60009150909192565b6006546000908082036107e7575090919050565b6107ef61020d565b6102a68285610e55565b6000610803610c27565b805490915060ff600160401b820416159067ffffffffffffffff1660008115801561082b5750825b905060008267ffffffffffffffff1660011480156108485750303b155b905081158015610856575080155b156108745760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561089e57845460ff60401b1916600160401b1785555b6001600160a01b0389166109005760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a206f776e65722063616e6e6f74206265207a60448201526265726f60e81b60648201526084016102e4565b6001600160a01b0388166109625760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a2061737365742063616e6e6f74206265207a60448201526265726f60e81b60648201526084016102e4565b6001600160a01b0387166109cc5760405162461bcd60e51b815260206004820152602b60248201527f506572736f6e616c5661756c743a207969656c6450726f76696465722063616e60448201526a6e6f74206265207a65726f60a81b60648201526084016102e4565b6001600160a01b038616610a355760405162461bcd60e51b815260206004820152602a60248201527f506572736f6e616c5661756c743a20666565526563697069656e742063616e6e6044820152696f74206265207a65726f60b01b60648201526084016102e4565b600180546001600160a01b03808c166001600160a01b031992831617909255600280548b8416908316179055600380548a841690831617905560048054928916929091169190911790558315610ac557845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b600260005403610af357604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b6040516001600160a01b03838116602483015260448201839052610b5991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610c52565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052610b979186918216906323b872dd90608401610b27565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015610bed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c119190610e26565b9050610b978484610c228585610ee3565b610cc3565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b600080602060008451602086016000885af180610c75576040513d6000823e3d81fd5b50506000513d91508115610c8d578060011415610c9a565b6001600160a01b0384163b155b15610b9757604051635274afe760e01b81526001600160a01b03851660048201526024016102e4565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610d148482610d53565b610b97576040516001600160a01b03848116602483015260006044830152610d4991869182169063095ea7b390606401610b27565b610b978482610c52565b6000806000806020600086516020880160008a5af192503d91506000519050828015610d9857508115610d895780600114610d98565b6000866001600160a01b03163b115b9695505050505050565b600060208284031215610db457600080fd5b5035919050565b80356001600160a01b03811681146105f657600080fd5b60008060008060808587031215610de857600080fd5b610df185610dbb565b9350610dff60208601610dbb565b9250610e0d60408601610dbb565b9150610e1b60608601610dbb565b905092959194509250565b600060208284031215610e3857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610c4c57610c4c610e3f565b600082610e8957634e487b7160e01b600052601260045260246000fd5b500490565b60208082526022908201527f506572736f6e616c5661756c743a2063616c6c6572206973206e6f74206f776e60408201526132b960f11b606082015260800190565b81810381811115610c4c57610c4c610e3f565b80820180821115610c4c57610c4c610e3f56fea26469706673582212207906908de1a0742f4a35083f11e6b93a0ed3cd75778ab76e1a38b4ca5e43fb3764736f6c63430008140033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063a525ad3c1161008c578063ba5d307811610066578063ba5d3078146101b9578063c59d4847146101c2578063c6e6f592146101e5578063f8c8765e146101f857600080fd5b8063a525ad3c1461018a578063a82250a814610193578063b6b55f25146101a657600080fd5b806338d52e0f116100c857806338d52e0f146101305780633a98ef391461015b57806346904840146101645780638da5cb5b1461017757600080fd5b806301e1d114146100ef57806307a2d13a1461010a5780632e1a7d4d1461011d575b600080fd5b6100f761020d565b6040519081526020015b60405180910390f35b6100f7610118366004610da2565b61027f565b6100f761012b366004610da2565b6102b7565b600254610143906001600160a01b031681565b6040516001600160a01b039091168152602001610101565b6100f760065481565b600454610143906001600160a01b031681565b600154610143906001600160a01b031681565b6100f76103e881565b600354610143906001600160a01b031681565b6100f76101b4366004610da2565b6105fb565b6100f760055481565b6101ca61079d565b60408051938452602084019290925290820152606001610101565b6100f76101f3366004610da2565b6107d3565b61020b610206366004610dd2565b6107f9565b005b600354604080516278744560e21b815290516000926001600160a01b0316916301e1d1149160048083019260209291908290030181865afa158015610256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027a9190610e26565b905090565b600654600090808203610293575090919050565b8061029c61020d565b6102a69085610e55565b6102b09190610e6c565b9392505050565b6001546000906001600160a01b031633146102ed5760405162461bcd60e51b81526004016102e490610e8e565b60405180910390fd5b6102f5610ad0565b600082116103515760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a2063616e6e6f74207769746864726177207a60448201526265726f60e81b60648201526084016102e4565b6000600654116103a35760405162461bcd60e51b815260206004820152601860248201527f506572736f6e616c5661756c743a206e6f20736861726573000000000000000060448201526064016102e4565b60006103ad61020d565b90508083111561040b5760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a20696e73756666696369656e742062616c616044820152626e636560e81b60648201526084016102e4565b6000818460055461041c9190610e55565b6104269190610e6c565b905060055481111561043757506005545b600082856006546104489190610e55565b6104529190610e6c565b905060065481111561046357506006545b80600660008282546104759190610ed0565b92505081905550816005600082825461048e9190610ed0565b90915550506006546000036104a35760006005555b600354604051627b8a6760e11b8152600481018790523060248201526000916001600160a01b03169062f714ce906044016020604051808303816000875af11580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105179190610e26565b90506000808483111561054c5761052e8584610ed0565b915061271061053f6103e884610e55565b6105499190610e6c565b90505b6105568184610ed0565b9650861561057b5760015460025461057b916001600160a01b03918216911689610afa565b801561059e5760045460025461059e916001600160a01b03918216911683610afa565b6040805189815260208101899052908101829052606081018690527fb088a38065873c9d2da855cf4a2e4aa012b28e45ead53c5b9edbcf71614cfb239060800160405180910390a15050505050506105f66001600055565b919050565b6001546000906001600160a01b031633146106285760405162461bcd60e51b81526004016102e490610e8e565b610630610ad0565b6000821161068b5760405162461bcd60e51b815260206004820152602260248201527f506572736f6e616c5661756c743a2063616e6e6f74206465706f736974207a65604482015261726f60f01b60648201526084016102e4565b6002546106a3906001600160a01b0316333085610b5e565b6106ac826107d3565b905080600660008282546106c09190610ee3565b9250508190555081600560008282546106d99190610ee3565b90915550506003546002546106fb916001600160a01b03918216911684610b9d565b60035460405163b6b55f2560e01b8152600481018490526001600160a01b039091169063b6b55f2590602401600060405180830381600087803b15801561074157600080fd5b505af1158015610755573d6000803e3d6000fd5b505060408051858152602081018590527fa3af609bf46297028ce551832669030f9effef2b02606d02cbbcc40fe6b47c55935001905060405180910390a16105f66001600055565b60008060006107aa61020d565b92506005549050808311156107ca576107c38184610ed0565b9150909192565b60009150909192565b6006546000908082036107e7575090919050565b6107ef61020d565b6102a68285610e55565b6000610803610c27565b805490915060ff600160401b820416159067ffffffffffffffff1660008115801561082b5750825b905060008267ffffffffffffffff1660011480156108485750303b155b905081158015610856575080155b156108745760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561089e57845460ff60401b1916600160401b1785555b6001600160a01b0389166109005760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a206f776e65722063616e6e6f74206265207a60448201526265726f60e81b60648201526084016102e4565b6001600160a01b0388166109625760405162461bcd60e51b815260206004820152602360248201527f506572736f6e616c5661756c743a2061737365742063616e6e6f74206265207a60448201526265726f60e81b60648201526084016102e4565b6001600160a01b0387166109cc5760405162461bcd60e51b815260206004820152602b60248201527f506572736f6e616c5661756c743a207969656c6450726f76696465722063616e60448201526a6e6f74206265207a65726f60a81b60648201526084016102e4565b6001600160a01b038616610a355760405162461bcd60e51b815260206004820152602a60248201527f506572736f6e616c5661756c743a20666565526563697069656e742063616e6e6044820152696f74206265207a65726f60b01b60648201526084016102e4565b600180546001600160a01b03808c166001600160a01b031992831617909255600280548b8416908316179055600380548a841690831617905560048054928916929091169190911790558315610ac557845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b600260005403610af357604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b6040516001600160a01b03838116602483015260448201839052610b5991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610c52565b505050565b6040516001600160a01b038481166024830152838116604483015260648201839052610b979186918216906323b872dd90608401610b27565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015610bed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c119190610e26565b9050610b978484610c228585610ee3565b610cc3565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b600080602060008451602086016000885af180610c75576040513d6000823e3d81fd5b50506000513d91508115610c8d578060011415610c9a565b6001600160a01b0384163b155b15610b9757604051635274afe760e01b81526001600160a01b03851660048201526024016102e4565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610d148482610d53565b610b97576040516001600160a01b03848116602483015260006044830152610d4991869182169063095ea7b390606401610b27565b610b978482610c52565b6000806000806020600086516020880160008a5af192503d91506000519050828015610d9857508115610d895780600114610d98565b6000866001600160a01b03163b115b9695505050505050565b600060208284031215610db457600080fd5b5035919050565b80356001600160a01b03811681146105f657600080fd5b60008060008060808587031215610de857600080fd5b610df185610dbb565b9350610dff60208601610dbb565b9250610e0d60408601610dbb565b9150610e1b60608601610dbb565b905092959194509250565b600060208284031215610e3857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610c4c57610c4c610e3f565b600082610e8957634e487b7160e01b600052601260045260246000fd5b500490565b60208082526022908201527f506572736f6e616c5661756c743a2063616c6c6572206973206e6f74206f776e60408201526132b960f11b606082015260800190565b81810381811115610c4c57610c4c610e3f565b80820180821115610c4c57610c4c610e3f56fea26469706673582212207906908de1a0742f4a35083f11e6b93a0ed3cd75778ab76e1a38b4ca5e43fb3764736f6c63430008140033
Deployed Bytecode Sourcemap
33091:6988:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38535:106;;;:::i;:::-;;;160:25:1;;;148:2;133:18;38535:106:0;;;;;;;;39181:254;;;;;;:::i;:::-;;:::i;36148:2252::-;;;;;;:::i;:::-;;:::i;33290:19::-;;;;;-1:-1:-1;;;;;33290:19:0;;;;;;-1:-1:-1;;;;;558:32:1;;;540:51;;528:2;513:18;33290:19:0;381:216:1;33503:26:0;;;;;;33366:27;;;;;-1:-1:-1;;;;;33366:27:0;;;33263:20;;;;;-1:-1:-1;;;;;33263:20:0;;;33568:47;;33611:4;33568:47;;33324:35;;;;;-1:-1:-1;;;;;33324:35:0;;;35281:654;;;;;;:::i;:::-;;:::i;33422:24::-;;;;;;39667:409;;;:::i;:::-;;;;1242:25:1;;;1298:2;1283:18;;1276:34;;;;1326:18;;;1319:34;1230:2;1215:18;39667:409:0;1040:319:1;38778:260:0;;;;;;:::i;:::-;;:::i;34436:673::-;;;;;;:::i;:::-;;:::i;:::-;;38535:106;38606:13;;:27;;;-1:-1:-1;;;38606:27:0;;;;38579:7;;-1:-1:-1;;;;;38606:13:0;;:25;;:27;;;;;;;;;;;;;;:13;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38599:34;;38535:106;:::o;39181:254::-;39286:11;;39249:7;;39312:11;;;39308:63;;-1:-1:-1;39347:12:0;;39181:254;-1:-1:-1;39181:254:0:o;39308:63::-;39421:6;39404:13;:11;:13::i;:::-;39389:28;;:12;:28;:::i;:::-;39388:39;;;;:::i;:::-;39381:46;39181:254;-1:-1:-1;;;39181:254:0:o;36148:2252::-;33858:5;;36223:22;;-1:-1:-1;;;;;33858:5:0;33844:10;:19;33836:66;;;;-1:-1:-1;;;33836:66:0;;;;;;;:::i;:::-;;;;;;;;;31572:21:::1;:19;:21::i;:::-;36275:1:::2;36266:6;:10;36258:58;;;::::0;-1:-1:-1;;;36258:58:0;;3277:2:1;36258:58:0::2;::::0;::::2;3259:21:1::0;3316:2;3296:18;;;3289:30;3355:34;3335:18;;;3328:62;-1:-1:-1;;;3406:18:1;;;3399:33;3449:19;;36258:58:0::2;3075:399:1::0;36258:58:0::2;36349:1;36335:11;;:15;36327:52;;;::::0;-1:-1:-1;;;36327:52:0;;3681:2:1;36327:52:0::2;::::0;::::2;3663:21:1::0;3720:2;3700:18;;;3693:30;3759:26;3739:18;;;3732:54;3803:18;;36327:52:0::2;3479:348:1::0;36327:52:0::2;36432:18;36453:13;:11;:13::i;:::-;36432:34;;36495:10;36485:6;:20;;36477:68;;;::::0;-1:-1:-1;;;36477:68:0;;4034:2:1;36477:68:0::2;::::0;::::2;4016:21:1::0;4073:2;4053:18;;;4046:30;4112:34;4092:18;;;4085:62;-1:-1:-1;;;4163:18:1;;;4156:33;4206:19;;36477:68:0::2;3832:399:1::0;36477:68:0::2;36682:21;36729:10;36719:6;36707:9;;:18;;;;:::i;:::-;36706:33;;;;:::i;:::-;36682:57;;36840:9;;36824:13;:25;36820:83;;;-1:-1:-1::0;36882:9:0::2;::::0;36820:83:::2;36952:20;37000:10;36990:6;36976:11;;:20;;;;:::i;:::-;36975:35;;;;:::i;:::-;36952:58;;37088:11;;37073:12;:26;37069:85;;;-1:-1:-1::0;37131:11:0::2;::::0;37069:85:::2;37244:12;37229:11;;:27;;;;;;;:::i;:::-;;;;;;;;37280:13;37267:9;;:26;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;37363:11:0::2;::::0;37378:1:::2;37363:16:::0;37359:62:::2;;37408:1;37396:9;:13:::0;37359:62:::2;37500:13;::::0;:45:::2;::::0;-1:-1:-1;;;37500:45:0;;::::2;::::0;::::2;4543:25:1::0;;;37539:4:0::2;4584:18:1::0;;;4577:60;37474:23:0::2;::::0;-1:-1:-1;;;;;37500:13:0::2;::::0;:22:::2;::::0;4516:18:1;;37500:45:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37474:71;;37661:14;37690:17:::0;37754:13:::2;37736:15;:31;37732:183;;;37793:31;37811:13:::0;37793:15;:31:::2;:::i;:::-;37784:40:::0;-1:-1:-1;37881:5:0::2;37852:25;33611:4;37784:40:::0;37852:25:::2;:::i;:::-;37851:35;;;;:::i;:::-;37839:47;;37732:183;38002:27;38020:9:::0;38002:15;:27:::2;:::i;:::-;37985:44:::0;-1:-1:-1;38087:18:0;;38083:92:::2;;38141:5;::::0;38122::::2;::::0;:41:::2;::::0;-1:-1:-1;;;;;38122:5:0;;::::2;::::0;38141::::2;38148:14:::0;38122:18:::2;:41::i;:::-;38232:13:::0;;38228:89:::2;;38281:12;::::0;38262:5:::2;::::0;:43:::2;::::0;-1:-1:-1;;;;;38262:5:0;;::::2;::::0;38281:12:::2;38295:9:::0;38262:18:::2;:43::i;:::-;38334:58;::::0;;4879:25:1;;;4935:2;4920:18;;4913:34;;;4963:18;;;4956:34;;;5021:2;5006:18;;4999:34;;;38334:58:0::2;::::0;4866:3:1;4851:19;38334:58:0::2;;;;;;;36247:2153;;;;;;31616:20:::1;30907:1:::0;32158:7;:21;31975:212;31616:20:::1;36148:2252:::0;;;:::o;35281:654::-;33858:5;;35355:17;;-1:-1:-1;;;;;33858:5:0;33844:10;:19;33836:66;;;;-1:-1:-1;;;33836:66:0;;;;;;;:::i;:::-;31572:21:::1;:19;:21::i;:::-;35402:1:::2;35393:6;:10;35385:57;;;::::0;-1:-1:-1;;;35385:57:0;;5246:2:1;35385:57:0::2;::::0;::::2;5228:21:1::0;5285:2;5265:18;;;5258:30;5324:34;5304:18;;;5297:62;-1:-1:-1;;;5375:18:1;;;5368:32;5417:19;;35385:57:0::2;5044:398:1::0;35385:57:0::2;35499:5;::::0;:57:::2;::::0;-1:-1:-1;;;;;35499:5:0::2;35522:10;35542:4;35549:6:::0;35499:22:::2;:57::i;:::-;35618:23;35634:6;35618:15;:23::i;:::-;35606:35;;35694:9;35679:11;;:24;;;;;;;:::i;:::-;;;;;;;;35727:6;35714:9;;:19;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;35820:13:0::2;::::0;35784:5:::2;::::0;:59:::2;::::0;-1:-1:-1;;;;;35784:5:0;;::::2;::::0;35820:13:::2;35836:6:::0;35784:27:::2;:59::i;:::-;35854:13;::::0;:29:::2;::::0;-1:-1:-1;;;35854:29:0;;::::2;::::0;::::2;160:25:1::0;;;-1:-1:-1;;;;;35854:13:0;;::::2;::::0;:21:::2;::::0;133:18:1;;35854:29:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;35901:26:0::2;::::0;;5751:25:1;;;5807:2;5792:18;;5785:34;;;35901:26:0::2;::::0;-1:-1:-1;5724:18:1;;-1:-1:-1;35901:26:0::2;;;;;;;31616:20:::1;30907:1:::0;32158:7;:21;31975:212;39667:409;39720:20;39751:23;39785;39842:13;:11;:13::i;:::-;39827:28;;39884:9;;39866:27;;39925:15;39910:12;:30;39906:163;;;39975:30;39990:15;39975:12;:30;:::i;:::-;39957:48;;39667:409;;;:::o;39906:163::-;40056:1;40038:19;;39667:409;;;:::o;38778:260::-;38877:11;;38840:7;;38903:11;;;38899:81;;-1:-1:-1;38938:6:0;;38778:260;-1:-1:-1;38778:260:0:o;38899:81::-;39017:13;:11;:13::i;:::-;38998:15;39007:6;38998;:15;:::i;34436:673::-;23670:30;23703:26;:24;:26::i;:::-;23817:15;;23670:59;;-1:-1:-1;23817:15:0;-1:-1:-1;;;23817:15:0;;;23816:16;;23864:14;;23794:19;24247:16;;:34;;;;;24267:14;24247:34;24227:54;;24292:17;24312:11;:16;;24327:1;24312:16;:50;;;;-1:-1:-1;24340:4:0;24332:25;:30;24312:50;24292:70;;24380:12;24379:13;:30;;;;;24397:12;24396:13;24379:30;24375:93;;;24433:23;;-1:-1:-1;;;24433:23:0;;;;;;;;;;;24375:93;24478:18;;-1:-1:-1;;24478:18:0;24495:1;24478:18;;;24507:69;;;;24542:22;;-1:-1:-1;;;;24542:22:0;-1:-1:-1;;;24542:22:0;;;24507:69;-1:-1:-1;;;;;34618:20:0;::::1;34610:68;;;::::0;-1:-1:-1;;;34610:68:0;;6032:2:1;34610:68:0::1;::::0;::::1;6014:21:1::0;6071:2;6051:18;;;6044:30;6110:34;6090:18;;;6083:62;-1:-1:-1;;;6161:18:1;;;6154:33;6204:19;;34610:68:0::1;5830:399:1::0;34610:68:0::1;-1:-1:-1::0;;;;;34697:20:0;::::1;34689:68;;;::::0;-1:-1:-1;;;34689:68:0;;6436:2:1;34689:68:0::1;::::0;::::1;6418:21:1::0;6475:2;6455:18;;;6448:30;6514:34;6494:18;;;6487:62;-1:-1:-1;;;6565:18:1;;;6558:33;6608:19;;34689:68:0::1;6234:399:1::0;34689:68:0::1;-1:-1:-1::0;;;;;34776:28:0;::::1;34768:84;;;::::0;-1:-1:-1;;;34768:84:0;;6840:2:1;34768:84:0::1;::::0;::::1;6822:21:1::0;6879:2;6859:18;;;6852:30;6918:34;6898:18;;;6891:62;-1:-1:-1;;;6969:18:1;;;6962:41;7020:19;;34768:84:0::1;6638:407:1::0;34768:84:0::1;-1:-1:-1::0;;;;;34871:27:0;::::1;34863:82;;;::::0;-1:-1:-1;;;34863:82:0;;7252:2:1;34863:82:0::1;::::0;::::1;7234:21:1::0;7291:2;7271:18;;;7264:30;7330:34;7310:18;;;7303:62;-1:-1:-1;;;7381:18:1;;;7374:40;7431:19;;34863:82:0::1;7050:406:1::0;34863:82:0::1;34958:5;:14:::0;;-1:-1:-1;;;;;34958:14:0;;::::1;-1:-1:-1::0;;;;;;34958:14:0;;::::1;;::::0;;;34983:5:::1;:22:::0;;;;::::1;::::0;;::::1;;::::0;;35016:13:::1;:46:::0;;;;::::1;::::0;;::::1;;::::0;;35073:12:::1;:28:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;24598:104;;;;24633:23;;-1:-1:-1;;;;24633:23:0;;;24676:14;;-1:-1:-1;7614:50:1;;24676:14:0;;7602:2:1;7587:18;24676:14:0;;;;;;;24598:104;23602:1107;;;;;34436:673;;;;:::o;31652:315::-;30950:1;31781:7;;:18;31777:88;;31823:30;;-1:-1:-1;;;31823:30:0;;;;;;;;;;;31777:88;30950:1;31942:7;:17;31652:315::o;10277:162::-;10387:43;;-1:-1:-1;;;;;7867:32:1;;;10387:43:0;;;7849:51:1;7916:18;;;7909:34;;;10360:71:0;;10380:5;;10402:14;;;;;7822:18:1;;10387:43:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10387:43:0;;;;;;;;;;;10360:19;:71::i;:::-;10277:162;;;:::o;10684:190::-;10812:53;;-1:-1:-1;;;;;8212:15:1;;;10812:53:0;;;8194:34:1;8264:15;;;8244:18;;;8237:43;8296:18;;;8289:34;;;10785:81:0;;10805:5;;10827:18;;;;;8129::1;;10812:53:0;7954:375:1;10785:81:0;10684:190;;;;:::o;12239:228::-;12359:39;;-1:-1:-1;;;12359:39:0;;12383:4;12359:39;;;8546:34:1;-1:-1:-1;;;;;8616:15:1;;;8596:18;;;8589:43;12336:20:0;;12359:15;;;;;;8481:18:1;;12359:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12336:62;-1:-1:-1;12409:50:0;12422:5;12429:7;12438:20;12453:5;12336:62;12438:20;:::i;:::-;12409:12;:50::i;28709:210::-;28767:30;;22630:66;28825:27;28810:42;28709:210;-1:-1:-1;;28709:210:0:o;17568:738::-;17649:18;17678:19;17818:4;17815:1;17808:4;17802:11;17795:4;17789;17785:15;17782:1;17775:5;17768;17763:60;17877:7;17867:180;;17922:4;17916:11;17968:16;17965:1;17960:3;17945:40;18015:16;18010:3;18003:29;17867:180;-1:-1:-1;;18126:1:0;18120:8;18075:16;;-1:-1:-1;18155:15:0;;:68;;18207:11;18222:1;18207:16;;18155:68;;;-1:-1:-1;;;;;18173:26:0;;;:31;18155:68;18151:148;;;18247:40;;-1:-1:-1;;;18247:40:0;;-1:-1:-1;;;;;558:32:1;;18247:40:0;;;540:51:1;513:18;;18247:40:0;381:216:1;14210:387:0;14326:47;;;-1:-1:-1;;;;;7867:32:1;;14326:47:0;;;7849:51:1;7916:18;;;;7909:34;;;14326:47:0;;;;;;;;;;7822:18:1;;;;14326:47:0;;;;;;;;-1:-1:-1;;;;;14326:47:0;-1:-1:-1;;;14326:47:0;;;14391:44;14341:13;14326:47;14391:23;:44::i;:::-;14386:204;;14479:43;;-1:-1:-1;;;;;7867:32:1;;;14479:43:0;;;7849:51:1;14519:1:0;7916:18:1;;;7909:34;14452:71:0;;14472:5;;14494:13;;;;;7822:18:1;;14479:43:0;7675:274:1;14452:71:0;14538:40;14558:5;14565:12;14538:19;:40::i;18818:490::-;18901:4;18918:12;18941:18;18970:19;19106:4;19103:1;19096:4;19090:11;19083:4;19077;19073:15;19070:1;19063:5;19056;19051:60;19040:71;;19139:16;19125:30;;19190:1;19184:8;19169:23;;19220:7;:80;;;;-1:-1:-1;19232:15:0;;:67;;19283:11;19298:1;19283:16;19232:67;;;19279:1;19258:5;-1:-1:-1;;;;;19250:26:0;;:30;19232:67;19213:87;18818:490;-1:-1:-1;;;;;;18818:490:0:o;196:180:1:-;255:6;308:2;296:9;287:7;283:23;279:32;276:52;;;324:1;321;314:12;276:52;-1:-1:-1;347:23:1;;196:180;-1:-1:-1;196:180:1:o;1364:173::-;1432:20;;-1:-1:-1;;;;;1481:31:1;;1471:42;;1461:70;;1527:1;1524;1517:12;1542:409;1628:6;1636;1644;1652;1705:3;1693:9;1684:7;1680:23;1676:33;1673:53;;;1722:1;1719;1712:12;1673:53;1745:29;1764:9;1745:29;:::i;:::-;1735:39;;1793:38;1827:2;1816:9;1812:18;1793:38;:::i;:::-;1783:48;;1850:38;1884:2;1873:9;1869:18;1850:38;:::i;:::-;1840:48;;1907:38;1941:2;1930:9;1926:18;1907:38;:::i;:::-;1897:48;;1542:409;;;;;;;:::o;1956:184::-;2026:6;2079:2;2067:9;2058:7;2054:23;2050:32;2047:52;;;2095:1;2092;2085:12;2047:52;-1:-1:-1;2118:16:1;;1956:184;-1:-1:-1;1956:184:1:o;2145:127::-;2206:10;2201:3;2197:20;2194:1;2187:31;2237:4;2234:1;2227:15;2261:4;2258:1;2251:15;2277:168;2350:9;;;2381;;2398:15;;;2392:22;;2378:37;2368:71;;2419:18;;:::i;2450:217::-;2490:1;2516;2506:132;;2560:10;2555:3;2551:20;2548:1;2541:31;2595:4;2592:1;2585:15;2623:4;2620:1;2613:15;2506:132;-1:-1:-1;2652:9:1;;2450:217::o;2672:398::-;2874:2;2856:21;;;2913:2;2893:18;;;2886:30;2952:34;2947:2;2932:18;;2925:62;-1:-1:-1;;;3018:2:1;3003:18;;2996:32;3060:3;3045:19;;2672:398::o;4236:128::-;4303:9;;;4324:11;;;4321:37;;;4338:18;;:::i;5447:125::-;5512:9;;;5533:10;;;5530:36;;;5546:18;;:::i
Swarm Source
ipfs://7906908de1a0742f4a35083f11e6b93a0ed3cd75778ab76e1a38b4ca5e43fb37
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.