Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xa0CC9B2573dff01B720a31FD9C4E341CF88Ae576
Balance 0 ETH
Nonce 31
Code Size 5202 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

5202 bytes
0x6080604052600436106100dd5760003560e01c8063946d92041161007f578063e1585e4411610059578063e1585e441461020d578063f073cecd1461023b578063f2fde38b1461027b578063f69049661461029b57600080fd5b8063946d9204146101ad578063afb83ce6146101cd578063cd0bcff5146101ed57600080fd5b806373599fd4116100bb57806373599fd4146101495780637ea815e2146101695780638da5cb5b1461017c57806391cb19d61461019a57600080fd5b80633ea05a76146100e25780635211a6af14610112578063715018a614610132575b600080fd5b6100f56100f0366004610eee565b6102bb565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561011e57600080fd5b506100f561012d366004610f9b565b610385565b34801561013e57600080fd5b5061014761046a565b005b34801561015557600080fd5b506100f5610164366004611026565b61047e565b6100f5610177366004610eee565b6104fc565b34801561018857600080fd5b506000546001600160a01b03166100f5565b6100f56101a8366004610f9b565b61056f565b3480156101b957600080fd5b506101476101c836600461108e565b610632565b3480156101d957600080fd5b506101476101e8366004611114565b6106ca565b3480156101f957600080fd5b50610147610208366004611114565b6106de565b34801561021957600080fd5b5061022d61022836600461112f565b6106ef565b604051908152602001610109565b34801561024757600080fd5b5061026b610256366004611114565b60016020526000908152604090205460ff1681565b6040519015158152602001610109565b34801561028757600080fd5b50610147610296366004611114565b61071f565b3480156102a757600080fd5b506100f56102b636600461116c565b61075f565b60006102c7838361076b565b6103156102d760408501856111b1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506060850135610816565b90503415610330576103306001600160a01b03821634610821565b61037e61034060408501856111b1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506060850135610852565b9392505050565b6000610391858561076b565b6103df6103a160408701876111b1565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060608701356108a5565b90506000816001600160a01b031684846040516103fd9291906111f8565b6000604051808303816000865af19150503d806000811461043a576040519150601f19603f3d011682016040523d82523d6000602084013e61043f565b606091505b50509050806104615760405163139c636760e01b815260040160405180910390fd5b50949350505050565b61047261093f565b61047c600061096c565b565b6000308285856040516104929291906111f8565b6040519081900381206104dc9392916020016001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b60408051601f198184030181529190528051602090910120949350505050565b6000610508838361076b565b3415610521576105216001600160a01b03821634610821565b61037e61053160408501856111b1565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060608501356108a5565b600061057b858561076b565b6105c961058b60408701876111b1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506060870135610816565b905034156105e4576105e46001600160a01b03821634610821565b6103df6105f460408701876111b1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506060870135610852565b61063a61093f565b600054600160a01b900460ff16156106645760405162dc149f60e41b815260040160405180910390fd5b6000805460ff60a01b1916600160a01b1790556106808361071f565b8060005b818110156106c3576106bb8484838181106106a1576106a1611208565b90506020020160208101906106b69190611114565b6109c9565b600101610684565b5050505050565b6106d261093f565b6106db81610a4c565b50565b6106e661093f565b6106db816109c9565b600081604051602001610702919061121e565b604051602081830303815290604052805190602001209050919050565b61072761093f565b6001600160a01b03811661075657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6106db8161096c565b600061037e8383610816565b61079d600183604051602001610781919061121e565b6040516020818303038152906040528051906020012083610ac4565b6107aa60408301836111b1565b90506000036107cc57604051633b5e0aeb60e11b815260040160405180910390fd5b42826020013510156107f15760405163559895a360e01b815260040160405180910390fd5b813546146108125760405163029b0df160e41b815260040160405180910390fd5b5050565b600061037e82610b19565b600080600080600085875af190508061084d57604051633d2cec6f60e21b815260040160405180910390fd5b505050565b600061085e8383610bcc565b9050806001600160a01b03168284805190602001207f27b8e3132afa95254770e1c1d214eafde52bc47d1b6e1f5dfcbb380c3ca3f53260405160405180910390a492915050565b600082516000036108c9576040516321744a5960e01b815260040160405180910390fd5b818351602085016000f590506001600160a01b0381166108fc5760405163b4f5411160e01b815260040160405180910390fd5b825160208401206040516001600160a01b0383169184917f27b8e3132afa95254770e1c1d214eafde52bc47d1b6e1f5dfcbb380c3ca3f53290600090a492915050565b6000546001600160a01b0316331461047c5760405163118cdaa760e01b815233600482015260240161074d565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166109f05760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527f0f35112fc04ac27795ba9e631146295f8a5f09f6c4016988f701e7919bdce46f91015b60405180910390a150565b6001600160a01b038116610a735760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527f41913741c8622c4e49c9e9ca9ab043835b44e88899f3572dc5522aaa8f7770549101610a41565b6000610acf83610ce7565b90506000610add8284610d22565b6001600160a01b03811660009081526020879052604090205490915060ff166106c357604051638baa579f60e01b815260040160405180910390fd5b604080516001600160f81b031960208083019190915230606090811b6bffffffffffffffffffffffff19908116602185015260358401959095527f694757ed2e18aa4b69920fbba0b58187ff0f7cd8839db599c0a9ee0351d9958c605580850191909152845180850390910181526075840185528051908301206135a560f21b6095850152901b9093166097820152600160f81b60ab8201528151608c81830301815260ac909101909152805191012090565b6000610bd782610b19565b90508251600003610bfb576040516321744a5960e01b815260040160405180910390fd5b610c0d816001600160a01b0316610da1565b15610c2b5760405163a6ef0ba160e01b815260040160405180910390fd5b600082604051610c3a90610e26565b8190604051809103906000f5905080158015610c5a573d6000803e3d6000fd5b5090506001600160a01b038116610c845760405163b4f5411160e01b815260040160405180910390fd5b6040516203ba1b60e51b81526001600160a01b038216906277436090610cae9087906004016112b6565b600060405180830381600087803b158015610cc857600080fd5b505af1158015610cdc573d6000803e3d6000fd5b505050505092915050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01610702565b600080600080610d3185610de1565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa158015610d8c573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60006001600160a01b0382163f801580159061037e57507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470141592915050565b60008060008351604114610e0857604051634be6321b60e01b815260040160405180910390fd5b50505060208101516040820151606090920151909260009190911a90565b6101418061130583390190565b600060808284031215610e4557600080fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610e7257600080fd5b813567ffffffffffffffff80821115610e8d57610e8d610e4b565b604051601f8301601f19908116603f01168101908282118183101715610eb557610eb5610e4b565b81604052838152866020858801011115610ece57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215610f0157600080fd5b823567ffffffffffffffff80821115610f1957600080fd5b610f2586838701610e33565b93506020850135915080821115610f3b57600080fd5b50610f4885828601610e61565b9150509250929050565b60008083601f840112610f6457600080fd5b50813567ffffffffffffffff811115610f7c57600080fd5b602083019150836020828501011115610f9457600080fd5b9250929050565b60008060008060608587031215610fb157600080fd5b843567ffffffffffffffff80821115610fc957600080fd5b610fd588838901610e33565b95506020870135915080821115610feb57600080fd5b610ff788838901610e61565b9450604087013591508082111561100d57600080fd5b5061101a87828801610f52565b95989497509550505050565b60008060006040848603121561103b57600080fd5b833567ffffffffffffffff81111561105257600080fd5b61105e86828701610f52565b909790965060209590950135949350505050565b80356001600160a01b038116811461108957600080fd5b919050565b6000806000604084860312156110a357600080fd5b6110ac84611072565b9250602084013567ffffffffffffffff808211156110c957600080fd5b818601915086601f8301126110dd57600080fd5b8135818111156110ec57600080fd5b8760208260051b850101111561110157600080fd5b6020830194508093505050509250925092565b60006020828403121561112657600080fd5b61037e82611072565b60006020828403121561114157600080fd5b813567ffffffffffffffff81111561115857600080fd5b61116484828501610e33565b949350505050565b6000806040838503121561117f57600080fd5b823567ffffffffffffffff81111561119657600080fd5b6111a285828601610e61565b95602094909401359450505050565b6000808335601e198436030181126111c857600080fd5b83018035915067ffffffffffffffff8211156111e357600080fd5b602001915036819003821315610f9457600080fd5b8183823760009101908152919050565b634e487b7160e01b600052603260045260246000fd5b60208152813560208201526020820135604082015260006040830135601e1984360301811261124c57600080fd5b830160208101903567ffffffffffffffff81111561126957600080fd5b80360382131561127857600080fd5b608060608501528060a0850152808260c0860137600060c082860101526060850135608085015260c0601f19601f8301168501019250505092915050565b600060208083528351808285015260005b818110156112e3578581018301518582016040015282016112c7565b506000604082860101526040601f19601f830116850101925050509291505056fe608060405234801561001057600080fd5b50610121806100206000396000f3fe60806040526004361061001d5760003560e01c806277436014610022575b600080fd5b610035610030366004610063565b610037565b005b8051602082016000f061004957600080fd5b6000ff5b634e487b7160e01b600052604160045260246000fd5b60006020828403121561007557600080fd5b813567ffffffffffffffff8082111561008d57600080fd5b818401915084601f8301126100a157600080fd5b8135818111156100b3576100b361004d565b604051601f8201601f19908116603f011681019083821181831017156100db576100db61004d565b816040528281528760208487010111156100f457600080fd5b82602086016020830137600092810160200192909252509594505050505056fea164736f6c6343000814000aa164736f6c6343000814000a

