ETH Price: $3,296.28 (+2.66%)

Contract

0x63c9362a7bEDC92Dec83433C15d623fbD3E1e5A9
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Solve With Signa...180352102023-08-31 14:39:23508 days ago1693492763IN
0x63c9362a...bD3E1e5A9
0 ETH0.0080413928.82831083
Solve With Signa...180351322023-08-31 14:23:47508 days ago1693491827IN
0x63c9362a...bD3E1e5A9
0 ETH0.0083123728.40129013
Solve With Signa...180349012023-08-31 13:37:35508 days ago1693489055IN
0x63c9362a...bD3E1e5A9
0 ETH0.0069034224.42998124
Solve With Signa...180335192023-08-31 8:59:59508 days ago1693472399IN
0x63c9362a...bD3E1e5A9
0 ETH0.0039325814.27831219
Solve With Signa...180333832023-08-31 8:32:47508 days ago1693470767IN
0x63c9362a...bD3E1e5A9
0 ETH0.0062857622.88844487
Solve With Signa...180281942023-08-30 15:05:35509 days ago1693407935IN
0x63c9362a...bD3E1e5A9
0 ETH0.0206151268.25974653
Solve With Signa...180279542023-08-30 14:17:11509 days ago1693405031IN
0x63c9362a...bD3E1e5A9
0 ETH0.0013255227.31917303
Solve With Signa...180266192023-08-30 9:46:59509 days ago1693388819IN
0x63c9362a...bD3E1e5A9
0 ETH0.0064207917.41760906
Solve With Signa...180259352023-08-30 7:29:23509 days ago1693380563IN
0x63c9362a...bD3E1e5A9
0 ETH0.0114006929.23150966

