S Price: $0.504726 (+0.68%)

Contract

0x4EC7b668BAF70d4A4b0FC7941a7708A07b6d45Be

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
4930842024-12-16 20:46:33109 days ago1734381993  Contract Creation0 S
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FluidContractFactory

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
paris EvmVersion
File 1 of 3 : main.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { Owned } from "solmate/src/auth/Owned.sol";

import { AddressCalcs } from "../libraries/addressCalcs.sol";

/// @title FluidContractFactory
/// @notice A contract that allows deployers to deploy any contract by passing the contract data in bytes
/// @dev The main objective of this contract is to avoid storing contract addresses in our protocols which requires 160 bits of storage
///      Instead, we can just store the nonce & deployment of this address to calculate the address realtime using "AddressCalcs" library
contract FluidContractFactory is Owned {
    /// @notice Thrown when an invalid operation is attempted
    error FluidContractFactory__InvalidOperation();

    /// @notice Emitted when a new contract is deployed
    /// @param addr The address of the deployed contract
    /// @param nonce The nonce used for deployment
    event LogContractDeployed(address indexed addr, uint256 indexed nonce);

    /// @notice Emitted when a deployer's count is updated
    /// @param deployer The address of the deployer
    /// @param count The new count for the deployer
    event LogUpdateDeployer(address indexed deployer, uint16 indexed count);

    /// @notice Mapping to store the deployment count for each deployer
    mapping(address => uint16) public deployer;

    /// @notice total number of contracts deployed
    uint256 public totalContracts;

    /// @notice Constructor to initialize the contract
    /// @param owner_ The address of the contract owner
    constructor(address owner_) Owned(owner_) {}

    /// @notice Updates the allowed deployments count for a specific deployer
    /// @param deployer_ The address of the deployer
    /// @param count_ The new count for the deployer
    /// @dev Only callable by the contract owner
    function updateDeployer(address deployer_, uint16 count_) public onlyOwner {
        deployer[deployer_] = count_;
        emit LogUpdateDeployer(deployer_, count_);
    }

    /// @notice Deploys a new contract
    /// @param contractCode_ The bytecode of the contract to deploy
    /// @return contractAddress_ The address of the deployed contract
    /// @dev Decrements the deployer's allowed deployments count if not the owner
    function deployContract(bytes calldata contractCode_) external returns (address contractAddress_) {
        if (msg.sender != owner) {
            // if deployer count is 0 then it'll underflow and hence solidity will throw error
            deployer[msg.sender] -= 1;
        }

        uint256 nonce_ = ++totalContracts;

        // compute contract address for nonce.
        contractAddress_ = getContractAddress(nonce_);

        if (contractAddress_ != _deploy(contractCode_)) {
            revert FluidContractFactory__InvalidOperation();
        }

        emit LogContractDeployed(contractAddress_, nonce_);
    }

    /// @notice Calculates the address of a contract for a given nonce
    /// @param nonce_ The nonce to use for address calculation
    /// @return contractAddress_ The calculated contract address
    function getContractAddress(uint256 nonce_) public view returns (address contractAddress_) {
        return AddressCalcs.addressCalc(address(this), nonce_);
    }

    /// @notice Internal function to deploy a contract
    /// @param bytecode_ The bytecode of the contract to deploy
    /// @return address_ The address of the deployed contract
    /// @dev Uses inline assembly for efficient deployment
    function _deploy(bytes memory bytecode_) internal returns (address address_) {
        if (bytecode_.length == 0) {
            revert FluidContractFactory__InvalidOperation();
        }
        /// @solidity memory-safe-assembly
        assembly {
            address_ := create(0, add(bytecode_, 0x20), mload(bytecode_))
        }
        if (address_ == address(0)) {
            revert FluidContractFactory__InvalidOperation();
        }
    }
}

File 2 of 3 : addressCalcs.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

/// @notice implements calculation of address for contracts deployed through CREATE.
/// Accepts contract deployed from which address & nonce
library AddressCalcs {

    /// @notice                         Computes the address of a contract based
    /// @param deployedFrom_            Address from which the contract was deployed
    /// @param nonce_                   Nonce at which the contract was deployed
    /// @return contract_               Address of deployed contract
    function addressCalc(address deployedFrom_, uint nonce_) internal pure returns (address contract_) {
        // @dev based on https://ethereum.stackexchange.com/a/61413

        // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment
        // hence, nonce of vault deployment starts with 1.
        bytes memory data;
        if (nonce_ == 0x00) {
            return address(0);
        } else if (nonce_ <= 0x7f) {
            data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployedFrom_, uint8(nonce_));
        } else if (nonce_ <= 0xff) {
            data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployedFrom_, bytes1(0x81), uint8(nonce_));
        } else if (nonce_ <= 0xffff) {
            data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployedFrom_, bytes1(0x82), uint16(nonce_));
        } else if (nonce_ <= 0xffffff) {
            data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployedFrom_, bytes1(0x83), uint24(nonce_));
        } else {
            data = abi.encodePacked(bytes1(0xda), bytes1(0x94), deployedFrom_, bytes1(0x84), uint32(nonce_));
        }

        return address(uint160(uint256(keccak256(data))));
    }

}