Verified Source Code Partial Match

Compiler: v0.8.20+commit.a1b79de6 EVM: paris Optimization: Yes (500 runs)
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
Ownable.sol 100 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
DefinitiveErrors.sol 84 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.20;

/**
 * @notice Contains all errors used throughout the Definitive contracts
 * @dev This file should only be used as an internal library.
 * @dev When adding a new error, add alphabetically
 */

error AccountMissingRole(address _account, bytes32 _role);
error AccountNotAdmin(address);
error AccountNotWhitelisted(address);
error AddLiquidityFailed();
error AlreadyDeployed();
error AlreadyInitialized();
error BytecodeEmpty();
error DeadlineExceeded();
error DeployInitFailed();
error DeployFailed();
error BorrowFailed(uint256 errorCode);
error DecollateralizeFailed(uint256 errorCode);
error DepositMoreThanMax();
error EmptyBytecode();
error EnterAllFailed();
error EnforcedSafeLTV(uint256 invalidLTV);
error ExceededMaxDelta();
error ExceededMaxLTV();
error ExceededShareToAssetRatioDeltaThreshold();
error ExitAllFailed();
error ExitOneCoinFailed();
error GlobalStopGuardianEnabled();
error InitializeMarketsFailed();
error InputGreaterThanStaked();
error InsufficientBalance();
error InsufficientSwapTokenBalance();
error InvalidAddress();
error InvalidAmount();
error InvalidAmounts();
error InvalidCalldata();
error InvalidDestinationSwapper();
error InvalidERC20Address();
error InvalidExecutedOutputAmount();
error InvalidFeePercent();
error InvalidHandler();
error InvalidInputs();
error InvalidMsgValue();
error InvalidSingleHopSwap();
error InvalidMultiHopSwap();
error InvalidOutputToken();
error InvalidRedemptionRecipient(); // Used in cross-chain redeptions
error InvalidReportedOutputAmount();
error InvalidRewardsClaim();
error InvalidSignature();
error InvalidSignatureLength();
error InvalidSwapHandler();
error InvalidSwapInputAmount();
error InvalidSwapOutputToken();
error InvalidSwapPath();
error InvalidSwapPayload();
error InvalidSwapToken();
error MintMoreThanMax();
error MismatchedChainId();
error NativeAssetWrapFailed(bool wrappingToNative);
error NoSignatureVerificationSignerSet();
error RedeemMoreThanMax();
error RemoveLiquidityFailed();
error RepayDebtFailed();
error SafeHarborModeEnabled();
error SafeHarborRedemptionDisabled();
error SlippageExceeded(uint256 _outputAmount, uint256 _outputAmountMin);
error StakeFailed();
error SupplyFailed();
error StopGuardianEnabled();
error TradingDisabled();
error SwapDeadlineExceeded();
error SwapLimitExceeded();
error SwapTokenIsOutputToken();
error TransfersLimitExceeded();
error UnstakeFailed();
error UnauthenticatedFlashloan();
error UntrustedFlashLoanSender(address);
error WithdrawMoreThanMax();
error WithdrawalsDisabled();
error ZeroShares();
SignatureVerifier.sol 64 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.20;