Latest 4 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
180349012023-08-31 13:37:35508 days ago1693489055
0x63c9362a...bD3E1e5A9
0.002 ETH
180349012023-08-31 13:37:35508 days ago1693489055
0x63c9362a...bD3E1e5A9
0.002 ETH
180266192023-08-30 9:46:59509 days ago1693388819
0x63c9362a...bD3E1e5A9
0.01 ETH
180266192023-08-30 9:46:59509 days ago1693388819
0x63c9362a...bD3E1e5A9
0.01 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Memswap

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 3 : Memswap.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract Memswap is ReentrancyGuard {
    // --- Structs ---

    struct Intent {
        IERC20 tokenIn;
        IERC20 tokenOut;
        address maker;
        // The address allowed to solve or authorize others to solve
        address matchmaker;
        address source;
        uint16 feeBps;
        uint16 surplusBps;
        uint32 deadline;
        bool isPartiallyFillable;
        uint128 amountIn;
        uint128 endAmountOut;
        uint16 startAmountBps;
        uint16 expectedAmountBps;
        bytes signature;
    }

    struct IntentStatus {
        bool isValidated;
        bool isCancelled;
        uint128 amountFilled;
    }

    struct Authorization {
        uint128 maxAmountIn;
        uint128 minAmountOut;
        uint32 blockDeadline;
        bool isPartiallyFillable;
    }

    struct Solution {
        address to;
        bytes data;
        uint128 amount;
    }

    // --- Events ---

    event IntentCancelled(bytes32 indexed intentHash);
    event IntentPosted();
    event IntentSolved(
        bytes32 indexed intentHash,
        address tokenIn,
        address tokenOut,
        address maker,
        address solver,
        uint128 amountIn,
        uint128 amountOut
    );
    event IntentValidated(bytes32 indexed intentHash);

    // --- Errors ---

    error AuthorizationIsExpired();
    error AuthorizationIsInsufficient();
    error AuthorizationIsNotPartiallyFillable();
    error IntentIsCancelled();
    error IntentIsExpired();
    error IntentIsFilled();
    error IntentIsNotPartiallyFillable();
    error InvalidSignature();
    error InvalidSolution();
    error MerkleTreeTooLarge();
    error Unauthorized();
    error UnsuccessfullCall();

    // --- Fields ---

    bytes32 public immutable DOMAIN_SEPARATOR;
    bytes32 public immutable AUTHORIZATION_TYPEHASH;
    bytes32 public immutable INTENT_TYPEHASH;

    mapping(bytes32 => IntentStatus) public intentStatus;
    mapping(bytes32 => Authorization) public authorization;

    // --- Constructor ---

    constructor() {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256(
                    "EIP712Domain("
                    "string name,"
                    "string version,"
                    "uint256 chainId,"
                    "address verifyingContract"
                    ")"
                ),
                keccak256("Memswap"),
                keccak256("1.0"),
                chainId,
                address(this)
            )
        );

        AUTHORIZATION_TYPEHASH = keccak256(
            abi.encodePacked(
                "Authorization(",
                "bytes32 intentHash,",
                "address authorizedSolver,",
                "uint128 maxAmountIn,",
                "uint128 minAmountOut,",
                "uint32 blockDeadline,",
                "bool isPartiallyFillable",
                ")"
            )
        );

        INTENT_TYPEHASH = keccak256(
            abi.encodePacked(
                "Intent(",
                "address tokenIn,",
                "address tokenOut,",
                "address maker,",
                "address matchmaker,",
                "address source,",
                "uint16 feeBps,",
                "uint16 surplusBps,",
                "uint32 deadline,",
                "bool isPartiallyFillable,",
                "uint128 amountIn,",
                "uint128 endAmountOut,",
                "uint16 startAmountBps,",
                "uint16 expectedAmountBps",
                ")"
            )
        );
    }

    // Fallback

    receive() external payable {}

    // Public methods

    /**
     * @notice Authorize an address to solve a particular intent
     *
     * @param intent Intent which is being solved
     * @param authorizedSolver The address authorized to solve the intent
     * @param auth Authorization details and conditions
     */
    function authorize(
        Intent calldata intent,
        address authorizedSolver,
        Authorization calldata auth
    ) external {
        if (intent.matchmaker != msg.sender) {
            revert Unauthorized();
        }

        bytes32 intentHash = getIntentHash(intent);
        bytes32 authId = keccak256(
            abi.encodePacked(intentHash, authorizedSolver)
        );
        authorization[authId] = auth;
    }

    /**
     * @notice Make an intent available on-chain (this method doesn't do
     *         anything useful, it's only used as a mechanism for intent
     *         distribution)
     *
     * @custom:param intent Intent being made available
     */
    function post(
        /**
         * @custom:name intent
         */
        Intent calldata
    ) external {
        emit IntentPosted();
    }

    /**
     * @notice Validate an arbitrary number of intents (the signature of each
     *         intent will be checked thus resulting in skipping verification
     *         on further attempts to solve the intent)
     *
     * @param intents Intents to validate
     */
    function validate(Intent[] calldata intents) external {
        uint256 length = intents.length;
        for (uint256 i; i < length; ) {
            Intent calldata intent = intents[i];

            bytes32 intentHash = getIntentHash(intent);

            _validateIntent(intentHash, intent.maker, intent.signature);
            emit IntentValidated(intentHash);

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Cancel an arbitrary number of intents
     *
     * @param intents Intents to cancel
     */
    function cancel(Intent[] calldata intents) external nonReentrant {
        uint256 length = intents.length;
        for (uint256 i; i < length; ) {
            Intent calldata intent = intents[i];
            if (intent.maker != msg.sender) {
                revert Unauthorized();
            }

            bytes32 intentHash = getIntentHash(intent);
            IntentStatus memory status = intentStatus[intentHash];
            status.isValidated = false;
            status.isCancelled = true;

            intentStatus[intentHash] = status;
            emit IntentCancelled(intentHash);

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Solve an intent
     *
     * @param intent Intent to solve
     * @param solution Solution for the intent
     */
    function solve(
        Intent calldata intent,
        Solution calldata solution
    ) external nonReentrant {
        // The intent must be open or tied to the current solver
        if (
            intent.matchmaker != address(0) && intent.matchmaker != msg.sender
        ) {
            revert Unauthorized();
        }

        // Solve (no minimum amount out restrictions when filling without authorization)
        _solve(intent, solution, 0);
    }

    /**
     * @notice Solve an intent with authorization (compared to the regular `solve`
     *         this method allows filling intents of a matchmaker as long as there
     *         is a valid authorization in-place for the current solver). The auth
     *         will be done on-chain (via a transaction from the matchmaker).
     *
     * @param intent Intent to solve
     * @param solution Solution for the intent
     */
    function solveWithOnChainAuthorizationCheck(
        Intent calldata intent,
        Solution calldata solution
    ) external nonReentrant {
        bytes32 intentHash = getIntentHash(intent);

        // Fetch the authorization
        bytes32 authId = keccak256(abi.encodePacked(intentHash, msg.sender));
        Authorization memory auth = authorization[authId];

        // Check the authorization and solve
        _checkAuthorization(auth, solution.amount);
        _solve(intent, solution, auth.minAmountOut);
    }

    /**
     * @notice Solve an intent with authorization (compared to the regular `solve`
     *         this method allows filling intents of a matchmaker as long as there
     *         is a valid authorization in-place for the current solver). The auth
     *         will be done off-chain (via a signature from the matchmaker).
     *
     * @param intent Intent to solve
     * @param solution Solution for the intent
     * @param auth Authorization details/conditions
     * @param signature Authorization signature
     */
    function solveWithSignatureAuthorizationCheck(
        Intent calldata intent,
        Solution calldata solution,
        Authorization calldata auth,
        bytes calldata signature
    ) external nonReentrant {
        bytes32 intentHash = getIntentHash(intent);
        bytes32 authorizationHash = getAuthorizationHash(
            intentHash,
            msg.sender,
            auth
        );

        // Verify the authorization
        bytes32 digest = _getEIP712Hash(authorizationHash);
        _assertValidSignature(
            intent.matchmaker,
            digest,
            digest,
            signature.length,
            signature
        );

        // Check the authorization and solve
        _checkAuthorization(auth, solution.amount);
        _solve(intent, solution, auth.minAmountOut);
    }

    // View methods

    /**
     * @notice Get the EIP712 struct hash for an authorization
     *
     * @param intentHash Intent EIP712 struct hash to authorize
     * @param authorizedSolver Solver to authorize
     * @param auth Authorization details/conditions
     *
     * @return authorizationHash The EIP712 struct hash of the authorization
     */
    function getAuthorizationHash(
        bytes32 intentHash,
        address authorizedSolver,
        Authorization memory auth
    ) public view returns (bytes32 authorizationHash) {
        authorizationHash = keccak256(
            abi.encode(
                AUTHORIZATION_TYPEHASH,
                intentHash,
                authorizedSolver,
                auth.maxAmountIn,
                auth.minAmountOut,
                auth.blockDeadline,
                auth.isPartiallyFillable
            )
        );
    }

    /**
     * @notice Get the EIP712 struct hash for an intent
     *
     * @param intent Intent to compute the hash for
     *
     * @return intentHash The EIP712 struct hash of the intent
     */
    function getIntentHash(
        Intent memory intent
    ) public view returns (bytes32 intentHash) {
        intentHash = keccak256(
            abi.encode(
                INTENT_TYPEHASH,
                intent.tokenIn,
                intent.tokenOut,
                intent.maker,
                intent.matchmaker,
                intent.source,
                intent.feeBps,
                intent.surplusBps,
                intent.deadline,
                intent.isPartiallyFillable,
                intent.amountIn,
                intent.endAmountOut,
                intent.startAmountBps,
                intent.expectedAmountBps
            )
        );
    }

    // Internal methods

    /**
     * @dev Solve an intent
     *
     * @param intent Intent to solve
     * @param solution Solution for the intent
     * @param minAmountOut The minimum amount out the solution is required to fulfill
     */
    function _solve(
        Intent calldata intent,
        Solution calldata solution,
        uint128 minAmountOut
    ) internal {
        bytes32 intentHash = getIntentHash(intent);

        // Verify deadline
        if (intent.deadline < block.timestamp) {
            revert IntentIsExpired();
        }

        IntentStatus memory status = intentStatus[intentHash];

        // Verify cancellation status
        if (status.isCancelled) {
            revert IntentIsCancelled();
        }

        // Verify signature
        if (!status.isValidated) {
            _validateIntent(intentHash, intent.maker, intent.signature);
        }

        uint128 amountToFill;
        // Avoid "Stack too deep" errors by wrapping inside a block
        {
            // Ensure there's still some amount left to be filled
            uint128 amountAvailable = intent.amountIn - status.amountFilled;
            if (amountAvailable == 0) {
                revert IntentIsFilled();
            }

            // Ensure non-partially-fillable intents are fully filled
            if (
                !intent.isPartiallyFillable && solution.amount < amountAvailable
            ) {
                revert IntentIsNotPartiallyFillable();
            }

            // Compute the amount available to fill
            amountToFill = solution.amount > amountAvailable
                ? amountAvailable
                : solution.amount;
            intentStatus[intentHash].amountFilled += amountToFill;
        }

        // Transfer inputs to fill contract
        if (amountToFill > 0) {
            _transferToken(
                intent.maker,
                solution.to,
                intent.tokenIn,
                amountToFill
            );
        }

        // Execute solution
        // Avoid "Stack too deep" errors by wrapping inside a block
        {
            (bool result, ) = solution.to.call(solution.data);
            if (!result) {
                revert UnsuccessfullCall();
            }
        }

        // Check

        uint128 endAmountOut = intent.endAmountOut;
        uint128 startAmountOut = endAmountOut +
            (endAmountOut * intent.startAmountBps) /
            10000;
        uint128 expectedAmountOut = endAmountOut +
            (endAmountOut * intent.expectedAmountBps) /
            10000;

        //                                (startAmount - endAmount)
        // requiredAmount = startAmount - -------------------------
        //                                   (deadline - now())

        uint128 requiredAmountOut = startAmountOut -
            (startAmountOut - endAmountOut) /
            (
                intent.deadline > uint32(block.timestamp)
                    ? intent.deadline - uint32(block.timestamp)
                    : 1
            );

        if (requiredAmountOut < minAmountOut) {
            revert InvalidSolution();
        }

        uint256 tokenOutBalance = address(intent.tokenOut) == address(0)
            ? address(this).balance
            : intent.tokenOut.allowance(solution.to, address(this));

        // Ensure the maker got at least what he intended
        if (tokenOutBalance < requiredAmountOut) {
            revert InvalidSolution();
        }

        if (intent.source != address(0)) {
            uint256 amount;

            // Charge fee
            if (intent.feeBps > 0) {
                amount += (requiredAmountOut * intent.feeBps) / 10000;
            }

            // Charge surplus fee
            if (
                intent.surplusBps > 0 &&
                tokenOutBalance > expectedAmountOut &&
                expectedAmountOut > requiredAmountOut
            ) {
                amount +=
                    ((tokenOutBalance - expectedAmountOut) *
                        intent.surplusBps) /
                    10000;
            }

            // Transfer fees
            if (amount > 0) {
                _transferToken(
                    solution.to,
                    intent.source,
                    intent.tokenOut,
                    amount
                );

                tokenOutBalance -= amount;
            }
        }

        // Transfer ouputs to maker
        if (tokenOutBalance > 0) {
            _transferToken(
                solution.to,
                intent.maker,
                intent.tokenOut,
                tokenOutBalance
            );
        }

        emit IntentSolved(
            intentHash,
            address(intent.tokenIn),
            address(intent.tokenOut),
            intent.maker,
            msg.sender,
            amountToFill,
            uint128(tokenOutBalance)
        );
    }

    /**
     * @dev Check an authorization
     *
     * @param auth Authorization to check
     * @param amount Amount to check the authorization against
     */
    function _checkAuthorization(
        Authorization memory auth,
        uint128 amount
    ) internal view {
        // Ensure the authorization is not expired
        if (auth.blockDeadline < block.number) {
            revert AuthorizationIsExpired();
        }

        // Ensure the amount doesn't exceed the maximum authorized amount
        if (auth.maxAmountIn < amount) {
            revert AuthorizationIsInsufficient();
        }

        // Ensure non-partially-fillable authorizations are fully filled
        if (!auth.isPartiallyFillable && auth.maxAmountIn != amount) {
            revert AuthorizationIsNotPartiallyFillable();
        }
    }

    /**
     * @dev Get the EIP712 hash of a struct hash
     *
     * @param structHash Struct hash to get the EIP712 hash for
     *
     * @return eip712Hash The resulting EIP712 hash
     */
    function _getEIP712Hash(
        bytes32 structHash
    ) internal view returns (bytes32 eip712Hash) {
        eip712Hash = keccak256(
            abi.encodePacked(hex"1901", DOMAIN_SEPARATOR, structHash)
        );
    }

    /**
     * @dev Validate an intent by checking its signature
     *
     * @param intentHash EIP712 intent struct hash to verify
     * @param maker The maker of the intent
     * @param signature The signature of the intent
     */
    function _validateIntent(
        bytes32 intentHash,
        address maker,
        bytes calldata signature
    ) internal {
        _verifySignature(intentHash, maker, signature);

        // Mark the intent as validated
        intentStatus[intentHash].isValidated = true;
    }

    /**
     * @dev Helper method for transferring native and ERC20 tokens
     *
     * @param from Transfer from this address
     * @param to Transfer to this address
     * @param token Token to transfer
     * @param amount Amonut to transfer
     */
    function _transferToken(
        address from,
        address to,
        IERC20 token,
        uint256 amount
    ) internal {
        bool success;

        // Represent native tokens as `address(0)`
        if (address(token) == address(0)) {
            (success, ) = to.call{value: amount}("");
        } else {
            success = token.transferFrom(from, to, amount);
        }

        if (!success) {
            revert UnsuccessfullCall();
        }
    }

    // Copied from Seaport's source code

    function _verifySignature(
        bytes32 intentHash,
        address signer,
        bytes memory signature
    ) internal view {
        // Skip signature verification if the signer is the caller
        if (signer == msg.sender) {
            return;
        }

        bytes32 originalDigest = _getEIP712Hash(intentHash);

        // Read the length of the signature from memory and place on the stack
        uint256 originalSignatureLength = signature.length;

        // Determine effective digest if signature has a valid bulk order size
        bytes32 digest;
        if (_isValidBulkOrderSize(originalSignatureLength)) {
            // Rederive order hash and digest using bulk order proof
            (intentHash) = _computeBulkOrderProof(signature, intentHash);
            digest = _getEIP712Hash(intentHash);
        } else {
            // Supply the original digest as the effective digest
            digest = originalDigest;
        }

        // Ensure that the signature for the digest is valid for the signer
        _assertValidSignature(
            signer,
            digest,
            originalDigest,
            originalSignatureLength,
            signature
        );
    }

    function _isValidBulkOrderSize(
        uint256 signatureLength
    ) internal pure returns (bool validLength) {
        // Utilize assembly to validate the length:
        // (64 + x) + 3 + 32y where (0 <= x <= 1) and (1 <= y <= 24)
        assembly {
            validLength := and(
                lt(sub(signatureLength, 0x63), 0x2e2),
                lt(and(add(signatureLength, 0x1d), 0x1f), 0x2)
            )
        }
    }

    function _computeBulkOrderProof(
        bytes memory proofAndSignature,
        bytes32 leaf
    ) internal pure returns (bytes32 bulkOrderHash) {
        // Declare arguments for the root hash and the height of the proof
        bytes32 root;
        uint256 height;

        // Utilize assembly to efficiently derive the root hash using the proof
        assembly {
            // Retrieve the length of the proof, key, and signature combined
            let fullLength := mload(proofAndSignature)

            // If proofAndSignature has odd length, it is a compact signature with 64 bytes
            let signatureLength := sub(65, and(fullLength, 1))

            // Derive height (or depth of tree) with signature and proof length
            height := shr(0x5, sub(fullLength, signatureLength))

            // Update the length in memory to only include the signature
            mstore(proofAndSignature, signatureLength)

            // Derive the pointer for the key using the signature length
            let keyPtr := add(proofAndSignature, add(0x20, signatureLength))

            // Retrieve the three-byte key using the derived pointer
            let key := shr(0xe8, mload(keyPtr))

            // Retrieve pointer to first proof element by applying a constant for the key size to the derived key pointer
            let proof := add(keyPtr, 0x3)

            // Compute level 1
            let scratchPtr1 := shl(0x5, and(key, 1))
            mstore(scratchPtr1, leaf)
            mstore(xor(scratchPtr1, 0x20), mload(proof))

            // Compute remaining proofs
            for {
                let i := 1
            } lt(i, height) {
                i := add(i, 1)
            } {
                proof := add(proof, 0x20)
                let scratchPtr := shl(0x5, and(shr(i, key), 1))
                mstore(scratchPtr, keccak256(0, 0x40))
                mstore(xor(scratchPtr, 0x20), mload(proof))
            }

            // Compute root hash
            root := keccak256(0, 0x40)
        }

        // Retrieve appropriate typehash constant based on height.
        bytes32 rootTypeHash = _lookupBulkOrderTypehash(height);

        // Use the typehash and the root hash to derive final bulk order hash
        assembly {
            mstore(0, rootTypeHash)
            mstore(0x20, root)
            bulkOrderHash := keccak256(0, 0x40)
        }
    }

    function _lookupBulkOrderTypehash(
        uint256 treeHeight
    ) internal pure returns (bytes32 typeHash) {
        // kecca256("BatchIntent(Intent[2] tree)Intent(address tokenIn,address tokenOut,address maker,address matchmaker,address source,uint16 feeBps,uint16 surplusBps,uint32 deadline,bool isPartiallyFillable,uint128 amountIn,uint128 endAmountOut,uint16 startAmountBps,uint16 expectedAmountBps)")
        if (treeHeight == 1) {
            typeHash = 0xa09b55b2b0f1611c4db0b312fc7063c8438a51497adc137310360981267db3ef;
        } else if (treeHeight == 2) {
            typeHash = 0x04440a5b85b1ac9a5931adc223455ce5ee3db7c8a2779030b9b8db54e2b85799;
        } else if (treeHeight == 3) {
            typeHash = 0x3201a8c99184de74eeba60a0f95ba5677e2d05308248224cff5d53314a25b768;
        } else if (treeHeight == 4) {
            typeHash = 0x5f9c3a9757945e640a0e6f0fa11269b3d05f3516b8377caf06a22bcd47f19a0c;
        } else if (treeHeight == 5) {
            typeHash = 0x49b5887b13176700800be2e1ec7eece8e4683eba84310a7a49f8acda23a84cc9;
        } else if (treeHeight == 6) {
            typeHash = 0x5aba5e52e068d52122f8220dda000664baf304f522ceface6940df335ca128fb;
        } else if (treeHeight == 7) {
            typeHash = 0xa004a0ff682c47acac1378afc7985f7c43efbd1adea9248e30d6afad0b0211e8;
        } else if (treeHeight == 8) {
            typeHash = 0x0745413a2bfe7693ff806398f8d59424166d165d7c16591bcfa1d4ce7cc168f5;
        } else {
            revert MerkleTreeTooLarge();
        }
    }

    function _assertValidSignature(
        address signer,
        bytes32 digest,
        bytes32 originalDigest,
        uint256 originalSignatureLength,
        bytes memory signature
    ) internal view {
        // Declare value for ecrecover equality or 1271 call success status
        bool success;

        // Utilize assembly to perform optimized signature verification check
        assembly {
            // Ensure that first word of scratch space is empty
            mstore(0, 0)

            // Get the length of the signature.
            let signatureLength := mload(signature)

            // Get the pointer to the value preceding the signature length
            // This will be used for temporary memory overrides - either the signature head for isValidSignature or the digest for ecrecover
            let wordBeforeSignaturePtr := sub(signature, 0x20)

            // Cache the current value behind the signature to restore it later
            let cachedWordBeforeSignature := mload(wordBeforeSignaturePtr)

            // Declare lenDiff + recoveredSigner scope to manage stack pressure
            {
                // Take the difference between the max ECDSA signature length and the actual signature length (overflow desired for any values > 65)
                // If the diff is not 0 or 1, it is not a valid ECDSA signature - move on to EIP1271 check
                let lenDiff := sub(65, signatureLength)

                // Declare variable for recovered signer
                let recoveredSigner

                // If diff is 0 or 1, it may be an ECDSA signature
                // Try to recover signer
                if iszero(gt(lenDiff, 1)) {
                    // Read the signature `s` value
                    let originalSignatureS := mload(add(signature, 0x40))

                    // Read the first byte of the word after `s`
                    // If the signature is 65 bytes, this will be the real `v` value
                    // If not, it will need to be modified - doing it this way saves an extra condition.
                    let v := byte(0, mload(add(signature, 0x60)))

                    // If lenDiff is 1, parse 64-byte signature as ECDSA
                    if lenDiff {
                        // Extract yParity from highest bit of vs and add 27 to get v
                        v := add(shr(0xff, originalSignatureS), 27)

                        // Extract canonical s from vs, all but the highest bit
                        // Temporarily overwrite the original `s` value in the signature
                        mstore(
                            add(signature, 0x40),
                            and(
                                originalSignatureS,
                                0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                            )
                        )
                    }
                    // Temporarily overwrite the signature length with `v` to conform to the expected input for ecrecover
                    mstore(signature, v)

                    // Temporarily overwrite the word before the length with `digest` to conform to the expected input for ecrecover
                    mstore(wordBeforeSignaturePtr, digest)

                    // Attempt to recover the signer for the given signature
                    // Do not check the call status as ecrecover will return a null address if the signature is invalid
                    pop(
                        staticcall(
                            gas(),
                            0x1, // Call ecrecover precompile
                            wordBeforeSignaturePtr, // Use data memory location
                            0x80, // Size of digest, v, r, and s
                            0, // Write result to scratch space
                            0x20 // Provide size of returned result
                        )
                    )

                    // Restore cached word before signature
                    mstore(wordBeforeSignaturePtr, cachedWordBeforeSignature)

                    // Restore cached signature length
                    mstore(signature, signatureLength)

                    // Restore cached signature `s` value
                    mstore(add(signature, 0x40), originalSignatureS)

                    // Read the recovered signer from the buffer given as return space for ecrecover
                    recoveredSigner := mload(0)
                }

                // Set success to true if the signature provided was a valid
                // ECDSA signature and the signer is not the null address
                // Use gt instead of direct as success is used outside of assembly
                success := and(eq(signer, recoveredSigner), gt(signer, 0))
            }

            // If the signature was not verified with ecrecover, try EIP1271
            if iszero(success) {
                // Reset the original signature length
                mstore(signature, originalSignatureLength)

                // Temporarily overwrite the word before the signature length and use it as the
                // head of the signature input to `isValidSignature`, which has a value of 64
                mstore(wordBeforeSignaturePtr, 0x40)

                // Get pointer to use for the selector of `isValidSignature`
                let selectorPtr := sub(signature, 0x44)

                // Cache the value currently stored at the selector pointer
                let cachedWordOverwrittenBySelector := mload(selectorPtr)

                // Cache the value currently stored at the digest pointer
                let cachedWordOverwrittenByDigest := mload(sub(signature, 0x40))

                // Write the selector first, since it overlaps the digest
                mstore(selectorPtr, 0x44)

                // Next, write the original digest
                mstore(sub(signature, 0x40), originalDigest)

                // Call signer with `isValidSignature` to validate signature
                success := staticcall(
                    gas(),
                    signer,
                    selectorPtr,
                    add(originalSignatureLength, 0x64),
                    0,
                    0x20
                )

                // Determine if the signature is valid on successful calls
                if success {
                    // If first word of scratch space does not contain EIP-1271 signature selector, revert
                    if iszero(
                        eq(
                            mload(0),
                            0x1626ba7e00000000000000000000000000000000000000000000000000000000
                        )
                    ) {
                        success := 0
                    }
                }

                // Restore the cached values overwritten by selector, digest and signature head
                mstore(wordBeforeSignaturePtr, cachedWordBeforeSignature)
                mstore(selectorPtr, cachedWordOverwrittenBySelector)
                mstore(sub(signature, 0x40), cachedWordOverwrittenByDigest)
            }
        }

        if (!success) {
            revert InvalidSignature();
        }
    }
}

File 2 of 3 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

File 3 of 3 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AuthorizationIsExpired","type":"error"},{"inputs":[],"name":"AuthorizationIsInsufficient","type":"error"},{"inputs":[],"name":"AuthorizationIsNotPartiallyFillable","type":"error"},{"inputs":[],"name":"IntentIsCancelled","type":"error"},{"inputs":[],"name":"IntentIsExpired","type":"error"},{"inputs":[],"name":"IntentIsFilled","type":"error"},{"inputs":[],"name":"IntentIsNotPartiallyFillable","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSolution","type":"error"},{"inputs":[],"name":"MerkleTreeTooLarge","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsuccessfullCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"intentHash","type":"bytes32"}],"name":"IntentCancelled","type":"event"},{"anonymous":false,"inputs":[],"name":"IntentPosted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"intentHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"address","name":"maker","type":"address"},{"indexed":false,"internalType":"address","name":"solver","type":"address"},{"indexed":false,"internalType":"uint128","name":"amountIn","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"amountOut","type":"uint128"}],"name":"IntentSolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"intentHash","type":"bytes32"}],"name":"IntentValidated","type":"event"},{"inputs":[],"name":"AUTHORIZATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INTENT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"authorization","outputs":[{"internalType":"uint128","name":"maxAmountIn","type":"uint128"},{"internalType":"uint128","name":"minAmountOut","type":"uint128"},{"internalType":"uint32","name":"blockDeadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent","name":"intent","type":"tuple"},{"internalType":"address","name":"authorizedSolver","type":"address"},{"components":[{"internalType":"uint128","name":"maxAmountIn","type":"uint128"},{"internalType":"uint128","name":"minAmountOut","type":"uint128"},{"internalType":"uint32","name":"blockDeadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"}],"internalType":"struct Memswap.Authorization","name":"auth","type":"tuple"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent[]","name":"intents","type":"tuple[]"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"intentHash","type":"bytes32"},{"internalType":"address","name":"authorizedSolver","type":"address"},{"components":[{"internalType":"uint128","name":"maxAmountIn","type":"uint128"},{"internalType":"uint128","name":"minAmountOut","type":"uint128"},{"internalType":"uint32","name":"blockDeadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"}],"internalType":"struct Memswap.Authorization","name":"auth","type":"tuple"}],"name":"getAuthorizationHash","outputs":[{"internalType":"bytes32","name":"authorizationHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent","name":"intent","type":"tuple"}],"name":"getIntentHash","outputs":[{"internalType":"bytes32","name":"intentHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"intentStatus","outputs":[{"internalType":"bool","name":"isValidated","type":"bool"},{"internalType":"bool","name":"isCancelled","type":"bool"},{"internalType":"uint128","name":"amountFilled","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent","name":"","type":"tuple"}],"name":"post","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent","name":"intent","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct Memswap.Solution","name":"solution","type":"tuple"}],"name":"solve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent","name":"intent","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct Memswap.Solution","name":"solution","type":"tuple"}],"name":"solveWithOnChainAuthorizationCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent","name":"intent","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct Memswap.Solution","name":"solution","type":"tuple"},{"components":[{"internalType":"uint128","name":"maxAmountIn","type":"uint128"},{"internalType":"uint128","name":"minAmountOut","type":"uint128"},{"internalType":"uint32","name":"blockDeadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"}],"internalType":"struct Memswap.Authorization","name":"auth","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"solveWithSignatureAuthorizationCheck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"matchmaker","type":"address"},{"internalType":"address","name":"source","type":"address"},{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"uint16","name":"surplusBps","type":"uint16"},{"internalType":"uint32","name":"deadline","type":"uint32"},{"internalType":"bool","name":"isPartiallyFillable","type":"bool"},{"internalType":"uint128","name":"amountIn","type":"uint128"},{"internalType":"uint128","name":"endAmountOut","type":"uint128"},{"internalType":"uint16","name":"startAmountBps","type":"uint16"},{"internalType":"uint16","name":"expectedAmountBps","type":"uint16"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Memswap.Intent[]","name":"intents","type":"tuple[]"}],"name":"validate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e060405234801561001057600080fd5b506001600055604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fa824f82ad76641f06bd470e908066402dd197198c1fad30f8a92d22b46bbcf5e918101919091527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b3606082015246608082018190523060a08301529060c00160408051808303601f190181529082905280516020918201206080526d082eae8d0dee4d2f4c2e8d2dedc560931b908201527f6279746573333220696e74656e74486173682c00000000000000000000000000602e8201527f6164647265737320617574686f72697a6564536f6c7665722c0000000000000060418201527f75696e74313238206d6178416d6f756e74496e2c000000000000000000000000605a8201527f75696e74313238206d696e416d6f756e744f75742c0000000000000000000000606e8201527f75696e74333220626c6f636b446561646c696e652c000000000000000000000060838201527f626f6f6c2069735061727469616c6c7946696c6c61626c6500000000000000006098820152602960f81b60b082015260b10160408051601f1981840301815290829052805160209182012060a052610386910166092dce8cadce8560cb1b81526f1859191c995cdcc81d1bdad95b925b8b60821b6007820152701859191c995cdcc81d1bdad95b93dd5d0b607a1b60178201526d1859191c995cdcc81b585ad95c8b60921b60288201527f61646472657373206d617463686d616b65722c0000000000000000000000000060368201526e1859191c995cdcc81cdbdd5c98d94b608a1b60498201526d1d5a5b9d0c4d88199959509c1ccb60921b6058820152711d5a5b9d0c4d881cdd5c9c1b1d5cd09c1ccb60721b60668201526f1d5a5b9d0ccc88191958591b1a5b994b60821b60788201527f626f6f6c2069735061727469616c6c7946696c6c61626c652c000000000000006088820152701d5a5b9d0c4c8e08185b5bdd5b9d125b8b607a1b60a18201527f75696e7431323820656e64416d6f756e744f75742c000000000000000000000060b28201527f75696e743136207374617274416d6f756e744270732c0000000000000000000060c78201527f75696e743136206578706563746564416d6f756e74427073000000000000000060dd820152602960f81b60f582015260f60190565b60408051601f19818403018152919052805160209091012060c0525060805160a05160c0516121de6103e6600039600081816103fc015261070a0152600081816101fb01526103880152600081816102c3015261137f01526121de6000f3fe6080604052600436106100e15760003560e01c80636b05d53b1161007f578063a42aeab011610059578063a42aeab0146103ca578063b082a274146103ea578063ccb8b9411461041e578063f27cab7b1461043e57600080fd5b80636b05d53b146103565780637339651214610376578063838d1ee1146103aa57600080fd5b8063219c7a15116100bb578063219c7a15146101c85780632adf642d146102915780633644e515146102b15780635c6741c0146102e557600080fd5b80630ff1b4e0146100ed578063181262f41461010f578063195508341461012f57600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004611879565b61045e565b005b34801561011b57600080fd5b5061010d61012a3660046118dd565b610553565b34801561013b57600080fd5b5061018b61014a36600461191a565b600260205260009081526040902080546001909101546001600160801b0380831692600160801b9004169063ffffffff811690640100000000900460ff1684565b604080516001600160801b03958616815294909316602085015263ffffffff90911691830191909152151560608201526080015b60405180910390f35b3480156101d457600080fd5b506102836101e3366004611a75565b805160208083015160408085015160609586015182517f000000000000000000000000000000000000000000000000000000000000000081870152808401999099526001600160a01b0397909716958801959095526001600160801b039384166080880152921660a086015263ffffffff90921660c085015291151560e08085019190915282518085039091018152610100909301909152815191012090565b6040519081526020016101bf565b34801561029d57600080fd5b5061010d6102ac366004611ab4565b61057f565b3480156102bd57600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156102f157600080fd5b5061033061030036600461191a565b60016020526000908152604090205460ff808216916101008104909116906201000090046001600160801b031683565b60408051931515845291151560208401526001600160801b0316908201526060016101bf565b34801561036257600080fd5b5061010d610371366004611b3b565b610624565b34801561038257600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b3480156103b657600080fd5b506102836103c5366004611dd2565b610706565b3480156103d657600080fd5b5061010d6103e5366004611879565b61082e565b3480156103f657600080fd5b506102837f000000000000000000000000000000000000000000000000000000000000000081565b34801561042a57600080fd5b5061010d610439366004611ab4565b6108aa565b34801561044a57600080fd5b5061010d610459366004611e07565b6109fa565b610466610aad565b60006104746103c584611e5f565b9050600081336040516020016104a692919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60408051808303601f19018152828252805160209182012060008181526002835283902060808501845280546001600160801b038082168752600160801b909104169285019290925260019091015463ffffffff811684840152640100000000900460ff16151560608085019190915290935061053391839161052e91908801908801611e71565b610b0a565b61054285858360200151610ba9565b50505061054f6001600055565b5050565b6040517f6eb1fe1ed1c00dd61527fc7354d8d0c434c5c8b03017905e72bea0d2be20200c90600090a150565b8060005b8181101561061e573684848381811061059e5761059e611e95565b90506020028101906105b09190611eab565b905060006105c06103c583611e5f565b90506105e9816105d66060850160408601611ecc565b6105e46101a0860186611ee9565b61130d565b60405181907f3bd1ea4a475636648bca86ed7425633364005c4642017950f960629e3201dbaf90600090a25050600101610583565b50505050565b61062c610aad565b600061063a6103c587611e5f565b9050600061065282336101e336899003890189611f37565b9050600061065f8261136f565b90506106b661067460808a0160608b01611ecc565b82838888905089898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113b592505050565b6106d86106c836889003880188611f37565b61052e60608a0160408b01611e71565b6106f288886106ed60408a0160208b01611e71565b610ba9565b5050506106ff6001600055565b5050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000826000015183602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e61018001516040516020016108119e9d9c9b9a999897969594939291909d8e526001600160a01b039c8d1660208f01529a8c1660408e0152988b1660608d0152968a1660808c01529490981660a08a015261ffff92831660c08a015290821660e089015263ffffffff166101008801529415156101208701526001600160801b03908116610140870152166101608501528216610180840152166101a08201526101c00190565b604051602081830303815290604052805190602001209050919050565b610836610aad565b60006108486080840160608501611ecc565b6001600160a01b03161415801561087757503361086b6080840160608501611ecc565b6001600160a01b031614155b15610894576040516282b42960e81b815260040160405180910390fd5b6108a082826000610ba9565b61054f6001600055565b6108b2610aad565b8060005b818110156109ee57368484838181106108d1576108d1611e95565b90506020028101906108e39190611eab565b9050336108f66060830160408401611ecc565b6001600160a01b03161461091c576040516282b42960e81b815260040160405180910390fd5b600061092a6103c583611e5f565b600081815260016020818152604080842081516060810183528154620100008082046001600160801b039081168487019081528985528488018981528b8b529890975283519751965161ffff1990931697151561ff00191697909717610100961515969096029590951771ffffffffffffffffffffffffffffffff0000191695169093029390931790925590519293509183917fc08eb64db16a39d2848960af04e3f16fb404d9d436a9f0e9d7d0d4854715c9dc91a28360010193505050506108b6565b505061054f6001600055565b33610a0b6080850160608601611ecc565b6001600160a01b031614610a31576040516282b42960e81b815260040160405180910390fd5b6000610a3f6103c585611e5f565b905060008184604051602001610a7192919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60408051601f1981840301815291815281516020928301206000818152600290935291209091508390610aa48282611f53565b50505050505050565b600260005403610b035760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640160405180910390fd5b6002600055565b43826040015163ffffffff161015610b35576040516301a8648f60e51b815260040160405180910390fd5b81516001600160801b0380831691161015610b635760405163062e314b60e01b815260040160405180910390fd5b8160600151158015610b8b5750806001600160801b031682600001516001600160801b031614155b1561054f5760405163081a857d60e01b815260040160405180910390fd5b6000610bb76103c585611e5f565b905042610bcb610100860160e08701611fdb565b63ffffffff161015610bf0576040516340db9d8d60e11b815260040160405180910390fd5b6000818152600160209081526040918290208251606081018452905460ff80821615158352610100820416158015938301939093526201000090046001600160801b031692810192909252610c585760405163460f1ebb60e11b815260040160405180910390fd5b8051610c8057610c8082610c726060880160408901611ecc565b6105e46101a0890189611ee9565b60408101516000908190610c9c61014089016101208a01611e71565b610ca6919061200e565b9050806001600160801b0316600003610cd25760405163dbce013760e01b815260040160405180910390fd5b610ce461012088016101008901612035565b158015610d1157506001600160801b038116610d066060880160408901611e71565b6001600160801b0316105b15610d2f57604051634f2ffed760e01b815260040160405180910390fd5b6001600160801b038116610d496060880160408901611e71565b6001600160801b031611610d6c57610d676060870160408801611e71565b610d6e565b805b600085815260016020526040902080549193508391600290610da09084906201000090046001600160801b0316612052565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550506000816001600160801b03161115610e1357610e13610dea6060880160408901611ecc565b610df76020880188611ecc565b610e0460208a018a611ecc565b846001600160801b03166114aa565b6000610e226020870187611ecc565b6001600160a01b0316610e386020880188611ee9565b604051610e46929190612072565b6000604051808303816000865af19150503d8060008114610e83576040519150601f19603f3d011682016040523d82523d6000602084013e610e88565b606091505b5050905080610ea957604051629c48b560e51b815260040160405180910390fd5b506000610ebe61016088016101408901611e71565b90506000612710610ed76101808a016101608b01612082565b610ee59061ffff168461209d565b610eef91906120de565b610ef99083612052565b90506000612710610f126101a08b016101808c01612082565b610f209061ffff168561209d565b610f2a91906120de565b610f349084612052565b9050600063ffffffff4216610f506101008c0160e08d01611fdb565b63ffffffff1611610f62576001610f7e565b42610f746101008c0160e08d01611fdb565b610f7e9190612104565b63ffffffff16610f8e858561200e565b610f9891906120de565b610fa2908461200e565b9050876001600160801b0316816001600160801b03161015610fd75760405163d9c1988f60e01b815260040160405180910390fd5b600080610fea60408d0160208e01611ecc565b6001600160a01b0316146110965761100860408c0160208d01611ecc565b6001600160a01b031663dd62ed3e61102360208d018d611ecc565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa15801561106d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110919190612121565b611098565b475b9050816001600160801b03168110156110c45760405163d9c1988f60e01b815260040160405180910390fd5b60006110d660a08d0160808e01611ecc565b6001600160a01b03161461122b576000806110f760c08e0160a08f01612082565b61ffff1611156111425761271061111460c08e0160a08f01612082565b6111229061ffff168561209d565b61112c91906120de565b61113f906001600160801b03168261213a565b90505b600061115460e08e0160c08f01612082565b61ffff1611801561116d5750836001600160801b031682115b801561118a5750826001600160801b0316846001600160801b0316115b156111da576127106111a260e08e0160c08f01612082565b61ffff166111b96001600160801b0387168561214d565b6111c39190612160565b6111cd9190612177565b6111d7908261213a565b90505b80156112295761121c6111f060208d018d611ecc565b8d60800160208101906112039190611ecc565b8e60200160208101906112169190611ecc565b846114aa565b611226818361214d565b91505b505b80156112645761126461124160208c018c611ecc565b61125160608e0160408f01611ecc565b8d60200160208101906112169190611ecc565b877fd6e19ae1c533d0e059acf6ce7b615562c06c54e924b5281d5b83fb2496bb638661129360208e018e611ecc565b8d60200160208101906112a69190611ecc565b8e60400160208101906112b99190611ecc565b604080516001600160a01b03948516815292841660208401529216818301523360608201526001600160801b038a81166080830152851660a082015290519081900360c00190a25050505050505050505050565b61134e848484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115ae92505050565b5050506000908152600160208190526040909120805460ff19169091179055565b60405161190160f01b60208201527f0000000000000000000000000000000000000000000000000000000000000000602282015260428101829052600090606201610811565b60008060005281516020830380518260410360006001821161141e576040870151606088015160001a83156113fd57601b8260ff1c0190506001600160ff1b03821660408a01525b88528a85526020600060808760015afa508385528588526040880152506000515b8a148a1515169450849050611481578585526040825260448503925082516040860351604485528860408803526020600060648a01878e5afa9550851561147457630b135d3f60e11b6000511461147457600095505b828452908452603f198601525b505050806114a257604051638baa579f60e01b815260040160405180910390fd5b505050505050565b60006001600160a01b038316611513576040516001600160a01b038516908390600081818185875af1925050503d8060008114611503576040519150601f19603f3d011682016040523d82523d6000602084013e611508565b606091505b505080915050611591565b6040516323b872dd60e01b81526001600160a01b0386811660048301528581166024830152604482018490528416906323b872dd906064016020604051808303816000875af115801561156a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158e919061218b565b90505b806106ff57604051629c48b560e51b815260040160405180910390fd5b336001600160a01b038316036115c357505050565b60006115ce8461136f565b825190915060006102e26062198301106002601d8401601f1610161561160a576115f8848761161a565b95506116038661136f565b905061160d565b50815b6114a285828585886113b5565b600080600084516001811660410380820360051c9250808752806020018701915050805160e81c6003820191506001811660051b868152825160208218525060015b8381101561168957604060002082821c60051b60209081169182529384018051919094185260010161165c565b50505060406000209150600061169e826116b6565b60009081526020939093525050604090209392505050565b6000816001036116e757507fa09b55b2b0f1611c4db0b312fc7063c8438a51497adc137310360981267db3ef919050565b8160020361171657507f04440a5b85b1ac9a5931adc223455ce5ee3db7c8a2779030b9b8db54e2b85799919050565b8160030361174557507f3201a8c99184de74eeba60a0f95ba5677e2d05308248224cff5d53314a25b768919050565b8160040361177457507f5f9c3a9757945e640a0e6f0fa11269b3d05f3516b8377caf06a22bcd47f19a0c919050565b816005036117a357507f49b5887b13176700800be2e1ec7eece8e4683eba84310a7a49f8acda23a84cc9919050565b816006036117d257507f5aba5e52e068d52122f8220dda000664baf304f522ceface6940df335ca128fb919050565b8160070361180157507fa004a0ff682c47acac1378afc7985f7c43efbd1adea9248e30d6afad0b0211e8919050565b8160080361183057507f0745413a2bfe7693ff806398f8d59424166d165d7c16591bcfa1d4ce7cc168f5919050565b6040516343d8a7b560e01b815260040160405180910390fd5b919050565b60006101c0828403121561186157600080fd5b50919050565b60006060828403121561186157600080fd5b6000806040838503121561188c57600080fd5b823567ffffffffffffffff808211156118a457600080fd5b6118b08683870161184e565b935060208501359150808211156118c657600080fd5b506118d385828601611867565b9150509250929050565b6000602082840312156118ef57600080fd5b813567ffffffffffffffff81111561190657600080fd5b6119128482850161184e565b949350505050565b60006020828403121561192c57600080fd5b5035919050565b6001600160a01b038116811461194857600080fd5b50565b803561184981611933565b634e487b7160e01b600052604160045260246000fd5b6040516101c0810167ffffffffffffffff8111828210171561199057611990611956565b60405290565b6001600160801b038116811461194857600080fd5b803561184981611996565b63ffffffff8116811461194857600080fd5b8035611849816119b6565b801515811461194857600080fd5b8035611849816119d3565b6000608082840312156119fe57600080fd5b6040516080810181811067ffffffffffffffff82111715611a2157611a21611956565b6040529050808235611a3281611996565b81526020830135611a4281611996565b60208201526040830135611a55816119b6565b60408201526060830135611a68816119d3565b6060919091015292915050565b600080600060c08486031215611a8a57600080fd5b833592506020840135611a9c81611933565b9150611aab85604086016119ec565b90509250925092565b60008060208385031215611ac757600080fd5b823567ffffffffffffffff80821115611adf57600080fd5b818501915085601f830112611af357600080fd5b813581811115611b0257600080fd5b8660208260051b8501011115611b1757600080fd5b60209290920196919550909350505050565b60006080828403121561186157600080fd5b600080600080600060e08688031215611b5357600080fd5b853567ffffffffffffffff80821115611b6b57600080fd5b611b7789838a0161184e565b96506020880135915080821115611b8d57600080fd5b611b9989838a01611867565b9550611ba88960408a01611b29565b945060c0880135915080821115611bbe57600080fd5b818801915088601f830112611bd257600080fd5b813581811115611be157600080fd5b896020828501011115611bf357600080fd5b9699959850939650602001949392505050565b803561ffff8116811461184957600080fd5b600082601f830112611c2957600080fd5b813567ffffffffffffffff80821115611c4457611c44611956565b604051601f8301601f19908116603f01168101908282118183101715611c6c57611c6c611956565b81604052838152866020858801011115611c8557600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101c08284031215611cb857600080fd5b611cc061196c565b9050611ccb8261194b565b8152611cd96020830161194b565b6020820152611cea6040830161194b565b6040820152611cfb6060830161194b565b6060820152611d0c6080830161194b565b6080820152611d1d60a08301611c06565b60a0820152611d2e60c08301611c06565b60c0820152611d3f60e083016119c8565b60e0820152610100611d528184016119e1565b90820152610120611d648382016119ab565b90820152610140611d768382016119ab565b90820152610160611d88838201611c06565b90820152610180611d9a838201611c06565b908201526101a08281013567ffffffffffffffff811115611dba57600080fd5b611dc685828601611c18565b82840152505092915050565b600060208284031215611de457600080fd5b813567ffffffffffffffff811115611dfb57600080fd5b61191284828501611ca5565b600080600060c08486031215611e1c57600080fd5b833567ffffffffffffffff811115611e3357600080fd5b611e3f8682870161184e565b9350506020840135611e5081611933565b9150611aab8560408601611b29565b6000611e6b3683611ca5565b92915050565b600060208284031215611e8357600080fd5b8135611e8e81611996565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600082356101be19833603018112611ec257600080fd5b9190910192915050565b600060208284031215611ede57600080fd5b8135611e8e81611933565b6000808335601e19843603018112611f0057600080fd5b83018035915067ffffffffffffffff821115611f1b57600080fd5b602001915036819003821315611f3057600080fd5b9250929050565b600060808284031215611f4957600080fd5b611e8e83836119ec565b8135611f5e81611996565b6001600160801b03811690506001600160801b031981818454161783556020840135611f8981611996565b60801b16178155600181016040830135611fa2816119b6565b81546060850135611fb2816119d3565b64ff0000000081151560201b1663ffffffff841664ffffffffff19841617178455505050505050565b600060208284031215611fed57600080fd5b8135611e8e816119b6565b634e487b7160e01b600052601160045260246000fd5b6001600160801b0382811682821603908082111561202e5761202e611ff8565b5092915050565b60006020828403121561204757600080fd5b8135611e8e816119d3565b6001600160801b0381811683821601908082111561202e5761202e611ff8565b8183823760009101908152919050565b60006020828403121561209457600080fd5b611e8e82611c06565b6001600160801b038181168382160280821691908281146120c0576120c0611ff8565b505092915050565b634e487b7160e01b600052601260045260246000fd5b60006001600160801b03808416806120f8576120f86120c8565b92169190910492915050565b63ffffffff82811682821603908082111561202e5761202e611ff8565b60006020828403121561213357600080fd5b5051919050565b80820180821115611e6b57611e6b611ff8565b81810381811115611e6b57611e6b611ff8565b8082028115828204841417611e6b57611e6b611ff8565b600082612186576121866120c8565b500490565b60006020828403121561219d57600080fd5b8151611e8e816119d356fea26469706673582212204ebc1eee07a304322fc1497b5f35ff775094a24d4b710f338495e7054bf8164b64736f6c63430008130033

