Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
622332 | 24 days ago | Contract Creation | 0 S | |||
622332 | 24 days ago | Contract Creation | 0 S | |||
433698 | 27 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
FluidLendingFactory
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 10000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { CREATE3 } from "solmate/src/utils/CREATE3.sol"; import { SSTORE2 } from "solmate/src/utils/SSTORE2.sol"; import { Owned } from "solmate/src/auth/Owned.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { IFluidLiquidity } from "../../../liquidity/interfaces/iLiquidity.sol"; import { IFluidLendingFactory, IFluidLendingFactoryAdmin } from "../interfaces/iLendingFactory.sol"; import { LiquiditySlotsLink } from "../../../libraries/liquiditySlotsLink.sol"; import { ErrorTypes } from "../errorTypes.sol"; import { Error } from "../error.sol"; import { Events } from "./events.sol"; abstract contract LendingFactoryVariables is Owned, Error, IFluidLendingFactory { /*////////////////////////////////////////////////////////////// CONSTANTS / IMMUTABLES //////////////////////////////////////////////////////////////*/ /// @inheritdoc IFluidLendingFactory IFluidLiquidity public immutable LIQUIDITY; /// @dev address that is mapped to the chain native token address internal constant _NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /*////////////////////////////////////////////////////////////// STORAGE VARIABLES //////////////////////////////////////////////////////////////*/ // ------------ storage variables from inherited contracts (Owned) come before vars here -------- // ----------------------- slot 0 --------------------------- // address public owner; // 12 bytes empty // ----------------------- slot 1 --------------------------- /// @dev auths can update rewards related config at created fToken contracts. /// owner can add/remove auths. /// Owner is auth by default. mapping(address => uint256) internal _auths; // ----------------------- slot 2 --------------------------- /// @dev deployers can deploy new fTokens. /// owner can add/remove deployers. /// Owner is deployer by default. mapping(address => uint256) internal _deployers; // ----------------------- slot 3 --------------------------- /// @dev list of all created tokens. /// Solidity creates an automatic getter only to fetch at a certain position, so explicitly define a getter that returns all. address[] internal _allTokens; // ----------------------- slot 4 --------------------------- /// @dev available fTokenTypes for deployment. At least EIP2612Deposits, Permit2Deposits, NativeUnderlying. /// Solidity creates an automatic getter only to fetch at a certain position, so explicitly define a getter that returns all. string[] internal _fTokenTypes; // ----------------------- slot 5 --------------------------- /// @dev fToken creation code for each fTokenType, accessed via SSTORE2. /// maps keccak256(abi.encode(fTokenType)) -> SSTORE2 written creation code for the fToken contract mapping(bytes32 => address) internal _fTokenCreationCodePointers; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(IFluidLiquidity liquidity_, address owner_) Owned(owner_) { if (owner_ == address(0)) { // Owned does not have a zero check for owner_ revert FluidLendingError(ErrorTypes.LendingFactory__ZeroAddress); } LIQUIDITY = liquidity_; } /// @inheritdoc IFluidLendingFactory function allTokens() public view returns (address[] memory) { return _allTokens; } /// @inheritdoc IFluidLendingFactory function fTokenTypes() public view returns (string[] memory) { return _fTokenTypes; } /// @inheritdoc IFluidLendingFactory function fTokenCreationCode(string memory fTokenType_) public view returns (bytes memory) { address creationCodePointer_ = _fTokenCreationCodePointers[keccak256(abi.encode(fTokenType_))]; return creationCodePointer_ == address(0) ? new bytes(0) : SSTORE2.read(creationCodePointer_); } } abstract contract LendingFactoryAdmin is LendingFactoryVariables, Events { /// @dev validates that an address is not the zero address modifier validAddress(address value_) { if (value_ == address(0)) { revert FluidLendingError(ErrorTypes.LendingFactory__ZeroAddress); } _; } /// @dev validates that msg.sender is auth or owner modifier onlyAuths() { if (!isAuth(msg.sender)) { revert FluidLendingError(ErrorTypes.LendingFactory__Unauthorized); } _; } /// @dev validates that msg.sender is deployer or owner modifier onlyDeployers() { if (!isDeployer(msg.sender)) { revert FluidLendingError(ErrorTypes.LendingFactory__Unauthorized); } _; } /// @inheritdoc IFluidLendingFactoryAdmin function isAuth(address auth_) public view returns (bool) { return auth_ == owner || _auths[auth_] == 1; } /// @inheritdoc IFluidLendingFactoryAdmin function isDeployer(address deployer_) public view returns (bool) { return deployer_ == owner || _deployers[deployer_] == 1; } /// @inheritdoc IFluidLendingFactoryAdmin function setAuth(address auth_, bool allowed_) external onlyOwner validAddress(auth_) { _auths[auth_] = allowed_ ? 1 : 0; emit LogSetAuth(auth_, allowed_); } /// @inheritdoc IFluidLendingFactoryAdmin function setDeployer(address deployer_, bool allowed_) external onlyOwner validAddress(deployer_) { _deployers[deployer_] = allowed_ ? 1 : 0; emit LogSetDeployer(deployer_, allowed_); } /// @inheritdoc IFluidLendingFactoryAdmin function setFTokenCreationCode(string memory fTokenType_, bytes calldata creationCode_) external onlyAuths { uint256 length_ = _fTokenTypes.length; bytes32 fTokenTypeHash_ = keccak256(abi.encode(fTokenType_)); if (creationCode_.length == 0) { // remove any previously stored creation code for `fTokenType_` delete _fTokenCreationCodePointers[keccak256(abi.encode(fTokenType_))]; // remove key from array _fTokenTypes. _fTokenTypes is most likely an array of very few elements, // where setFTokenCreationCode is a rarely called method and the removal of an fTokenType is even more rare. // So gas cost is not really an issue here but even if it were, this should still be cheaper than having // an additional mapping like with an OpenZeppelin EnumerableSet for (uint256 i; i < length_; ++i) { if (keccak256(abi.encode(_fTokenTypes[i])) == fTokenTypeHash_) { _fTokenTypes[i] = _fTokenTypes[length_ - 1]; _fTokenTypes.pop(); break; } } emit LogSetFTokenCreationCode(fTokenType_, address(0)); } else { // write creation code to SSTORE2 pointer and set in mapping address creationCodePointer_ = SSTORE2.write(creationCode_); _fTokenCreationCodePointers[keccak256(abi.encode(fTokenType_))] = creationCodePointer_; // make sure `fTokenType_` is present in array _fTokenTypes bool isPresent_; for (uint256 i; i < length_; ++i) { if (keccak256(abi.encode(_fTokenTypes[i])) == fTokenTypeHash_) { isPresent_ = true; break; } } if (!isPresent_) { _fTokenTypes.push(fTokenType_); } emit LogSetFTokenCreationCode(fTokenType_, creationCodePointer_); } } /// @inheritdoc IFluidLendingFactoryAdmin function createToken( address asset_, string calldata fTokenType_, bool isNativeUnderlying_ ) external validAddress(asset_) onlyDeployers returns (address token_) { address creationCodePointer_ = _fTokenCreationCodePointers[keccak256(abi.encode(fTokenType_))]; if (creationCodePointer_ == address(0)) { revert FluidLendingError(ErrorTypes.LendingFactory__InvalidParams); } bytes32 salt_ = _getSalt(asset_, fTokenType_); if (Address.isContract(CREATE3.getDeployed(salt_))) { // revert if token already exists (Solmate CREATE3 does not check before deploying) revert FluidLendingError(ErrorTypes.LendingFactory__TokenExists); } bytes32 liquidityExchangePricesSlot_ = LiquiditySlotsLink.calculateMappingStorageSlot( LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT, // native underlying always uses the native token at Liquidity, but also supports WETH isNativeUnderlying_ ? _NATIVE_TOKEN_ADDRESS : asset_ ); if (LIQUIDITY.readFromStorage(liquidityExchangePricesSlot_) == 0) { // revert if fToken has not been configured at Liquidity contract yet (exchange prices config) revert FluidLendingError(ErrorTypes.LendingFactory__LiquidityNotConfigured); } // Use CREATE3 for deterministic deployments. Unfortunately it has 55k gas overhead token_ = CREATE3.deploy( salt_, abi.encodePacked( SSTORE2.read(creationCodePointer_), // creation code abi.encode(LIQUIDITY, address(this), asset_) // constructor params ), 0 ); // Add the created token to the allTokens array _allTokens.push(token_); // Emit the TokenCreated event emit LogTokenCreated(token_, asset_, _allTokens.length, fTokenType_); } /*////////////////////////////////////////////////////////////// INTERNAL //////////////////////////////////////////////////////////////*/ /// @dev gets the CREATE3 salt for `asset_` and `fTokenType_` function _getSalt(address asset_, string calldata fTokenType_) internal pure returns (bytes32) { return keccak256(abi.encode(asset_, fTokenType_)); } } /// @title Fluid LendingFactory /// @notice creates Fluid lending protocol fTokens, which are interacting with Fluid Liquidity. /// fTokens are ERC20 & ERC4626 compatible tokens that allow to deposit to Fluid Liquidity to earn interest. /// Tokens are created at a deterministic address (see `computeToken()`), only executable by allow-listed auths. /// @dev Note the deployed token starts out with no config at Liquidity contract. /// This must be done by Liquidity auths in a separate step, otherwise no deposits will be possible. /// This contract is not upgradeable. It supports adding new fToken creation codes for future new fToken types. contract FluidLendingFactory is LendingFactoryVariables, LendingFactoryAdmin { /// @notice initialize liquidity contract address & owner constructor( IFluidLiquidity liquidity_, address owner_ ) validAddress(address(liquidity_)) validAddress(owner) LendingFactoryVariables(liquidity_, owner_) {} /// @inheritdoc IFluidLendingFactory function computeToken(address asset_, string calldata fTokenType_) public view returns (address token_) { return CREATE3.getDeployed(_getSalt(asset_, fTokenType_)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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 * ==== * * [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://diligence.consensys.net/posts/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.5.11/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 pragma solidity 0.8.21; interface IProxy { function setAdmin(address newAdmin_) external; function setDummyImplementation(address newDummyImplementation_) external; function addImplementation(address implementation_, bytes4[] calldata sigs_) external; function removeImplementation(address implementation_) external; function getAdmin() external view returns (address); function getDummyImplementation() external view returns (address); function getImplementationSigs(address impl_) external view returns (bytes4[] memory); function getSigsImplementation(bytes4 sig_) external view returns (address); function readFromStorage(bytes32 slot_) external view returns (uint256 result_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; /// @notice library that helps in reading / working with storage slot data of Fluid Liquidity. /// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual /// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver. library LiquiditySlotsLink { /// @dev storage slot for status at Liquidity uint256 internal constant LIQUIDITY_STATUS_SLOT = 1; /// @dev storage slot for auths mapping at Liquidity uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2; /// @dev storage slot for guardians mapping at Liquidity uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3; /// @dev storage slot for user class mapping at Liquidity uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4; /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5; /// @dev storage slot for rateData mapping at Liquidity uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6; /// @dev storage slot for totalAmounts mapping at Liquidity uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7; /// @dev storage slot for user supply double mapping at Liquidity uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8; /// @dev storage slot for user borrow double mapping at Liquidity uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9; /// @dev storage slot for listed tokens array at Liquidity uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10; // -------------------------------- // @dev stacked uint256 storage slots bits position data for each: // ExchangePricesAndConfig uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0; uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16; uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30; uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44; uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58; uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91; uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155; uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219; uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234; // RateData: uint256 internal constant BITS_RATE_DATA_VERSION = 0; // RateData: V1 uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4; uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20; uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36; uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52; // RateData: V2 uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4; uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20; uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36; uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52; uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68; uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84; // TotalAmounts uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0; uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64; uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128; uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192; // UserSupplyData uint256 internal constant BITS_USER_SUPPLY_MODE = 0; uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1; uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65; uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129; uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162; uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176; uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200; uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255; // UserBorrowData uint256 internal constant BITS_USER_BORROW_MODE = 0; uint256 internal constant BITS_USER_BORROW_AMOUNT = 1; uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65; uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129; uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162; uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176; uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200; uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218; uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255; // -------------------------------- /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_` function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) { return keccak256(abi.encode(key_, slot_)); } /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_` function calculateDoubleMappingStorageSlot( uint256 slot_, address key1_, address key2_ ) internal pure returns (bytes32) { bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_)); return keccak256(abi.encode(key2_, intermediateSlot_)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; abstract contract Structs { struct AddressBool { address addr; bool value; } struct AddressUint256 { address addr; uint256 value; } /// @notice struct to set borrow rate data for version 1 struct RateDataV1Params { /// /// @param token for rate data address token; /// /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100 /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast uint256 kink; /// /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100 /// i.e. constant minimum borrow rate /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then) uint256 rateAtUtilizationZero; /// /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700 uint256 rateAtUtilizationKink; /// /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500 uint256 rateAtUtilizationMax; } /// @notice struct to set borrow rate data for version 2 struct RateDataV2Params { /// /// @param token for rate data address token; /// /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100 /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster uint256 kink1; /// /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100 /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast uint256 kink2; /// /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100 /// i.e. constant minimum borrow rate /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then) uint256 rateAtUtilizationZero; /// /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700 uint256 rateAtUtilizationKink1; /// /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200 uint256 rateAtUtilizationKink2; /// /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100 /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500 uint256 rateAtUtilizationMax; } /// @notice struct to set token config struct TokenConfig { /// /// @param token address address token; /// /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100 uint256 fee; /// /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100 uint256 threshold; } /// @notice struct to set user supply & withdrawal config struct UserSupplyConfig { /// /// @param user address address user; /// /// @param token address address token; /// /// @param mode: 0 = without interest. 1 = with interest uint8 mode; /// /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100 /// Also used to calculate rate at which withdrawal limit should decrease (instant). uint256 expandPercent; /// /// @param expandDuration withdrawal limit expand duration in seconds. /// used to calculate rate together with expandPercent uint256 expandDuration; /// /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount. /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: /// with interest -> raw, without interest -> normal uint256 baseWithdrawalLimit; } /// @notice struct to set user borrow & payback config struct UserBorrowConfig { /// /// @param user address address user; /// /// @param token address address token; /// /// @param mode: 0 = without interest. 1 = with interest uint8 mode; /// /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100 /// Also used to calculate rate at which debt limit should decrease (instant). uint256 expandPercent; /// /// @param expandDuration debt limit expand duration in seconds. /// used to calculate rate together with expandPercent uint256 expandDuration; /// /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place. /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: /// with interest -> raw, without interest -> normal uint256 baseDebtCeiling; /// /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow. /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token: /// with interest -> raw, without interest -> normal uint256 maxDebtCeiling; } }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; import { IProxy } from "../../infiniteProxy/interfaces/iProxy.sol"; import { Structs as AdminModuleStructs } from "../adminModule/structs.sol"; interface IFluidLiquidityAdmin { /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract. /// auths can be helpful in reducing governance overhead where it's not needed. /// @param authsStatus_ array of structs setting allowed status for an address. /// status true => add auth, false => remove auth function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external; /// @notice adds/removes guardians. Only callable by Governance. /// @param guardiansStatus_ array of structs setting allowed status for an address. /// status true => add guardian, false => remove guardian function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external; /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance. /// @param revenueCollector_ new revenue collector address function updateRevenueCollector(address revenueCollector_) external; /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths. /// @param newStatus_ new status /// status = 2 -> pause, status = 1 -> resume. function changeStatus(uint256 newStatus_) external; /// @notice update tokens rate data version 1. Only callable by Auths. /// @param tokensRateData_ array of RateDataV1Params with rate data to set for each token function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external; /// @notice update tokens rate data version 2. Only callable by Auths. /// @param tokensRateData_ array of RateDataV2Params with rate data to set for each token function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external; /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold. /// Only callable by Auths. /// @param tokenConfigs_ contains token address, fee & utilization threshold function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external; /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols. /// Only callable by Auths. /// @param userClasses_ struct array of uint256 value to assign for each user address function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external; /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits. /// Only callable by Auths. /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external; /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits. /// Only callable by Auths. /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external; /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians). /// Only callable by Guardians. /// @param user_ address of user to pause operations for /// @param supplyTokens_ token addresses to pause withdrawals for /// @param borrowTokens_ token addresses to pause borrowings for function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external; /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians). /// Only callable by Guardians. /// @param user_ address of user to unpause operations for /// @param supplyTokens_ token addresses to unpause withdrawals for /// @param borrowTokens_ token addresses to unpause borrowings for function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external; /// @notice collects revenue for tokens to configured revenueCollector address. /// @param tokens_ array of tokens to collect revenue for /// @dev Note that this can revert if token balance is < revenueAmount (utilization > 100%) function collectRevenue(address[] calldata tokens_) external; /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage. /// @param tokens_ tokens to update exchange prices for /// @return supplyExchangePrices_ new supply rates of overall system for each token /// @return borrowExchangePrices_ new borrow rates of overall system for each token function updateExchangePrices( address[] calldata tokens_ ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_); } interface IFluidLiquidityLogic is IFluidLiquidityAdmin { /// @notice Single function which handles supply, withdraw, borrow & payback /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native) /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing /// @param withdrawTo_ if withdrawal then to which address /// @param borrowTo_ if borrow then to which address /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol /// @return memVar3_ updated supplyExchangePrice /// @return memVar4_ updated borrowExchangePrice /// @dev to trigger skipping in / out transfers when in&out amounts balance themselves out (gas optimization): /// - supply(+) == borrow(+), withdraw(-) == payback(-). /// - `withdrawTo_` / `borrowTo_` must be msg.sender (protocol) /// - `callbackData_` MUST be encoded so that "from" address is at last 20 bytes (if this optimization is desired), /// also for native token operations where liquidityCallback is not triggered! /// from address must come at last position if there is more data. I.e. encode like: /// abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end /// so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end. function operate( address token_, int256 supplyAmount_, int256 borrowAmount_, address withdrawTo_, address borrowTo_, bytes calldata callbackData_ ) external payable returns (uint256 memVar3_, uint256 memVar4_); } interface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; abstract contract Error { error FluidLendingError(uint256 errorId_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; library ErrorTypes { /***********************************| | fToken | |__________________________________*/ /// @notice thrown when a deposit amount is too small to increase BigMath stored balance in Liquidity. /// precision of BigMath is 1e12, so if token holds 120_000_000_000 USDC, min amount to make a difference would be 0.1 USDC. /// i.e. user would send a very small deposit which mints no shares -> revert uint256 internal constant fToken__DepositInsignificant = 20001; /// @notice thrown when minimum output amount is not reached, e.g. for minimum shares minted (deposit) or /// minimum assets received (redeem) uint256 internal constant fToken__MinAmountOut = 20002; /// @notice thrown when maximum amount is surpassed, e.g. for maximum shares burned (withdraw) or /// maximum assets input (mint) uint256 internal constant fToken__MaxAmount = 20003; /// @notice thrown when invalid params are sent to a method, e.g. zero address uint256 internal constant fToken__InvalidParams = 20004; /// @notice thrown when an unauthorized caller is trying to execute an auth-protected method uint256 internal constant fToken__Unauthorized = 20005; /// @notice thrown when a with permit / signature method is called from msg.sender that is the owner. /// Should call the method without permit instead if msg.sender is the owner. uint256 internal constant fToken__PermitFromOwnerCall = 20006; /// @notice thrown when a reentrancy is detected. uint256 internal constant fToken__Reentrancy = 20007; /// @notice thrown when _tokenExchangePrice overflows type(uint64).max uint256 internal constant fToken__ExchangePriceOverflow = 20008; /// @notice thrown when msg.sender is not rebalancer uint256 internal constant fToken__NotRebalancer = 20009; /// @notice thrown when rebalance is called with msg.value > 0 for non NativeUnderlying fToken uint256 internal constant fToken__NotNativeUnderlying = 20010; /// @notice thrown when the received new liquidity exchange price is of unexpected value (< than the old one) uint256 internal constant fToken__LiquidityExchangePriceUnexpected = 20011; /***********************************| | fToken Native Underlying | |__________________________________*/ /// @notice thrown when native deposit is called but sent along `msg.value` does not cover the deposit amount uint256 internal constant fTokenNativeUnderlying__TransferInsufficient = 21001; /// @notice thrown when a liquidity callback is called for a native token operation uint256 internal constant fTokenNativeUnderlying__UnexpectedLiquidityCallback = 21002; /***********************************| | Lending Factory | |__________________________________*/ /// @notice thrown when a method is called with invalid params uint256 internal constant LendingFactory__InvalidParams = 22001; /// @notice thrown when the provided input param address is zero uint256 internal constant LendingFactory__ZeroAddress = 22002; /// @notice thrown when the token already exists uint256 internal constant LendingFactory__TokenExists = 22003; /// @notice thrown when the fToken has not yet been configured at Liquidity uint256 internal constant LendingFactory__LiquidityNotConfigured = 22004; /// @notice thrown when an unauthorized caller is trying to execute an auth-protected method uint256 internal constant LendingFactory__Unauthorized = 22005; /***********************************| | Lending Rewards Rate Model | |__________________________________*/ /// @notice thrown when invalid params are given as input uint256 internal constant LendingRewardsRateModel__InvalidParams = 23001; /// @notice thrown when calculated rewards rate is exceeding the maximum rate uint256 internal constant LendingRewardsRateModel__MaxRate = 23002; /// @notice thrown when start is called by any other address other than initiator uint256 internal constant LendingRewardsRateModel__NotTheInitiator = 23003; /// @notice thrown when start is called after the rewards are already started uint256 internal constant LendingRewardsRateModel__AlreadyStarted = 23004; /// @notice thrown when the provided input param address is zero uint256 internal constant LendingRewardsRateModel__ZeroAddress = 23005; }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; import { IFluidLiquidity } from "../../../liquidity/interfaces/iLiquidity.sol"; interface IFluidLendingFactoryAdmin { /// @notice reads if a certain `auth_` address is an allowed auth or not. Owner is auth by default. function isAuth(address auth_) external view returns (bool); /// @notice Sets an address as allowed auth or not. Only callable by owner. /// @param auth_ address to set auth value for /// @param allowed_ bool flag for whether address is allowed as auth or not function setAuth(address auth_, bool allowed_) external; /// @notice reads if a certain `deployer_` address is an allowed deployer or not. Owner is deployer by default. function isDeployer(address deployer_) external view returns (bool); /// @notice Sets an address as allowed deployer or not. Only callable by owner. /// @param deployer_ address to set deployer value for /// @param allowed_ bool flag for whether address is allowed as deployer or not function setDeployer(address deployer_, bool allowed_) external; /// @notice Sets the `creationCode_` bytecode for a certain `fTokenType_`. Only callable by auths. /// @param fTokenType_ the fToken Type used to refer the creation code /// @param creationCode_ contract creation code. can be set to bytes(0) to remove a previously available `fTokenType_` function setFTokenCreationCode(string memory fTokenType_, bytes calldata creationCode_) external; /// @notice creates token for `asset_` for a lending protocol with interest. Only callable by deployers. /// @param asset_ address of the asset /// @param fTokenType_ type of fToken: /// - if it's the native token, it should use `NativeUnderlying` /// - otherwise it should use `fToken` /// - could be more types available, check `fTokenTypes()` /// @param isNativeUnderlying_ flag to signal fToken type that uses native underlying at Liquidity /// @return token_ address of the created token function createToken( address asset_, string calldata fTokenType_, bool isNativeUnderlying_ ) external returns (address token_); } interface IFluidLendingFactory is IFluidLendingFactoryAdmin { /// @notice list of all created tokens function allTokens() external view returns (address[] memory); /// @notice list of all fToken types that can be deployed function fTokenTypes() external view returns (string[] memory); /// @notice returns the creation code for a certain `fTokenType_` function fTokenCreationCode(string memory fTokenType_) external view returns (bytes memory); /// @notice address of the Liquidity contract. function LIQUIDITY() external view returns (IFluidLiquidity); /// @notice computes deterministic token address for `asset_` for a lending protocol /// @param asset_ address of the asset /// @param fTokenType_ type of fToken: /// - if it's the native token, it should use `NativeUnderlying` /// - otherwise it should use `fToken` /// - could be more types available, check `fTokenTypes()` /// @return token_ detemrinistic address of the computed token function computeToken(address asset_, string calldata fTokenType_) external view returns (address token_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IFluidLendingFactory } from "../interfaces/iLendingFactory.sol"; abstract contract Events { /// @notice emitted when a new fToken is created event LogTokenCreated(address indexed token, address indexed asset, uint256 indexed count, string fTokenType); /// @notice emitted when an auth is modified by owner event LogSetAuth(address indexed auth, bool indexed allowed); /// @notice emitted when a deployer is modified by owner event LogSetDeployer(address indexed deployer, bool indexed allowed); /// @notice emitted when the creation code for an fTokenType is set event LogSetFTokenCreationCode(string indexed fTokenType, address indexed creationCodePointer); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// 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(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Read and write to persistent storage at a fraction of the cost. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol) /// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol) library SSTORE2 { uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called. /*////////////////////////////////////////////////////////////// WRITE LOGIC //////////////////////////////////////////////////////////////*/ function write(bytes memory data) internal returns (address pointer) { // Prefix the bytecode with a STOP opcode to ensure it cannot be called. bytes memory runtimeCode = abi.encodePacked(hex"00", data); bytes memory creationCode = abi.encodePacked( //---------------------------------------------------------------------------------------------------------------// // Opcode | Opcode + Arguments | Description | Stack View // //---------------------------------------------------------------------------------------------------------------// // 0x60 | 0x600B | PUSH1 11 | codeOffset // // 0x59 | 0x59 | MSIZE | 0 codeOffset // // 0x81 | 0x81 | DUP2 | codeOffset 0 codeOffset // // 0x38 | 0x38 | CODESIZE | codeSize codeOffset 0 codeOffset // // 0x03 | 0x03 | SUB | (codeSize - codeOffset) 0 codeOffset // // 0x80 | 0x80 | DUP | (codeSize - codeOffset) (codeSize - codeOffset) 0 codeOffset // // 0x92 | 0x92 | SWAP3 | codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) // // 0x59 | 0x59 | MSIZE | 0 codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) // // 0x39 | 0x39 | CODECOPY | 0 (codeSize - codeOffset) // // 0xf3 | 0xf3 | RETURN | // //---------------------------------------------------------------------------------------------------------------// hex"60_0B_59_81_38_03_80_92_59_39_F3", // Returns all code in the contract except for the first 11 (0B in hex) bytes. runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit. ); /// @solidity memory-safe-assembly assembly { // Deploy a new contract with the generated creation code. // We start 32 bytes into the code to avoid copying the byte length. pointer := create(0, add(creationCode, 32), mload(creationCode)) } require(pointer != address(0), "DEPLOYMENT_FAILED"); } /*////////////////////////////////////////////////////////////// READ LOGIC //////////////////////////////////////////////////////////////*/ function read(address pointer) internal view returns (bytes memory) { return readBytecode(pointer, DATA_OFFSET, pointer.code.length - DATA_OFFSET); } function read(address pointer, uint256 start) internal view returns (bytes memory) { start += DATA_OFFSET; return readBytecode(pointer, start, pointer.code.length - start); } function read( address pointer, uint256 start, uint256 end ) internal view returns (bytes memory) { start += DATA_OFFSET; end += DATA_OFFSET; require(pointer.code.length >= end, "OUT_OF_BOUNDS"); return readBytecode(pointer, start, end - start); } /*////////////////////////////////////////////////////////////// INTERNAL HELPER LOGIC //////////////////////////////////////////////////////////////*/ function readBytecode( address pointer, uint256 start, uint256 size ) private view returns (bytes memory data) { /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. data := mload(0x40) // Update the free memory pointer to prevent overriding our data. // We use and(x, not(31)) as a cheaper equivalent to sub(x, mod(x, 32)). // Adding 31 to size and running the result through the logic above ensures // the memory pointer remains word-aligned, following the Solidity convention. mstore(0x40, add(data, and(add(add(size, 32), 31), not(31)))) // Store the size of the data in the first 32 byte chunk of free memory. mstore(data, size) // Copy the code into memory right after the 32 bytes we used to store the size. extcodecopy(pointer, add(data, 32), start, size) } } }
{ "optimizer": { "enabled": true, "runs": 10000000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IFluidLiquidity","name":"liquidity_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidLendingError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"auth","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"}],"name":"LogSetAuth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"}],"name":"LogSetDeployer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"fTokenType","type":"string"},{"indexed":true,"internalType":"address","name":"creationCodePointer","type":"address"}],"name":"LogSetFTokenCreationCode","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint256","name":"count","type":"uint256"},{"indexed":false,"internalType":"string","name":"fTokenType","type":"string"}],"name":"LogTokenCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"LIQUIDITY","outputs":[{"internalType":"contract IFluidLiquidity","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"string","name":"fTokenType_","type":"string"}],"name":"computeToken","outputs":[{"internalType":"address","name":"token_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"},{"internalType":"string","name":"fTokenType_","type":"string"},{"internalType":"bool","name":"isNativeUnderlying_","type":"bool"}],"name":"createToken","outputs":[{"internalType":"address","name":"token_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"fTokenType_","type":"string"}],"name":"fTokenCreationCode","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fTokenTypes","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auth_","type":"address"}],"name":"isAuth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer_","type":"address"}],"name":"isDeployer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auth_","type":"address"},{"internalType":"bool","name":"allowed_","type":"bool"}],"name":"setAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"deployer_","type":"address"},{"internalType":"bool","name":"allowed_","type":"bool"}],"name":"setDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"fTokenType_","type":"string"},{"internalType":"bytes","name":"creationCode_","type":"bytes"}],"name":"setFTokenCreationCode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620022173803806200221783398101604081905262000034916200013d565b600080546001600160a01b0319166001600160a01b03831690811782556040518492849283929091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b038116620000b45760405163694bda1d60e01b81526155f260048201526024015b60405180910390fd5b506001600160a01b0390811660805282908116620000ea5760405163694bda1d60e01b81526155f26004820152602401620000ab565b6000546001600160a01b0316806200011a5760405163694bda1d60e01b81526155f26004820152602401620000ab565b505050506200017c565b6001600160a01b03811681146200013a57600080fd5b50565b600080604083850312156200015157600080fd5b82516200015e8162000124565b6020840151909250620001718162000124565b809150509250929050565b608051612071620001a660003960008181610126015281816109f50152610ada01526120716000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c8063a34b5ee81161008c578063dd179e3b11610066578063dd179e3b146101fb578063e78e049a14610210578063f2fde38b14610223578063f60150791461023657600080fd5b8063a34b5ee8146101b5578063bb4a64d3146101c8578063c949aea6146101db57600080fd5b806350c358a4116100bd57806350c358a41461016d5780636ff97f1d146101805780638da5cb5b1461019557600080fd5b80630b44a218146100e45780632520e7ff146100f95780632861c7d114610121575b600080fd5b6100f76100f2366004611655565b610249565b005b61010c610107366004611688565b61038d565b60405190151581526020015b60405180910390f35b6101487f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610118565b61010c61017b366004611688565b6103e3565b610188610434565b60405161011891906116a3565b6000546101489073ffffffffffffffffffffffffffffffffffffffff1681565b6100f76101c3366004611655565b6104a3565b6101486101d6366004611746565b6105e2565b6101ee6101e9366004611873565b6105ff565b6040516101189190611916565b61020361069f565b6040516101189190611929565b61014861021e3660046119a9565b610778565b6100f7610231366004611688565b610c29565b6100f7610244366004611a0e565b610d1a565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff8116610321576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f260048201526024016102c6565b8161032d576000610330565b60015b73ffffffffffffffffffffffffffffffffffffffff841660008181526001602052604080822060ff949094169093559151841515927f014b54fa6d2080e9aacd1c598c7689a625610d7d684dd41d10407e48aa8b120091a3505050565b6000805473ffffffffffffffffffffffffffffffffffffffff838116911614806103dd575073ffffffffffffffffffffffffffffffffffffffff8216600090815260016020819052604090912054145b92915050565b6000805473ffffffffffffffffffffffffffffffffffffffff838116911614806103dd57505073ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460011490565b6060600380548060200260200160405190810160405280929190818152602001828054801561049957602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161046e575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610524576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102c6565b8173ffffffffffffffffffffffffffffffffffffffff8116610576576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f260048201526024016102c6565b81610582576000610585565b60015b73ffffffffffffffffffffffffffffffffffffffff841660008181526002602052604080822060ff949094169093559151841515927f48cc5b4660fae22eabe5e803ee595e63572773d114bcd54ecc118c1efa8d75af91a3505050565b60006105f76105f2858585611111565b611147565b949350505050565b6060600060056000846040516020016106189190611916565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120835290820192909252016000205473ffffffffffffffffffffffffffffffffffffffff169050801561068857610683816112ad565b610698565b6040805160008152602081019091525b9392505050565b60606004805480602002602001604051908101604052809291908181526020016000905b8282101561076f5783829060005260206000200180546106e290611a6a565b80601f016020809104026020016040519081016040528092919081815260200182805461070e90611a6a565b801561075b5780601f106107305761010080835404028352916020019161075b565b820191906000526020600020905b81548152906001019060200180831161073e57829003601f168201915b5050505050815260200190600101906106c3565b50505050905090565b60008473ffffffffffffffffffffffffffffffffffffffff81166107cc576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f260048201526024016102c6565b6107d5336103e3565b61080f576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f560048201526024016102c6565b6000600560008787604051602001610828929190611b06565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120835290820192909252016000205473ffffffffffffffffffffffffffffffffffffffff169050806108bf576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f160048201526024016102c6565b60006108cc888888611111565b90506108f66108da82611147565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b15610931576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f360048201526024016102c6565b60006109c3600587610981576040805173ffffffffffffffffffffffffffffffffffffffff8d16602080830191909152818301939093528151808203830181526060909101909152805191012090565b6040805173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee602080830191909152818301939093528151808203830181526060909101909152805191012090565b6040517fb5c736e4000000000000000000000000000000000000000000000000000000008152600481018290529091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa158015610a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a759190611b1a565b600003610ab2576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f460048201526024016102c6565b610b6582610abf856112ad565b6040805173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301523092820192909252908d166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052610b4f9291602001611b33565b60405160208183030381529060405260006112db565b6003805460018101825560008290527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255915460405193985092908c1691907f60c8487fc242a40cc8d2722cf9b3b5a14b316a50bf4ed30c9f0f1b0126728a3690610c15908d908d90611b06565b60405180910390a450505050949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610caa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102c6565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b610d233361038d565b610d5d576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f560048201526024016102c6565b600454604051600090610d74908690602001611916565b60405160208183030381529060405280519060200120905083839050600003610f45576005600086604051602001610dac9190611916565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012083529082019290925201600090812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b82811015610efe578160048281548110610e3457610e34611b62565b90600052602060002001604051602001610e4e9190611b91565b6040516020818303038152906040528051906020012003610eee576004610e76600185611c69565b81548110610e8657610e86611b62565b9060005260206000200160048281548110610ea357610ea3611b62565b906000526020600020019081610eb99190611ccb565b506004805480610ecb57610ecb611e02565b600190038181906000526020600020016000610ee791906115c6565b9055610efe565b610ef781611e31565b9050610e18565b50604051600090610f10908790611e69565b604051908190038120907f93dad940f342b3cd95007806ae0cb0c162dbbfba54d55223bc6d055c62e608e090600090a361110a565b6000610f8685858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114ad92505050565b9050806005600088604051602001610f9e9190611916565b60405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000805b8481101561106e57836004828154811061102057611020611b62565b9060005260206000200160405160200161103a9190611b91565b604051602081830303815290604052805190602001200361105e576001915061106e565b61106781611e31565b9050611004565b50806110b257600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b016110b08882611e85565b505b8173ffffffffffffffffffffffffffffffffffffffff16876040516110d79190611e69565b604051908190038120907f93dad940f342b3cd95007806ae0cb0c162dbbfba54d55223bc6d055c62e608e090600090a350505b5050505050565b600083838360405160200161112893929190611f97565b6040516020818303038152906040528051906020012090509392505050565b604080518082018252601081527f67363d3d37363d34f03d5260086018f30000000000000000000000000000000060209182015290517fff00000000000000000000000000000000000000000000000000000000000000918101919091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b166021820152603581018290527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f60558201526000908190611223906075015b6040516020818303038152906040528051906020012090565b6040517fd69400000000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660228201527f010000000000000000000000000000000000000000000000000000000000000060368201529091506106989060370161120a565b60606103dd8260016112d68173ffffffffffffffffffffffffffffffffffffffff84163b611c69565b611585565b6000806040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000858251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff81166113a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4445504c4f594d454e545f4641494c454400000000000000000000000000000060448201526064016102c6565b6113aa86611147565b925060008173ffffffffffffffffffffffffffffffffffffffff1685876040516113d49190611e69565b60006040518083038185875af1925050503d8060008114611411576040519150601f19603f3d011682016040523d82523d6000602084013e611416565b606091505b5050905080801561143d575073ffffffffffffffffffffffffffffffffffffffff84163b15155b6114a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f494e495449414c495a4154494f4e5f4641494c4544000000000000000000000060448201526064016102c6565b5050509392505050565b600080826040516020016114c19190611fd0565b60405160208183030381529060405290506000816040516020016114e59190611ff6565b60405160208183030381529060405290508051602082016000f0925073ffffffffffffffffffffffffffffffffffffffff831661157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4445504c4f594d454e545f4641494c454400000000000000000000000000000060448201526064016102c6565b5050919050565b60408051603f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101909152818152818360208301863c9392505050565b5080546115d290611a6a565b6000825580601f106115e2575050565b601f0160209004906000526020600020908101906116009190611603565b50565b5b808211156116185760008155600101611604565b5090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461164057600080fd5b919050565b8035801515811461164057600080fd5b6000806040838503121561166857600080fd5b6116718361161c565b915061167f60208401611645565b90509250929050565b60006020828403121561169a57600080fd5b6106988261161c565b6020808252825182820181905260009190848201906040850190845b818110156116f157835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016116bf565b50909695505050505050565b60008083601f84011261170f57600080fd5b50813567ffffffffffffffff81111561172757600080fd5b60208301915083602082850101111561173f57600080fd5b9250929050565b60008060006040848603121561175b57600080fd5b6117648461161c565b9250602084013567ffffffffffffffff81111561178057600080fd5b61178c868287016116fd565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126117d957600080fd5b813567ffffffffffffffff808211156117f4576117f4611799565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561183a5761183a611799565b8160405283815286602085880101111561185357600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561188557600080fd5b813567ffffffffffffffff81111561189c57600080fd5b6105f7848285016117c8565b60005b838110156118c35781810151838201526020016118ab565b50506000910152565b600081518084526118e48160208601602086016118a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061069860208301846118cc565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561199c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261198a8583516118cc565b94509285019290850190600101611950565b5092979650505050505050565b600080600080606085870312156119bf57600080fd5b6119c88561161c565b9350602085013567ffffffffffffffff8111156119e457600080fd5b6119f0878288016116fd565b9094509250611a03905060408601611645565b905092959194509250565b600080600060408486031215611a2357600080fd5b833567ffffffffffffffff80821115611a3b57600080fd5b611a47878388016117c8565b94506020860135915080821115611a5d57600080fd5b5061178c868287016116fd565b600181811c90821680611a7e57607f821691505b602082108103611ab7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815260006105f7602083018486611abd565b600060208284031215611b2c57600080fd5b5051919050565b60008351611b458184602088016118a8565b835190830190611b598183602088016118a8565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602080835260008454611ba581611a6a565b80848701526040600180841660008114611bc65760018114611bfe57611c2c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611c2c565b896000528660002060005b85811015611c245781548b8201860152908301908801611c09565b8a0184019650505b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156103dd576103dd611c3a565b601f821115611cc657600081815260208120601f850160051c81016020861015611ca35750805b601f850160051c820191505b81811015611cc257828155600101611caf565b5050505b505050565b818103611cd6575050565b611ce08254611a6a565b67ffffffffffffffff811115611cf857611cf8611799565b611d0c81611d068454611a6a565b84611c7c565b6000601f821160018114611d5e5760008315611d285750848201545b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b17845561110a565b6000858152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0841690600086815260209020845b83811015611db65782860154825560019586019590910190602001611d96565b5085831015611df257818501547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611e6257611e62611c3a565b5060010190565b60008251611e7b8184602087016118a8565b9190910192915050565b815167ffffffffffffffff811115611e9f57611e9f611799565b611ead81611d068454611a6a565b602080601f831160018114611f005760008415611eca5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611cc2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611f4d57888601518255948401946001909101908401611f2e565b5085821015611df25793909601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f8600387901b161c19169092555050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff84168152604060208201526000611fc7604083018486611abd565b95945050505050565b6000815260008251611fe98160018501602087016118a8565b9190910160010192915050565b7f600b5981380380925939f300000000000000000000000000000000000000000081526000825161202e81600b8501602087016118a8565b91909101600b019291505056fea2646970667358221220829aaace410b5d4c5716d8dcea71dfcc8c5c561c651a6548ba8b8d3990f3589364736f6c6343000815003300000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4970000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100df5760003560e01c8063a34b5ee81161008c578063dd179e3b11610066578063dd179e3b146101fb578063e78e049a14610210578063f2fde38b14610223578063f60150791461023657600080fd5b8063a34b5ee8146101b5578063bb4a64d3146101c8578063c949aea6146101db57600080fd5b806350c358a4116100bd57806350c358a41461016d5780636ff97f1d146101805780638da5cb5b1461019557600080fd5b80630b44a218146100e45780632520e7ff146100f95780632861c7d114610121575b600080fd5b6100f76100f2366004611655565b610249565b005b61010c610107366004611688565b61038d565b60405190151581526020015b60405180910390f35b6101487f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49781565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610118565b61010c61017b366004611688565b6103e3565b610188610434565b60405161011891906116a3565b6000546101489073ffffffffffffffffffffffffffffffffffffffff1681565b6100f76101c3366004611655565b6104a3565b6101486101d6366004611746565b6105e2565b6101ee6101e9366004611873565b6105ff565b6040516101189190611916565b61020361069f565b6040516101189190611929565b61014861021e3660046119a9565b610778565b6100f7610231366004611688565b610c29565b6100f7610244366004611a0e565b610d1a565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff8116610321576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f260048201526024016102c6565b8161032d576000610330565b60015b73ffffffffffffffffffffffffffffffffffffffff841660008181526001602052604080822060ff949094169093559151841515927f014b54fa6d2080e9aacd1c598c7689a625610d7d684dd41d10407e48aa8b120091a3505050565b6000805473ffffffffffffffffffffffffffffffffffffffff838116911614806103dd575073ffffffffffffffffffffffffffffffffffffffff8216600090815260016020819052604090912054145b92915050565b6000805473ffffffffffffffffffffffffffffffffffffffff838116911614806103dd57505073ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460011490565b6060600380548060200260200160405190810160405280929190818152602001828054801561049957602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161046e575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610524576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102c6565b8173ffffffffffffffffffffffffffffffffffffffff8116610576576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f260048201526024016102c6565b81610582576000610585565b60015b73ffffffffffffffffffffffffffffffffffffffff841660008181526002602052604080822060ff949094169093559151841515927f48cc5b4660fae22eabe5e803ee595e63572773d114bcd54ecc118c1efa8d75af91a3505050565b60006105f76105f2858585611111565b611147565b949350505050565b6060600060056000846040516020016106189190611916565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120835290820192909252016000205473ffffffffffffffffffffffffffffffffffffffff169050801561068857610683816112ad565b610698565b6040805160008152602081019091525b9392505050565b60606004805480602002602001604051908101604052809291908181526020016000905b8282101561076f5783829060005260206000200180546106e290611a6a565b80601f016020809104026020016040519081016040528092919081815260200182805461070e90611a6a565b801561075b5780601f106107305761010080835404028352916020019161075b565b820191906000526020600020905b81548152906001019060200180831161073e57829003601f168201915b5050505050815260200190600101906106c3565b50505050905090565b60008473ffffffffffffffffffffffffffffffffffffffff81166107cc576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f260048201526024016102c6565b6107d5336103e3565b61080f576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f560048201526024016102c6565b6000600560008787604051602001610828929190611b06565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120835290820192909252016000205473ffffffffffffffffffffffffffffffffffffffff169050806108bf576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f160048201526024016102c6565b60006108cc888888611111565b90506108f66108da82611147565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b15610931576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f360048201526024016102c6565b60006109c3600587610981576040805173ffffffffffffffffffffffffffffffffffffffff8d16602080830191909152818301939093528151808203830181526060909101909152805191012090565b6040805173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee602080830191909152818301939093528151808203830181526060909101909152805191012090565b6040517fb5c736e4000000000000000000000000000000000000000000000000000000008152600481018290529091507f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49773ffffffffffffffffffffffffffffffffffffffff169063b5c736e490602401602060405180830381865afa158015610a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a759190611b1a565b600003610ab2576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f460048201526024016102c6565b610b6582610abf856112ad565b6040805173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497811660208301523092820192909252908d166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052610b4f9291602001611b33565b60405160208183030381529060405260006112db565b6003805460018101825560008290527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255915460405193985092908c1691907f60c8487fc242a40cc8d2722cf9b3b5a14b316a50bf4ed30c9f0f1b0126728a3690610c15908d908d90611b06565b60405180910390a450505050949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610caa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102c6565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b610d233361038d565b610d5d576040517f694bda1d0000000000000000000000000000000000000000000000000000000081526155f560048201526024016102c6565b600454604051600090610d74908690602001611916565b60405160208183030381529060405280519060200120905083839050600003610f45576005600086604051602001610dac9190611916565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012083529082019290925201600090812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b82811015610efe578160048281548110610e3457610e34611b62565b90600052602060002001604051602001610e4e9190611b91565b6040516020818303038152906040528051906020012003610eee576004610e76600185611c69565b81548110610e8657610e86611b62565b9060005260206000200160048281548110610ea357610ea3611b62565b906000526020600020019081610eb99190611ccb565b506004805480610ecb57610ecb611e02565b600190038181906000526020600020016000610ee791906115c6565b9055610efe565b610ef781611e31565b9050610e18565b50604051600090610f10908790611e69565b604051908190038120907f93dad940f342b3cd95007806ae0cb0c162dbbfba54d55223bc6d055c62e608e090600090a361110a565b6000610f8685858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114ad92505050565b9050806005600088604051602001610f9e9190611916565b60405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000805b8481101561106e57836004828154811061102057611020611b62565b9060005260206000200160405160200161103a9190611b91565b604051602081830303815290604052805190602001200361105e576001915061106e565b61106781611e31565b9050611004565b50806110b257600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b016110b08882611e85565b505b8173ffffffffffffffffffffffffffffffffffffffff16876040516110d79190611e69565b604051908190038120907f93dad940f342b3cd95007806ae0cb0c162dbbfba54d55223bc6d055c62e608e090600090a350505b5050505050565b600083838360405160200161112893929190611f97565b6040516020818303038152906040528051906020012090509392505050565b604080518082018252601081527f67363d3d37363d34f03d5260086018f30000000000000000000000000000000060209182015290517fff00000000000000000000000000000000000000000000000000000000000000918101919091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b166021820152603581018290527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f60558201526000908190611223906075015b6040516020818303038152906040528051906020012090565b6040517fd69400000000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660228201527f010000000000000000000000000000000000000000000000000000000000000060368201529091506106989060370161120a565b60606103dd8260016112d68173ffffffffffffffffffffffffffffffffffffffff84163b611c69565b611585565b6000806040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000858251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff81166113a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4445504c4f594d454e545f4641494c454400000000000000000000000000000060448201526064016102c6565b6113aa86611147565b925060008173ffffffffffffffffffffffffffffffffffffffff1685876040516113d49190611e69565b60006040518083038185875af1925050503d8060008114611411576040519150601f19603f3d011682016040523d82523d6000602084013e611416565b606091505b5050905080801561143d575073ffffffffffffffffffffffffffffffffffffffff84163b15155b6114a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f494e495449414c495a4154494f4e5f4641494c4544000000000000000000000060448201526064016102c6565b5050509392505050565b600080826040516020016114c19190611fd0565b60405160208183030381529060405290506000816040516020016114e59190611ff6565b60405160208183030381529060405290508051602082016000f0925073ffffffffffffffffffffffffffffffffffffffff831661157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4445504c4f594d454e545f4641494c454400000000000000000000000000000060448201526064016102c6565b5050919050565b60408051603f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101909152818152818360208301863c9392505050565b5080546115d290611a6a565b6000825580601f106115e2575050565b601f0160209004906000526020600020908101906116009190611603565b50565b5b808211156116185760008155600101611604565b5090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461164057600080fd5b919050565b8035801515811461164057600080fd5b6000806040838503121561166857600080fd5b6116718361161c565b915061167f60208401611645565b90509250929050565b60006020828403121561169a57600080fd5b6106988261161c565b6020808252825182820181905260009190848201906040850190845b818110156116f157835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016116bf565b50909695505050505050565b60008083601f84011261170f57600080fd5b50813567ffffffffffffffff81111561172757600080fd5b60208301915083602082850101111561173f57600080fd5b9250929050565b60008060006040848603121561175b57600080fd5b6117648461161c565b9250602084013567ffffffffffffffff81111561178057600080fd5b61178c868287016116fd565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126117d957600080fd5b813567ffffffffffffffff808211156117f4576117f4611799565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561183a5761183a611799565b8160405283815286602085880101111561185357600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006020828403121561188557600080fd5b813567ffffffffffffffff81111561189c57600080fd5b6105f7848285016117c8565b60005b838110156118c35781810151838201526020016118ab565b50506000910152565b600081518084526118e48160208601602086016118a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061069860208301846118cc565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561199c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261198a8583516118cc565b94509285019290850190600101611950565b5092979650505050505050565b600080600080606085870312156119bf57600080fd5b6119c88561161c565b9350602085013567ffffffffffffffff8111156119e457600080fd5b6119f0878288016116fd565b9094509250611a03905060408601611645565b905092959194509250565b600080600060408486031215611a2357600080fd5b833567ffffffffffffffff80821115611a3b57600080fd5b611a47878388016117c8565b94506020860135915080821115611a5d57600080fd5b5061178c868287016116fd565b600181811c90821680611a7e57607f821691505b602082108103611ab7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815260006105f7602083018486611abd565b600060208284031215611b2c57600080fd5b5051919050565b60008351611b458184602088016118a8565b835190830190611b598183602088016118a8565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602080835260008454611ba581611a6a565b80848701526040600180841660008114611bc65760018114611bfe57611c2c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611c2c565b896000528660002060005b85811015611c245781548b8201860152908301908801611c09565b8a0184019650505b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156103dd576103dd611c3a565b601f821115611cc657600081815260208120601f850160051c81016020861015611ca35750805b601f850160051c820191505b81811015611cc257828155600101611caf565b5050505b505050565b818103611cd6575050565b611ce08254611a6a565b67ffffffffffffffff811115611cf857611cf8611799565b611d0c81611d068454611a6a565b84611c7c565b6000601f821160018114611d5e5760008315611d285750848201545b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b17845561110a565b6000858152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0841690600086815260209020845b83811015611db65782860154825560019586019590910190602001611d96565b5085831015611df257818501547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611e6257611e62611c3a565b5060010190565b60008251611e7b8184602087016118a8565b9190910192915050565b815167ffffffffffffffff811115611e9f57611e9f611799565b611ead81611d068454611a6a565b602080601f831160018114611f005760008415611eca5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611cc2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611f4d57888601518255948401946001909101908401611f2e565b5085821015611df25793909601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f8600387901b161c19169092555050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff84168152604060208201526000611fc7604083018486611abd565b95945050505050565b6000815260008251611fe98160018501602087016118a8565b9190910160010192915050565b7f600b5981380380925939f300000000000000000000000000000000000000000081526000825161202e81600b8501602087016118a8565b91909101600b019291505056fea2646970667358221220829aaace410b5d4c5716d8dcea71dfcc8c5c561c651a6548ba8b8d3990f3589364736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4970000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e
-----Decoded View---------------
Arg [0] : liquidity_ (address): 0x52Aa899454998Be5b000Ad077a46Bbe360F4e497
Arg [1] : owner_ (address): 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497
Arg [1] : 0000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.