import { InvalidSignature, InvalidSignatureLength } from "./DefinitiveErrors.sol";

library SignatureVerifier {
    function verifySignature(
        mapping(address => bool) storage validSigners,
        bytes32 messageHash,
        bytes memory signature
    ) internal view {
        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);

        address signer = recoverSigner(ethSignedMessageHash, signature);

        if (!validSigners[signer]) {
            revert InvalidSignature();
        }
    }

    /* cSpell:disable */
    function getEthSignedMessageHash(bytes32 messageHash) public pure returns (bytes32) {
        /*
            Signature is produced by signing a keccak256 hash with the following format:
            "\x19Ethereum Signed Message\n" + len(msg) + msg
        */
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
    }

    /* cSpell:enable */

    function recoverSigner(bytes32 ethSignedMessageHash, bytes memory signature) private pure returns (address signer) {
        (bytes32 r, bytes32 s, uint8 v) = splitSignature(signature);
        return ecrecover(ethSignedMessageHash, v, r, s);
    }

    // https://solidity-by-example.org/signature
    function splitSignature(bytes memory sig) private pure returns (bytes32 r, bytes32 s, uint8 v) {
        if (sig.length != 65) {
            revert InvalidSignatureLength();
        }

        // solhint-disable-next-line no-inline-assembly
        assembly {
            /*
            First 32 bytes stores the length of the signature

            add(sig, 32) = pointer of sig + 32
            effectively, skips first 32 bytes of signature

            mload(p) loads next 32 bytes starting at the memory address p into memory
            */

            // first 32 bytes, after the length prefix
            r := mload(add(sig, 32))
            // second 32 bytes
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes)
            v := byte(0, mload(add(sig, 96)))
        }

        // implicitly return (r, s, v)
    }
}
SignatureLogic.sol 98 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import { SignatureVerifier } from "../../core/libraries/SignatureVerifier.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import {
    AlreadyInitialized,
    DeadlineExceeded,
    BytecodeEmpty,
    MismatchedChainId,
    InvalidAddress
} from "../../core/libraries/DefinitiveErrors.sol";