Deployed Bytecode

0x6080604052600436106100e15760003560e01c80636b05d53b1161007f578063a42aeab011610059578063a42aeab0146103ca578063b082a274146103ea578063ccb8b9411461041e578063f27cab7b1461043e57600080fd5b80636b05d53b146103565780637339651214610376578063838d1ee1146103aa57600080fd5b8063219c7a15116100bb578063219c7a15146101c85780632adf642d146102915780633644e515146102b15780635c6741c0146102e557600080fd5b80630ff1b4e0146100ed578063181262f41461010f578063195508341461012f57600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004611879565b61045e565b005b34801561011b57600080fd5b5061010d61012a3660046118dd565b610553565b34801561013b57600080fd5b5061018b61014a36600461191a565b600260205260009081526040902080546001909101546001600160801b0380831692600160801b9004169063ffffffff811690640100000000900460ff1684565b604080516001600160801b03958616815294909316602085015263ffffffff90911691830191909152151560608201526080015b60405180910390f35b3480156101d457600080fd5b506102836101e3366004611a75565b805160208083015160408085015160609586015182517f2e7c6c83eca6a9f817af26781ec5999f18b71fda5627382cb9191900b438a6bd81870152808401999099526001600160a01b0397909716958801959095526001600160801b039384166080880152921660a086015263ffffffff90921660c085015291151560e08085019190915282518085039091018152610100909301909152815191012090565b6040519081526020016101bf565b34801561029d57600080fd5b5061010d6102ac366004611ab4565b61057f565b3480156102bd57600080fd5b506102837f5d956f06bcaa5e673dffff063451891bc4be7bb69d635776ec22af717b3e76c181565b3480156102f157600080fd5b5061033061030036600461191a565b60016020526000908152604090205460ff808216916101008104909116906201000090046001600160801b031683565b60408051931515845291151560208401526001600160801b0316908201526060016101bf565b34801561036257600080fd5b5061010d610371366004611b3b565b610624565b34801561038257600080fd5b506102837f2e7c6c83eca6a9f817af26781ec5999f18b71fda5627382cb9191900b438a6bd81565b3480156103b657600080fd5b506102836103c5366004611dd2565b610706565b3480156103d657600080fd5b5061010d6103e5366004611879565b61082e565b3480156103f657600080fd5b506102837f577dc98febdc18c4443a7dc4c3ed332ac5ee708f6b8a0a51d5139497d0ff57d481565b34801561042a57600080fd5b5061010d610439366004611ab4565b6108aa565b34801561044a57600080fd5b5061010d610459366004611e07565b6109fa565b610466610aad565b60006104746103c584611e5f565b9050600081336040516020016104a692919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60408051808303601f19018152828252805160209182012060008181526002835283902060808501845280546001600160801b038082168752600160801b909104169285019290925260019091015463ffffffff811684840152640100000000900460ff16151560608085019190915290935061053391839161052e91908801908801611e71565b610b0a565b61054285858360200151610ba9565b50505061054f6001600055565b5050565b6040517f6eb1fe1ed1c00dd61527fc7354d8d0c434c5c8b03017905e72bea0d2be20200c90600090a150565b8060005b8181101561061e573684848381811061059e5761059e611e95565b90506020028101906105b09190611eab565b905060006105c06103c583611e5f565b90506105e9816105d66060850160408601611ecc565b6105e46101a0860186611ee9565b61130d565b60405181907f3bd1ea4a475636648bca86ed7425633364005c4642017950f960629e3201dbaf90600090a25050600101610583565b50505050565b61062c610aad565b600061063a6103c587611e5f565b9050600061065282336101e336899003890189611f37565b9050600061065f8261136f565b90506106b661067460808a0160608b01611ecc565b82838888905089898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113b592505050565b6106d86106c836889003880188611f37565b61052e60608a0160408b01611e71565b6106f288886106ed60408a0160208b01611e71565b610ba9565b5050506106ff6001600055565b5050505050565b60007f577dc98febdc18c4443a7dc4c3ed332ac5ee708f6b8a0a51d5139497d0ff57d4826000015183602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e61018001516040516020016108119e9d9c9b9a999897969594939291909d8e526001600160a01b039c8d1660208f01529a8c1660408e0152988b1660608d0152968a1660808c01529490981660a08a015261ffff92831660c08a015290821660e089015263ffffffff166101008801529415156101208701526001600160801b03908116610140870152166101608501528216610180840152166101a08201526101c00190565b604051602081830303815290604052805190602001209050919050565b610836610aad565b60006108486080840160608501611ecc565b6001600160a01b03161415801561087757503361086b6080840160608501611ecc565b6001600160a01b031614155b15610894576040516282b42960e81b815260040160405180910390fd5b6108a082826000610ba9565b61054f6001600055565b6108b2610aad565b8060005b818110156109ee57368484838181106108d1576108d1611e95565b90506020028101906108e39190611eab565b9050336108f66060830160408401611ecc565b6001600160a01b03161461091c576040516282b42960e81b815260040160405180910390fd5b600061092a6103c583611e5f565b600081815260016020818152604080842081516060810183528154620100008082046001600160801b039081168487019081528985528488018981528b8b529890975283519751965161ffff1990931697151561ff00191697909717610100961515969096029590951771ffffffffffffffffffffffffffffffff0000191695169093029390931790925590519293509183917fc08eb64db16a39d2848960af04e3f16fb404d9d436a9f0e9d7d0d4854715c9dc91a28360010193505050506108b6565b505061054f6001600055565b33610a0b6080850160608601611ecc565b6001600160a01b031614610a31576040516282b42960e81b815260040160405180910390fd5b6000610a3f6103c585611e5f565b905060008184604051602001610a7192919091825260601b6bffffffffffffffffffffffff1916602082015260340190565b60408051601f1981840301815291815281516020928301206000818152600290935291209091508390610aa48282611f53565b50505050505050565b600260005403610b035760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640160405180910390fd5b6002600055565b43826040015163ffffffff161015610b35576040516301a8648f60e51b815260040160405180910390fd5b81516001600160801b0380831691161015610b635760405163062e314b60e01b815260040160405180910390fd5b8160600151158015610b8b5750806001600160801b031682600001516001600160801b031614155b1561054f5760405163081a857d60e01b815260040160405180910390fd5b6000610bb76103c585611e5f565b905042610bcb610100860160e08701611fdb565b63ffffffff161015610bf0576040516340db9d8d60e11b815260040160405180910390fd5b6000818152600160209081526040918290208251606081018452905460ff80821615158352610100820416158015938301939093526201000090046001600160801b031692810192909252610c585760405163460f1ebb60e11b815260040160405180910390fd5b8051610c8057610c8082610c726060880160408901611ecc565b6105e46101a0890189611ee9565b60408101516000908190610c9c61014089016101208a01611e71565b610ca6919061200e565b9050806001600160801b0316600003610cd25760405163dbce013760e01b815260040160405180910390fd5b610ce461012088016101008901612035565b158015610d1157506001600160801b038116610d066060880160408901611e71565b6001600160801b0316105b15610d2f57604051634f2ffed760e01b815260040160405180910390fd5b6001600160801b038116610d496060880160408901611e71565b6001600160801b031611610d6c57610d676060870160408801611e71565b610d6e565b805b600085815260016020526040902080549193508391600290610da09084906201000090046001600160801b0316612052565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550506000816001600160801b03161115610e1357610e13610dea6060880160408901611ecc565b610df76020880188611ecc565b610e0460208a018a611ecc565b846001600160801b03166114aa565b6000610e226020870187611ecc565b6001600160a01b0316610e386020880188611ee9565b604051610e46929190612072565b6000604051808303816000865af19150503d8060008114610e83576040519150601f19603f3d011682016040523d82523d6000602084013e610e88565b606091505b5050905080610ea957604051629c48b560e51b815260040160405180910390fd5b506000610ebe61016088016101408901611e71565b90506000612710610ed76101808a016101608b01612082565b610ee59061ffff168461209d565b610eef91906120de565b610ef99083612052565b90506000612710610f126101a08b016101808c01612082565b610f209061ffff168561209d565b610f2a91906120de565b610f349084612052565b9050600063ffffffff4216610f506101008c0160e08d01611fdb565b63ffffffff1611610f62576001610f7e565b42610f746101008c0160e08d01611fdb565b610f7e9190612104565b63ffffffff16610f8e858561200e565b610f9891906120de565b610fa2908461200e565b9050876001600160801b0316816001600160801b03161015610fd75760405163d9c1988f60e01b815260040160405180910390fd5b600080610fea60408d0160208e01611ecc565b6001600160a01b0316146110965761100860408c0160208d01611ecc565b6001600160a01b031663dd62ed3e61102360208d018d611ecc565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa15801561106d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110919190612121565b611098565b475b9050816001600160801b03168110156110c45760405163d9c1988f60e01b815260040160405180910390fd5b60006110d660a08d0160808e01611ecc565b6001600160a01b03161461122b576000806110f760c08e0160a08f01612082565b61ffff1611156111425761271061111460c08e0160a08f01612082565b6111229061ffff168561209d565b61112c91906120de565b61113f906001600160801b03168261213a565b90505b600061115460e08e0160c08f01612082565b61ffff1611801561116d5750836001600160801b031682115b801561118a5750826001600160801b0316846001600160801b0316115b156111da576127106111a260e08e0160c08f01612082565b61ffff166111b96001600160801b0387168561214d565b6111c39190612160565b6111cd9190612177565b6111d7908261213a565b90505b80156112295761121c6111f060208d018d611ecc565b8d60800160208101906112039190611ecc565b8e60200160208101906112169190611ecc565b846114aa565b611226818361214d565b91505b505b80156112645761126461124160208c018c611ecc565b61125160608e0160408f01611ecc565b8d60200160208101906112169190611ecc565b877fd6e19ae1c533d0e059acf6ce7b615562c06c54e924b5281d5b83fb2496bb638661129360208e018e611ecc565b8d60200160208101906112a69190611ecc565b8e60400160208101906112b99190611ecc565b604080516001600160a01b03948516815292841660208401529216818301523360608201526001600160801b038a81166080830152851660a082015290519081900360c00190a25050505050505050505050565b61134e848484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115ae92505050565b5050506000908152600160208190526040909120805460ff19169091179055565b60405161190160f01b60208201527f5d956f06bcaa5e673dffff063451891bc4be7bb69d635776ec22af717b3e76c1602282015260428101829052600090606201610811565b60008060005281516020830380518260410360006001821161141e576040870151606088015160001a83156113fd57601b8260ff1c0190506001600160ff1b03821660408a01525b88528a85526020600060808760015afa508385528588526040880152506000515b8a148a1515169450849050611481578585526040825260448503925082516040860351604485528860408803526020600060648a01878e5afa9550851561147457630b135d3f60e11b6000511461147457600095505b828452908452603f198601525b505050806114a257604051638baa579f60e01b815260040160405180910390fd5b505050505050565b60006001600160a01b038316611513576040516001600160a01b038516908390600081818185875af1925050503d8060008114611503576040519150601f19603f3d011682016040523d82523d6000602084013e611508565b606091505b505080915050611591565b6040516323b872dd60e01b81526001600160a01b0386811660048301528581166024830152604482018490528416906323b872dd906064016020604051808303816000875af115801561156a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158e919061218b565b90505b806106ff57604051629c48b560e51b815260040160405180910390fd5b336001600160a01b038316036115c357505050565b60006115ce8461136f565b825190915060006102e26062198301106002601d8401601f1610161561160a576115f8848761161a565b95506116038661136f565b905061160d565b50815b6114a285828585886113b5565b600080600084516001811660410380820360051c9250808752806020018701915050805160e81c6003820191506001811660051b868152825160208218525060015b8381101561168957604060002082821c60051b60209081169182529384018051919094185260010161165c565b50505060406000209150600061169e826116b6565b60009081526020939093525050604090209392505050565b6000816001036116e757507fa09b55b2b0f1611c4db0b312fc7063c8438a51497adc137310360981267db3ef919050565b8160020361171657507f04440a5b85b1ac9a5931adc223455ce5ee3db7c8a2779030b9b8db54e2b85799919050565b8160030361174557507f3201a8c99184de74eeba60a0f95ba5677e2d05308248224cff5d53314a25b768919050565b8160040361177457507f5f9c3a9757945e640a0e6f0fa11269b3d05f3516b8377caf06a22bcd47f19a0c919050565b816005036117a357507f49b5887b13176700800be2e1ec7eece8e4683eba84310a7a49f8acda23a84cc9919050565b816006036117d257507f5aba5e52e068d52122f8220dda000664baf304f522ceface6940df335ca128fb919050565b8160070361180157507fa004a0ff682c47acac1378afc7985f7c43efbd1adea9248e30d6afad0b0211e8919050565b8160080361183057507f0745413a2bfe7693ff806398f8d59424166d165d7c16591bcfa1d4ce7cc168f5919050565b6040516343d8a7b560e01b815260040160405180910390fd5b919050565b60006101c0828403121561186157600080fd5b50919050565b60006060828403121561186157600080fd5b6000806040838503121561188c57600080fd5b823567ffffffffffffffff808211156118a457600080fd5b6118b08683870161184e565b935060208501359150808211156118c657600080fd5b506118d385828601611867565b9150509250929050565b6000602082840312156118ef57600080fd5b813567ffffffffffffffff81111561190657600080fd5b6119128482850161184e565b949350505050565b60006020828403121561192c57600080fd5b5035919050565b6001600160a01b038116811461194857600080fd5b50565b803561184981611933565b634e487b7160e01b600052604160045260246000fd5b6040516101c0810167ffffffffffffffff8111828210171561199057611990611956565b60405290565b6001600160801b038116811461194857600080fd5b803561184981611996565b63ffffffff8116811461194857600080fd5b8035611849816119b6565b801515811461194857600080fd5b8035611849816119d3565b6000608082840312156119fe57600080fd5b6040516080810181811067ffffffffffffffff82111715611a2157611a21611956565b6040529050808235611a3281611996565b81526020830135611a4281611996565b60208201526040830135611a55816119b6565b60408201526060830135611a68816119d3565b6060919091015292915050565b600080600060c08486031215611a8a57600080fd5b833592506020840135611a9c81611933565b9150611aab85604086016119ec565b90509250925092565b60008060208385031215611ac757600080fd5b823567ffffffffffffffff80821115611adf57600080fd5b818501915085601f830112611af357600080fd5b813581811115611b0257600080fd5b8660208260051b8501011115611b1757600080fd5b60209290920196919550909350505050565b60006080828403121561186157600080fd5b600080600080600060e08688031215611b5357600080fd5b853567ffffffffffffffff80821115611b6b57600080fd5b611b7789838a0161184e565b96506020880135915080821115611b8d57600080fd5b611b9989838a01611867565b9550611ba88960408a01611b29565b945060c0880135915080821115611bbe57600080fd5b818801915088601f830112611bd257600080fd5b813581811115611be157600080fd5b896020828501011115611bf357600080fd5b9699959850939650602001949392505050565b803561ffff8116811461184957600080fd5b600082601f830112611c2957600080fd5b813567ffffffffffffffff80821115611c4457611c44611956565b604051601f8301601f19908116603f01168101908282118183101715611c6c57611c6c611956565b81604052838152866020858801011115611c8557600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101c08284031215611cb857600080fd5b611cc061196c565b9050611ccb8261194b565b8152611cd96020830161194b565b6020820152611cea6040830161194b565b6040820152611cfb6060830161194b565b6060820152611d0c6080830161194b565b6080820152611d1d60a08301611c06565b60a0820152611d2e60c08301611c06565b60c0820152611d3f60e083016119c8565b60e0820152610100611d528184016119e1565b90820152610120611d648382016119ab565b90820152610140611d768382016119ab565b90820152610160611d88838201611c06565b90820152610180611d9a838201611c06565b908201526101a08281013567ffffffffffffffff811115611dba57600080fd5b611dc685828601611c18565b82840152505092915050565b600060208284031215611de457600080fd5b813567ffffffffffffffff811115611dfb57600080fd5b61191284828501611ca5565b600080600060c08486031215611e1c57600080fd5b833567ffffffffffffffff811115611e3357600080fd5b611e3f8682870161184e565b9350506020840135611e5081611933565b9150611aab8560408601611b29565b6000611e6b3683611ca5565b92915050565b600060208284031215611e8357600080fd5b8135611e8e81611996565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600082356101be19833603018112611ec257600080fd5b9190910192915050565b600060208284031215611ede57600080fd5b8135611e8e81611933565b6000808335601e19843603018112611f0057600080fd5b83018035915067ffffffffffffffff821115611f1b57600080fd5b602001915036819003821315611f3057600080fd5b9250929050565b600060808284031215611f4957600080fd5b611e8e83836119ec565b8135611f5e81611996565b6001600160801b03811690506001600160801b031981818454161783556020840135611f8981611996565b60801b16178155600181016040830135611fa2816119b6565b81546060850135611fb2816119d3565b64ff0000000081151560201b1663ffffffff841664ffffffffff19841617178455505050505050565b600060208284031215611fed57600080fd5b8135611e8e816119b6565b634e487b7160e01b600052601160045260246000fd5b6001600160801b0382811682821603908082111561202e5761202e611ff8565b5092915050565b60006020828403121561204757600080fd5b8135611e8e816119d3565b6001600160801b0381811683821601908082111561202e5761202e611ff8565b8183823760009101908152919050565b60006020828403121561209457600080fd5b611e8e82611c06565b6001600160801b038181168382160280821691908281146120c0576120c0611ff8565b505092915050565b634e487b7160e01b600052601260045260246000fd5b60006001600160801b03808416806120f8576120f86120c8565b92169190910492915050565b63ffffffff82811682821603908082111561202e5761202e611ff8565b60006020828403121561213357600080fd5b5051919050565b80820180821115611e6b57611e6b611ff8565b81810381811115611e6b57611e6b611ff8565b8082028115828204841417611e6b57611e6b611ff8565b600082612186576121866120c8565b500490565b60006020828403121561219d57600080fd5b8151611e8e816119d356fea26469706673582212204ebc1eee07a304322fc1497b5f35ff775094a24d4b710f338495e7054bf8164b64736f6c63430008130033

Block Transaction Difficulty 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
Loading...
Loading
[ Download: CSV Export  ]
[ 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.