File 3 of 3 : Owned.sol
// 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);
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FluidContractFactory__InvalidOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"LogContractDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":true,"internalType":"uint16","name":"count","type":"uint16"}],"name":"LogUpdateDeployer","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":[{"internalType":"bytes","name":"contractCode_","type":"bytes"}],"name":"deployContract","outputs":[{"internalType":"address","name":"contractAddress_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deployer","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"}],"name":"getContractAddress","outputs":[{"internalType":"address","name":"contractAddress_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalContracts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"deployer_","type":"address"},{"internalType":"uint16","name":"count_","type":"uint16"}],"name":"updateDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50604051610c72380380610c7283398101604081905261002f9161007e565b600080546001600160a01b0319166001600160a01b03831690811782556040518392907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350506100ae565b60006020828403121561009057600080fd5b81516001600160a01b03811681146100a757600080fd5b9392505050565b610bb5806100bd6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a7e042b31161005b578063a7e042b3146100f6578063aefa7d981461010b578063b9caf9d91461011e578063f2fde38b1461015557600080fd5b8063798133dd146100825780638da5cb5b146100bf578063a09037a9146100df575b600080fd5b6100956100903660046109e7565b610168565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6000546100959073ffffffffffffffffffffffffffffffffffffffff1681565b6100e860025481565b6040519081526020016100b6565b610109610104366004610a7d565b6102d9565b005b610095610119366004610abb565b6103e0565b61014261012c366004610ad4565b60016020526000908152604090205461ffff1681565b60405161ffff90911681526020016100b6565b610109610163366004610ad4565b6103f2565b6000805473ffffffffffffffffffffffffffffffffffffffff1633146101c95733600090815260016020819052604082208054919290916101ae90849061ffff16610b25565b92506101000a81548161ffff021916908361ffff1602179055505b60006002600081546101da90610b47565b918290555090506101ea816103e0565b915061022b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104e392505050565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461028f576040517fd1bf1e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051819073ffffffffffffffffffffffffffffffffffffffff8416907f511b2c8f5fa0dbd58000435f9f090fff2fea17afb6a93d4b42269e91fb8122bd90600090a35092915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461035f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661ffff861690811790915590519092917fa31a54a42cb8a0d27fbdc5b388a008e53701c95de4a199f0ff33ac6929cd4e1c91a35050565b60006103ec308361057d565b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610356565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60008151600003610520576040517fd1bf1e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151602083016000f0905073ffffffffffffffffffffffffffffffffffffffff8116610578576040517fd1bf1e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60006060826000036105935760009150506103ec565b607f831161065c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b60405160208183030381529060405290506109d8565b60ff8311610739576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801610646565b61ffff8311610817576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901610646565b62ffffff83116108f6576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01610646565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b80516020909101209392505050565b600080602083850312156109fa57600080fd5b823567ffffffffffffffff80821115610a1257600080fd5b818501915085601f830112610a2657600080fd5b813581811115610a3557600080fd5b866020828501011115610a4757600080fd5b60209290920196919550909350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461057857600080fd5b60008060408385031215610a9057600080fd5b610a9983610a59565b9150602083013561ffff81168114610ab057600080fd5b809150509250929050565b600060208284031215610acd57600080fd5b5035919050565b600060208284031215610ae657600080fd5b610aef82610a59565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff828116828216039080821115610b4057610b40610af6565b5092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7857610b78610af6565b506001019056fea264697066735822122055bc67eade8dc37e2ad0f7629834c10925fdbd79bff5de6072f4b7eda2400a2164736f6c634300081500330000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a7e042b31161005b578063a7e042b3146100f6578063aefa7d981461010b578063b9caf9d91461011e578063f2fde38b1461015557600080fd5b8063798133dd146100825780638da5cb5b146100bf578063a09037a9146100df575b600080fd5b6100956100903660046109e7565b610168565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6000546100959073ffffffffffffffffffffffffffffffffffffffff1681565b6100e860025481565b6040519081526020016100b6565b610109610104366004610a7d565b6102d9565b005b610095610119366004610abb565b6103e0565b61014261012c366004610ad4565b60016020526000908152604090205461ffff1681565b60405161ffff90911681526020016100b6565b610109610163366004610ad4565b6103f2565b6000805473ffffffffffffffffffffffffffffffffffffffff1633146101c95733600090815260016020819052604082208054919290916101ae90849061ffff16610b25565b92506101000a81548161ffff021916908361ffff1602179055505b60006002600081546101da90610b47565b918290555090506101ea816103e0565b915061022b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104e392505050565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461028f576040517fd1bf1e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051819073ffffffffffffffffffffffffffffffffffffffff8416907f511b2c8f5fa0dbd58000435f9f090fff2fea17afb6a93d4b42269e91fb8122bd90600090a35092915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461035f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661ffff861690811790915590519092917fa31a54a42cb8a0d27fbdc5b388a008e53701c95de4a199f0ff33ac6929cd4e1c91a35050565b60006103ec308361057d565b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610356565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60008151600003610520576040517fd1bf1e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151602083016000f0905073ffffffffffffffffffffffffffffffffffffffff8116610578576040517fd1bf1e2d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60006060826000036105935760009150506103ec565b607f831161065c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b60405160208183030381529060405290506109d8565b60ff8311610739576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801610646565b61ffff8311610817576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901610646565b62ffffff83116108f6576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01610646565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b80516020909101209392505050565b600080602083850312156109fa57600080fd5b823567ffffffffffffffff80821115610a1257600080fd5b818501915085601f830112610a2657600080fd5b813581811115610a3557600080fd5b866020828501011115610a4757600080fd5b60209290920196919550909350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461057857600080fd5b60008060408385031215610a9057600080fd5b610a9983610a59565b9150602083013561ffff81168114610ab057600080fd5b809150509250929050565b600060208284031215610acd57600080fd5b5035919050565b600060208284031215610ae657600080fd5b610aef82610a59565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61ffff828116828216039080821115610b4057610b40610af6565b5092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7857610b78610af6565b506001019056fea264697066735822122055bc67eade8dc37e2ad0f7629834c10925fdbd79bff5de6072f4b7eda2400a2164736f6c63430008150033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e

-----Decoded View---------------
Arg [0] : owner_ (address): 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e


Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.