struct DeploymentParams {
    uint256 chainId;
    uint256 deadline;
    bytes bytecode;
    bytes32 deploySalt;
}

contract SignatureLogic is Ownable {
    event SignatureVerifierAdded(address signatureVerifier);
    event SignatureVerifierRemoved(address signatureVerifier);

    bool isInitialized;

    mapping(address => bool) public isSignatureVerifier;

    constructor() Ownable(msg.sender) {}

    function initialize(address _owner, address[] calldata _initialVerifiers) external onlyOwner {
        if (isInitialized) {
            revert AlreadyInitialized();
        }
        isInitialized = true;

        transferOwnership(_owner);

        uint256 length = _initialVerifiers.length;
        for (uint256 i = 0; i < length; ) {
            _addSignatureVerifier(_initialVerifiers[i]);
            unchecked {
                ++i;
            }
        }
    }

    function addSignatureVerifier(address _signatureVerifier) public onlyOwner {
        _addSignatureVerifier(_signatureVerifier);
    }

    function removeSignatureVerifier(address _signatureVerifier) public onlyOwner {
        _removeSignatureVerifier(_signatureVerifier);
    }

    function encodeDepositParams(DeploymentParams calldata deploymentParameters) public pure returns (bytes32) {
        return keccak256(abi.encode(deploymentParameters));
    }

    function _verifyDeploymentParams(
        DeploymentParams calldata deployParams,
        bytes memory authorizedDeploySignature
    ) internal view {
        SignatureVerifier.verifySignature(
            isSignatureVerifier,
            keccak256(abi.encode(deployParams)),
            authorizedDeploySignature
        );

        if (deployParams.bytecode.length == 0) {
            revert BytecodeEmpty();
        }

        if (deployParams.deadline < block.timestamp) {
            revert DeadlineExceeded();
        }

        if (deployParams.chainId != block.chainid) {
            revert MismatchedChainId();
        }
    }

    function _addSignatureVerifier(address _signatureVerifier) private {
        if (_signatureVerifier == address(0)) {
            revert InvalidAddress();
        }
        isSignatureVerifier[_signatureVerifier] = true;
        emit SignatureVerifierAdded(_signatureVerifier);
    }

    function _removeSignatureVerifier(address _signatureVerifier) private {
        if (_signatureVerifier == address(0)) {
            revert InvalidAddress();
        }
        isSignatureVerifier[_signatureVerifier] = false;
        emit SignatureVerifierRemoved(_signatureVerifier);
    }
}
Create3.sol 42 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import { ContractAddress } from "../libs/ContractAddress.sol";
import { CreateDeploy } from "./CreateDeploy.sol";
import { Create3Address } from "./Create3Address.sol";

import { EmptyBytecode, AlreadyDeployed, DeployFailed } from "../../../core/libraries/DefinitiveErrors.sol";

/**
 * @title Create3 contract
 * @notice This contract can be used to deploy a contract with a deterministic address that depends only on
 * the deployer address and deployment salt, not the contract bytecode and constructor parameters.
 */
abstract contract Create3 is Create3Address {
    using ContractAddress for address;

    /**
     * @notice Deploys a new contract using the `CREATE3` method.
     * @dev This function first deploys the CreateDeploy contract using
     * the `CREATE2` opcode and then utilizes the CreateDeploy to deploy the
     * new contract with the `CREATE` opcode.
     * @param bytecode The bytecode of the contract to be deployed
     * @param deploySalt A salt to influence the contract address
     * @return deployed The address of the deployed contract
     */
    function _create3(bytes memory bytecode, bytes32 deploySalt) internal returns (address deployed) {
        deployed = _create3Address(deploySalt);

        if (bytecode.length == 0) revert EmptyBytecode();
        if (deployed.isContract()) revert AlreadyDeployed();

        // Deploy using create2
        CreateDeploy create = new CreateDeploy{ salt: deploySalt }();

        if (address(create) == address(0)) revert DeployFailed();

        // Deploy using create
        create.deploy(bytecode);
    }
}
Deployer.sol 108 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import { SafeNativeTransfer } from "../libs/SafeNativeTransfer.sol";
import { DeploymentParams, SignatureLogic } from "../SignatureLogic.sol";
import { DeployInitFailed } from "../../../core/libraries/DefinitiveErrors.sol";

/**
 * @title Deployer Contract
 * @notice This contract is responsible for deploying and initializing new contracts using
 * a deployment method, such as `CREATE2` or `CREATE3`.
 */
abstract contract Deployer is SignatureLogic {
    using SafeNativeTransfer for address;

    /**
     * @notice Deploys a contract using a deployment method defined by derived contracts.
     * @dev The address where the contract will be deployed can be known in
     * advance via {deployedAddress}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already by the same `msg.sender`.
     *
     * @param deployParams Deployment parameters
     * @param authorizedDeploySignature valid signature authorizing the deploy
     */
    // slither-disable-next-line locked-ether
    function deploy(
        DeploymentParams calldata deployParams,
        bytes memory authorizedDeploySignature
    ) public payable returns (address deployedAddress_) {
        _verifyDeploymentParams(deployParams, authorizedDeploySignature);

        deployedAddress_ = _deployedAddress(deployParams.bytecode, deployParams.deploySalt);

        if (msg.value > 0) {
            // slither-disable-next-line unused-return
            deployedAddress_.safeNativeTransfer(msg.value);
        }

        deployedAddress_ = _deploy(deployParams.bytecode, deployParams.deploySalt);
    }

    /**
     * @notice Deploys a contract using a deployment method defined by derived contracts and initializes it.
     * @dev The address where the contract will be deployed can be known in advance
     * via {deployedAddress}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already by the same `msg.sender`.
     * - `init` is used to initialize the deployed contract as an option to not have the
     *    constructor args affect the address derived by `CREATE2`.
     *
     * @param deployParams Deployment parameters
     * @param authorizedDeploySignature valid signature authorizing the deploy
     * @param init Init data used to initialize the deployed contract
     * @return deployedAddress_ The address of the deployed contract
     */
    // slither-disable-next-line locked-ether
    function deployAndInit(
        DeploymentParams calldata deployParams,
        bytes memory authorizedDeploySignature,
        bytes calldata init
    ) external payable returns (address deployedAddress_) {
        _verifyDeploymentParams(deployParams, authorizedDeploySignature);

        deployedAddress_ = _deployedAddress(deployParams.bytecode, deployParams.deploySalt);

        if (msg.value > 0) {
            // slither-disable-next-line unused-return
            deployedAddress_.safeNativeTransfer(msg.value);
        }

        deployedAddress_ = _deploy(deployParams.bytecode, deployParams.deploySalt);

        (bool success, ) = deployedAddress_.call(init);
        if (!success) revert DeployInitFailed();
    }

    /**
     *
     * @notice Returns the address where a contract will be stored
     * if deployed via {deploy} or {deployAndInit} by `sender`.
     * @dev Any change in the `bytecode` (except for `CREATE3`), `sender`,
     * or `salt` will result in a new deployed address.
     * @param bytecode The bytecode of the contract to be deployed
     * @param salt The salt that will be used to influence the contract address
     * @return deployedAddress_ The address that the contract will be deployed to
     */
    function deployedAddress(bytes memory bytecode, bytes32 salt) public view returns (address) {
        return _deployedAddress(bytecode, salt);
    }

    function _deploy(bytes memory bytecode, bytes32 deploySalt) internal virtual returns (address);

    function _deployedAddress(bytes memory bytecode, bytes32 deploySalt) internal view virtual returns (address);
}
CreateDeploy.sol 27 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

/**
 * @title CreateDeploy Contract
 * @notice This contract deploys new contracts using the `CREATE` opcode and is used as part of
 * the `CREATE3` deployment method.
 */
contract CreateDeploy {
    /**
     * @dev Deploys a new contract with the specified bytecode using the `CREATE` opcode.
     * @param bytecode The bytecode of the contract to be deployed
     */
    // slither-disable-next-line locked-ether
    function deploy(bytes memory bytecode) external payable {
        assembly {
            if iszero(create(0, add(bytecode, 32), mload(bytecode))) {
                revert(0, 0)
            }
        }

        /// @dev If we want to redeploy to the same contract we must self destruct this intermediate contract
        // slither-disable-next-line suicidal
        selfdestruct(payable(address(0)));
    }
}
ContractAddress.sol 15 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

library ContractAddress {
    function isContract(address contractAddress) internal view returns (bool) {
        bytes32 existingCodeHash = contractAddress.codehash;

        // https://eips.ethereum.org/EIPS/eip-1052
        // keccak256('') == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
        return
            existingCodeHash != bytes32(0) &&
            existingCodeHash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
    }
}
Create3Address.sol 33 lines
// SPDX-License-Identifier: MIT

import { CreateDeploy } from "./CreateDeploy.sol";

pragma solidity ^0.8.4;

/**
 * @title Create3Address contract
 * @notice This contract can be used to predict the deterministic
 * deployment address of a contract deployed with the `CREATE3` technique.
 */
abstract contract Create3Address {
    /// @dev bytecode hash of the CreateDeploy helper contract
    /* immutable-vars-naming */
    bytes32 internal immutable createDeployBytecodeHash;

    constructor() {
        createDeployBytecodeHash = keccak256(type(CreateDeploy).creationCode);
    }

    /**
     * @notice Compute the deployed address that will result from the `CREATE3` method.
     * @param deploySalt A salt to influence the contract address
     * @return deployed The deterministic contract address if it was deployed
     */
    function _create3Address(bytes32 deploySalt) internal view returns (address deployed) {
        address deployer = address(
            uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(this), deploySalt, createDeployBytecodeHash))))
        );

        deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex"d6_94", deployer, hex"01")))));
    }
}
Create2Deployer.sol 103 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { SignatureLogic, DeploymentParams } from "../SignatureLogic.sol";
import { DeployFailed, EmptyBytecode, DeployInitFailed } from "../../../core/libraries/DefinitiveErrors.sol";
import { SafeNativeTransfer } from "../libs/SafeNativeTransfer.sol";

abstract contract Create2Deployer is SignatureLogic {
    using SafeNativeTransfer for address;

    event Deployed(bytes32 indexed bytecodeHash, bytes32 indexed salt, address indexed deployedAddress);

    /**
     * @dev Deploys a contract using `CREATE2`. The address where the contract
     * will be deployed can be known in advance via {deployedAddress}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already by the same `msg.sender`.
     */
    function deployCreate2(
        DeploymentParams calldata deployParams,
        bytes memory authorizedDeploySignature
    ) external payable returns (address deployedAddress_) {
        _verifyDeploymentParams(deployParams, authorizedDeploySignature);

        if (msg.value > 0) {
            // slither-disable-next-line unused-return
            deployedAddress_.safeNativeTransfer(msg.value);
        }
        deployedAddress_ = _deployCreate2(deployParams.bytecode, deployParams.deploySalt);
    }

    /**
     * @dev Deploys a contract using `CREATE2` and initialize it. The address where the contract
     * will be deployed can be known in advance via {deployedAddress}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already by the same `msg.sender`.
     * - `init` is used to initialize the deployed contract
     *    as an option to not have the constructor args affect the address derived by `CREATE2`.
     */
    function deployCreate2AndInit(
        DeploymentParams calldata deployParams,
        bytes memory authorizedDeploySignature,
        bytes calldata init
    ) external returns (address deployedAddress_) {
        _verifyDeploymentParams(deployParams, authorizedDeploySignature);

        deployedAddress_ = _deployCreate2(deployParams.bytecode, deployParams.deploySalt);

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, ) = deployedAddress_.call(init);
        if (!success) revert DeployInitFailed();
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy} or {deployAndInit} by `sender`.
     * Any change in the `bytecode`, `sender`, or `salt` will result in a new destination address.
     */
    function deployedCreate2Address(
        bytes calldata bytecode,
        bytes32 salt
    ) external view returns (address deployedAddress_) {
        deployedAddress_ = address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            hex"ff",
                            address(this),
                            salt,
                            keccak256(bytecode) // init code hash
                        )
                    )
                )
            )
        );
    }

    function _deployCreate2(bytes memory bytecode, bytes32 salt) internal returns (address deployedAddress_) {
        if (bytecode.length == 0) revert EmptyBytecode();

        // solhint-disable-next-line no-inline-assembly
        assembly {
            deployedAddress_ := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }

        if (deployedAddress_ == address(0)) revert DeployFailed();

        emit Deployed(keccak256(bytecode), salt, deployedAddress_);
    }
}
SafeNativeTransfer.sol 28 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

error NativeTransferFailed();

/*
 * @title SafeNativeTransfer
 * @dev This library is used for performing safe native value transfers in Solidity by utilizing inline assembly.
 */
library SafeNativeTransfer {
    /*
     * @notice Perform a native transfer to a given address.
     * @param receiver The recipient address to which the amount will be sent.
     * @param amount The amount of native value to send.
     * @throws NativeTransferFailed error if transfer is not successful.
     */
    function safeNativeTransfer(address receiver, uint256 amount) internal {
        bool success;

        /* solhint-disable no-inline-assembly */
        assembly {
            success := call(gas(), receiver, amount, 0, 0, 0, 0)
        }

        if (!success) revert NativeTransferFailed();
    }
}
PermissionedDeployer.sol 27 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import { Deployer } from "./Deployer.sol";
import { Create3 } from "./Create3.sol";
import { Create2Deployer } from "./Create2Deployer.sol";

/**
 * @title PermissionedDeployer Contract
 * @notice This contract is responsible for deploying and initializing new contracts using the `CREATE3` method
 * which computes the deployed contract address based on the deployer address and deployment salt.
 */
contract PermissionedDeployer is Create3, Create2Deployer, Deployer {
    function _deploy(bytes memory bytecode, bytes32 deploySalt) internal override returns (address deployedAddress_) {
        deployedAddress_ = _create3(bytecode, deploySalt);

        emit Deployed(keccak256(bytecode), deploySalt, deployedAddress_);
    }

    function _deployedAddress(
        bytes memory /* bytecode */,
        bytes32 deploySalt
    ) internal view override returns (address) {
        return _create3Address(deploySalt);
    }
}

Read Contract

deployedAddress 0xf6904966 → address
deployedCreate2Address 0x73599fd4 → address
encodeDepositParams 0x7eaa3194 → bytes32
isSignatureVerifier 0xf073cecd → bool
owner 0x8da5cb5b → address

Write Contract 9 functions

These functions modify contract state and require a wallet transaction to execute.

addSignatureVerifier 0xcd0bcff5
address _signatureVerifier
deploy 0x06e24fb9
tuple deployParams
bytes authorizedDeploySignature
returns: address
deployAndInit 0xe7045cfb
tuple deployParams
bytes authorizedDeploySignature
bytes init
returns: address
deployCreate2 0xaaed388d
tuple deployParams
bytes authorizedDeploySignature
returns: address
deployCreate2AndInit 0x2465195c
tuple deployParams
bytes authorizedDeploySignature
bytes init
returns: address
initialize 0x946d9204
address _owner
address[] _initialVerifiers
removeSignatureVerifier 0xafb83ce6
address _signatureVerifier
renounceOwnership 0x715018a6
No parameters
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address