Contract

0x073f71e7fc5A03dA2bD9AC84253665C2c575ae4D

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

-

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
4110152024-12-14 18:30:0815 days ago1734201008  Contract Creation0 S
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AvoForwarder

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
default evmVersion
File 1 of 11 : AvoForwarder.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import { IAvoFactory } from "./interfaces/IAvoFactory.sol";
import { IAvoForwarder } from "./interfaces/IAvoForwarder.sol";
import { IAvocadoMultisigV1 } from "./interfaces/IAvocadoMultisigV1.sol";

// empty interface used for Natspec docs for nice layout in automatically generated docs:
//
/// @title  AvoForwarder v1.1.0
/// @notice Handles executing authorized actions (through signatures) at Avocados, triggered by allow-listed broadcasters.
/// @dev Only compatible with forwarding `cast` calls to Avocado smart wallet contracts.
/// This is not a generic forwarder.
/// This is NOT a "TrustedForwarder" as proposed in EIP-2770, see info in Avocado smart wallet contracts.
///
/// Does not validate the EIP712 signature (instead this is done in the smart wallet itself).
///
/// Upgradeable through AvoForwarderProxy
interface AvoForwarder_V1 {}

abstract contract AvoForwarderConstants is IAvoForwarder {
    /// @notice AvoFactory (proxy) used to deploy new Avocado smart wallets.
    //
    // @dev     If this changes then the deployment addresses for Avocado smart wallets change too. A more complex
    //          system with versioning would have to be implemented then for most methods.
    IAvoFactory public immutable avoFactory;

    /// @notice cached Avocado Bytecode to directly compute address in this contract to optimize gas usage.
    //
    // @dev If this changes because of an Avocado change (and AvoFactory upgrade),
    // then this variable must be updated through an upgrade, deploying a new AvoForwarder!
    bytes32 public constant avocadoBytecode = 0x6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc54;

    /// @dev amount of gas to keep in cast caller method as reserve for emitting Executed / ExecuteFailed event.
    /// ~6920 gas + buffer. the dynamic part is covered with EMIT_EVENT_COST_PER_BYTE (for metadata).
    uint256 internal constant EVENTS_RESERVE_GAS = 8_500;

    /// @dev emitting one byte in an event costs 8 byte see https://github.com/wolflo/evm-opcodes/blob/main/gas.md#a8-log-operations
    uint256 internal constant EMIT_EVENT_COST_PER_BYTE = 8;

    constructor(IAvoFactory avoFactory_) {
        avoFactory = avoFactory_;
    }
}

abstract contract AvoForwarderVariables is AvoForwarderConstants, Initializable, OwnableUpgradeable {
    // @dev variables here start at storage slot 101, before is:
    // - Initializable with storage slot 0:
    // uint8 private _initialized;
    // bool private _initializing;
    // - OwnableUpgradeable with slots 1 to 100:
    // uint256[50] private __gap; (from ContextUpgradeable, slot 1 until slot 50)
    // address private _owner; (at slot 51)
    // uint256[49] private __gap; (slot 52 until slot 100)

    // ---------------- slot 101 -----------------

    /// @notice allowed broadcasters that can call `execute()` methods. allowed if set to `1`
    mapping(address => uint256) internal _broadcasters;

    // ---------------- slot 102 -----------------

    /// @notice allowed auths. allowed if set to `1`
    mapping(address => uint256) internal _auths;
}

abstract contract AvoForwarderErrors {
    /// @notice thrown when a method is called with invalid params (e.g. zero address)
    error AvoForwarder__InvalidParams();

    /// @notice thrown when a caller is not authorized to execute a certain action
    error AvoForwarder__Unauthorized();

    /// @notice thrown when trying to execute legacy methods for a not yet deployed Avocado smart wallet
    error AvoForwarder__LegacyVersionNotDeployed();

    /// @notice thrown when an unsupported method is called (e.g. renounceOwnership)
    error AvoForwarder__Unsupported();
}

abstract contract AvoForwarderStructs {
    /// @notice struct mapping an address value to a boolean flag.
    //
    // @dev when used as input param, removes need to make sure two input arrays are of same length etc.
    struct AddressBool {
        address addr;
        bool value;
    }

    struct ExecuteBatchParams {
        address from;
        uint32 index;
        IAvocadoMultisigV1.CastChainAgnosticParams params;
        IAvocadoMultisigV1.SignatureParams[] signaturesParams;
        IAvocadoMultisigV1.ChainAgnosticHash[] chainAgnosticHashes;
    }

    struct SimulateBatchResult {
        uint256 castGasUsed;
        bool success;
        string revertReason;
    }
}

abstract contract AvoForwarderEvents is AvoForwarderStructs {
    /// @notice emitted when all actions for `cast()` in an `execute()` method are executed successfully
    event Executed(
        address indexed avocadoOwner,
        uint32 index,
        address indexed avocadoAddress,
        address indexed source,
        bytes metadata
    );

    /// @notice emitted if one of the actions for `cast()` in an `execute()` method fails
    event ExecuteFailed(
        address indexed avocadoOwner,
        uint32 index,
        address indexed avocadoAddress,
        address indexed source,
        bytes metadata,
        string reason
    );

    /// @notice emitted if a broadcaster's allowed status is updated
    event BroadcasterUpdated(address indexed broadcaster, bool indexed status);

    /// @notice emitted if an auth's allowed status is updated
    event AuthUpdated(address indexed auth, bool indexed status);
}

abstract contract AvoForwarderCore is
    AvoForwarderConstants,
    AvoForwarderVariables,
    AvoForwarderStructs,
    AvoForwarderEvents,
    AvoForwarderErrors
{
    /***********************************|
    |             MODIFIERS             |
    |__________________________________*/

    /// @dev checks if `msg.sender` is an allowed broadcaster
    modifier onlyBroadcaster() {
        if (_broadcasters[msg.sender] != 1) {
            revert AvoForwarder__Unauthorized();
        }
        _;
    }

    /// @dev checks if an address is not the zero address
    modifier validAddress(address _address) {
        if (_address == address(0)) {
            revert AvoForwarder__InvalidParams();
        }
        _;
    }

    /***********************************|
    |            CONSTRUCTOR            |
    |__________________________________*/

    constructor(IAvoFactory avoFactory_) validAddress(address(avoFactory_)) AvoForwarderConstants(avoFactory_) {
        // Ensure logic contract initializer is not abused by disabling initializing
        // see https://forum.openzeppelin.com/t/security-advisory-initialize-uups-implementation-contracts/15301
        // and https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializing_the_implementation_contract
        _disableInitializers();
    }

    /***********************************|
    |              INTERNAL             |
    |__________________________________*/

    /// @dev gets or if necessary deploys an Avocado for owner `from_` and `index_` and returns the address
    function _getDeployedAvocado(address from_, uint32 index_) internal returns (address) {
        address computedAvocadoAddress_ = _computeAvocado(from_, index_);
        if (Address.isContract(computedAvocadoAddress_)) {
            return computedAvocadoAddress_;
        } else {
            return avoFactory.deploy(from_, index_);
        }
    }

    /// @dev executes `_getDeployedAvocado` with gas measurements
    function _getSimulateDeployedAvocado(
        address from_,
        uint32 index_
    ) internal returns (IAvocadoMultisigV1 avocado_, uint256 deploymentGasUsed_, bool isDeployed_) {
        if (msg.sender != 0x000000000000000000000000000000000000dEaD) {
            revert AvoForwarder__Unauthorized();
        }

        uint256 gasSnapshotBefore_ = gasleft();
        // `_getDeployedAvocado()` automatically checks if Avocado has to be deployed
        // or if it already exists and simply returns the address in that case
        avocado_ = IAvocadoMultisigV1(_getDeployedAvocado(from_, index_));
        deploymentGasUsed_ = gasSnapshotBefore_ - gasleft();

        isDeployed_ = deploymentGasUsed_ < 100_000; // avocado for sure not yet deployed if gas used > 100k
        // (deployment costs > 200k)
    }

    /// @dev computes the deterministic contract address for an Avocado deployment for `owner_` and `index_`
    function _computeAvocado(address owner_, uint32 index_) internal view returns (address computedAddress_) {
        // replicate Create2 address determination logic
        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), address(avoFactory), _getSalt(owner_, index_), avocadoBytecode)
        );

        // cast last 20 bytes of hash to address via low level assembly
        assembly {
            computedAddress_ := and(hash, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        }
    }

    /// @dev gets the bytes32 salt used for deterministic Avocado deployment for `owner_` and `index_`, same as on AvoFactory
    function _getSalt(address owner_, uint32 index_) internal pure returns (bytes32) {
        // use owner + index of avocado nr per EOA (plus "type", currently always 0)
        // Note CREATE2 deployments take into account the deployers address (i.e. this factory address)
        return keccak256(abi.encode(owner_, index_, 0));
    }

    /// @dev returns the dynamic reserve gas to be kept back for emitting the Executed or ExecuteFailed event
    function _dynamicReserveGas(uint256 metadataLength_) internal pure returns (uint256 reserveGas_) {
        unchecked {
            // the gas usage for the emitting the CastExecuted/CastFailed events depends on the  metadata bytes length,
            // dynamically calculated with cost per byte for emit event
            reserveGas_ = EVENTS_RESERVE_GAS + (EMIT_EVENT_COST_PER_BYTE * metadataLength_);
        }
    }

    /// @dev Deploys Avocado for owner if necessary and calls `cast()` on it with given input params.
    function _executeV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastParams calldata params_,
        IAvocadoMultisigV1.CastForwardParams calldata forwardParams_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_
    ) internal returns (bool success_) {
        // `_getDeployedAvocado()` automatically checks if Avocado has to be deployed
        // or if it already exists and simply returns the address in that case
        IAvocadoMultisigV1 avocadoMultisig_ = IAvocadoMultisigV1(_getDeployedAvocado(from_, index_));

        string memory revertReason_;
        (success_, revertReason_) = avocadoMultisig_.cast{
            value: forwardParams_.value,
             // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
             // will be kept back or 1/64th according to EIP150 (whichever is bigger).
            gas: gasleft() - _dynamicReserveGas(params_.metadata.length)
        }(params_, forwardParams_, signaturesParams_);

        // @dev on changes in the code below this point, measure the needed reserve gas via `gasleft()` anew
        // and update the reserve gas constant amount.
        // gas measurement currently: ~6920 gas for emit event with max revertReason length
        if (success_) {
            emit Executed(from_, index_, address(avocadoMultisig_), params_.source, params_.metadata);
        } else {
            emit ExecuteFailed(
                from_,
                index_,
                address(avocadoMultisig_),
                params_.source,
                params_.metadata,
                revertReason_
            );
        }
        // @dev ending point for measuring reserve gas should be here.
    }

    /// @dev Deploys Avocado for owner if necessary and calls `castChainAgnostic()` on it with given input params.
    function _executeChainAgnosticV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastChainAgnosticParams calldata params_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_,
        IAvocadoMultisigV1.ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) internal returns (bool success_) {
        // `_getDeployedAvocado()` automatically checks if Avocado has to be deployed
        // or if it already exists and simply returns the address in that case
        IAvocadoMultisigV1 avocadoMultisig_ = IAvocadoMultisigV1(_getDeployedAvocado(from_, index_));

        string memory revertReason_;
        (success_, revertReason_) = avocadoMultisig_.castChainAgnostic{ 
                value: params_.forwardParams.value,
                // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
                // will be kept back or 1/64th according to EIP150 (whichever is bigger).
                gas: gasleft() - _dynamicReserveGas(params_.params.metadata.length)
            }(
            params_,
            signaturesParams_,
            chainAgnosticHashes_
        );

        // @dev on changes below, reserve gas must be updated. see _executeV1.
        if (success_) {
            emit Executed(from_, index_, address(avocadoMultisig_), params_.params.source, params_.params.metadata);
        } else {
            emit ExecuteFailed(
                from_,
                index_,
                address(avocadoMultisig_),
                params_.params.source,
                params_.params.metadata,
                revertReason_
            );
        }
    }
}

abstract contract AvoForwarderViews is AvoForwarderCore {
    /// @notice checks if a `broadcaster_` address is an allowed broadcaster
    function isBroadcaster(address broadcaster_) external view returns (bool) {
        return _broadcasters[broadcaster_] == 1;
    }

    /// @notice checks if an `auth_` address is an allowed auth
    function isAuth(address auth_) external view returns (bool) {
        return _auths[auth_] == 1;
    }
}

abstract contract AvoForwarderViewsAvocado is AvoForwarderCore {
    /// @notice        Retrieves the current avoNonce of AvocadoMultisig for `owner_` address.
    ///                Needed for building signatures.
    /// @param owner_  Avocado owner to retrieve the nonce for.
    /// @param index_  index number of Avocado for `owner_` EOA
    /// @return        returns the avoNonce for the `owner_` necessary to sign a meta transaction
    function avoNonce(address owner_, uint32 index_) external view returns (uint256) {
        address avoAddress_ = _computeAvocado(owner_, index_);
        if (Address.isContract(avoAddress_)) {
            return IAvocadoMultisigV1(avoAddress_).avoNonce();
        }

        return 0;
    }

    /// @notice        Retrieves the current AvocadoMultisig implementation name for `owner_` address.
    ///                Needed for building signatures.
    /// @param owner_  Avocado owner to retrieve the name for.
    /// @param index_  index number of Avocado for `owner_` EOA
    /// @return        returns the domain separator name for the `owner_` necessary to sign a meta transaction
    function avocadoVersionName(address owner_, uint32 index_) external view returns (string memory) {
        address avoAddress_ = _computeAvocado(owner_, index_);
        if (Address.isContract(avoAddress_)) {
            // if AvocadoMultisig is deployed, return value from deployed contract
            return IAvocadoMultisigV1(avoAddress_).DOMAIN_SEPARATOR_NAME();
        }

        // otherwise return default value for current implementation that will be deployed
        return IAvocadoMultisigV1(avoFactory.avoImpl()).DOMAIN_SEPARATOR_NAME();
    }

    /// @notice        Retrieves the current AvocadoMultisig implementation version for `owner_` address.
    ///                Needed for building signatures.
    /// @param owner_  Avocado owner to retrieve the version for.
    /// @param index_  index number of Avocado for `owner_` EOA
    /// @return        returns the domain separator version for the `owner_` necessary to sign a meta transaction
    function avocadoVersion(address owner_, uint32 index_) external view returns (string memory) {
        address avoAddress_ = _computeAvocado(owner_, index_);
        if (Address.isContract(avoAddress_)) {
            // if AvocadoMultisig is deployed, return value from deployed contract
            return IAvocadoMultisigV1(avoAddress_).DOMAIN_SEPARATOR_VERSION();
        }

        // otherwise return default value for current implementation that will be deployed
        return IAvocadoMultisigV1(avoFactory.avoImpl()).DOMAIN_SEPARATOR_VERSION();
    }

    /// @notice Computes the deterministic Avocado address for `owner_` and `index_`
    function computeAvocado(address owner_, uint32 index_) external view returns (address) {
        if (Address.isContract(owner_)) {
            // owner of a Avocado must be an EOA, if it's a contract return zero address
            return address(0);
        }
        return _computeAvocado(owner_, index_);
    }

    /// @notice returns the hashes struct for each `CastChainAgnosticParams` element of `params_`. The returned array must be
    ///         passed into `castChainAgnostic()` as the param `chainAgnosticHashes_` there (order must be the same).
    ///         The returned hash for each element is the EIP712 type hash for `CAST_CHAIN_AGNOSTIC_PARAMS_TYPE_HASH`,
    ///         as used when the signature digest is built.
    /// @dev    Deploys the Avocado if necessary. Expected to be called with callStatic.
    function getAvocadoChainAgnosticHashes(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastChainAgnosticParams[] calldata params_
    ) external returns (IAvocadoMultisigV1.ChainAgnosticHash[] memory chainAgnosticHashes_) {
        // `_getDeployedAvocado()` automatically checks if Avocado has to be deployed
        // or if it already exists and simply returns the address in that case
        IAvocadoMultisigV1 avocadoMultisig_ = IAvocadoMultisigV1(_getDeployedAvocado(from_, index_));

        return avocadoMultisig_.getChainAgnosticHashes(params_);
    }
}

abstract contract AvoForwarderV1 is AvoForwarderCore {
    /// @notice                  Deploys Avocado for owner if necessary and calls `cast()` on it.
    ///                          For Avocado v1.
    ///                          Only callable by allowed broadcasters.
    /// @param from_             Avocado owner
    /// @param index_            index number of Avocado for `owner_` EOA
    /// @param params_           Cast params such as id, avoNonce and actions to execute
    /// @param forwardParams_    Cast params related to validity of forwarding as instructed and signed
    /// @param signaturesParams_ SignatureParams structs array for signature and signer:
    ///                          - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                            For smart contract signatures it must fulfill the requirements for the relevant
    ///                            smart contract `.isValidSignature()` EIP1271 logic
    ///                          - signer: address of the signature signer.
    ///                            Must match the actual signature signer or refer to the smart contract
    ///                            that must be an allowed signer and validates signature via EIP1271
    function executeV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastParams calldata params_,
        IAvocadoMultisigV1.CastForwardParams calldata forwardParams_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_
    ) external payable onlyBroadcaster {
        _executeV1(from_, index_, params_, forwardParams_, signaturesParams_);
    }

    /// @notice                  Verify the transaction is valid and can be executed.
    ///                          IMPORTANT: Expected to be called via callStatic.
    ///
    ///                          Returns true if valid, reverts otherwise:
    ///                          e.g. if input params, signature or avoNonce etc. are invalid.
    /// @param from_             Avocado owner
    /// @param index_            index number of Avocado for `owner_` EOA
    /// @param params_           Cast params such as id, avoNonce and actions to execute
    /// @param forwardParams_    Cast params related to validity of forwarding as instructed and signed
    /// @param signaturesParams_ SignatureParams structs array for signature and signer:
    ///                          - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                            For smart contract signatures it must fulfill the requirements for the relevant
    ///                            smart contract `.isValidSignature()` EIP1271 logic
    ///                          - signer: address of the signature signer.
    ///                            Must match the actual signature signer or refer to the smart contract
    ///                            that must be an allowed signer and validates signature via EIP1271
    /// @return                  returns true if everything is valid, otherwise reverts.
    //
    // @dev can not be marked as view because it does potentially modify state by deploying the
    //      AvocadoMultisig for `from_` if it does not exist yet. Thus expected to be called via callStatic
    function verifyV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastParams calldata params_,
        IAvocadoMultisigV1.CastForwardParams calldata forwardParams_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_
    ) external returns (bool) {
        // `_getDeployedAvocado()` automatically checks if Avocado has to be deployed
        // or if it already exists and simply returns the address in that case
        IAvocadoMultisigV1 avocadoMultisig_ = IAvocadoMultisigV1(_getDeployedAvocado(from_, index_));

        return avocadoMultisig_.verify(params_, forwardParams_, signaturesParams_);
    }
}

abstract contract AvoForwarderChainAgnosticV1 is AvoForwarderCore {
    /// @notice                     Deploys Avocado for owner if necessary and calls `castChainAgnostic()` on it.
    ///                             For Avocado v1.
    ///                             Only callable by allowed broadcasters.
    /// @param from_                Avocado owner
    /// @param index_               index number of Avocado for `owner_` EOA
    /// @param params_              Chain agnostic params containing CastParams, ForwardParams and chain id.
    ///                             Note chain id must match block.chainid.
    /// @param signaturesParams_    SignatureParams structs array for signature and signer:
    ///                             - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                               For smart contract signatures it must fulfill the requirements for the relevant
    ///                               smart contract `.isValidSignature()` EIP1271 logic
    ///                             - signer: address of the signature signer.
    ///                               Must match the actual signature signer or refer to the smart contract
    ///                               that must be an allowed signer and validates signature via EIP1271
    /// @param chainAgnosticHashes_ hashes struct for each original `CastChainAgnosticParams` struct as used when signing the
    ///                             txs to be executed. Result of `.getChainAgnosticHashes()`.
    function executeChainAgnosticV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastChainAgnosticParams calldata params_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_,
        IAvocadoMultisigV1.ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external payable onlyBroadcaster {
        _executeChainAgnosticV1(from_, index_, params_, signaturesParams_, chainAgnosticHashes_);
    }

    /// @notice                     Verify the transaction is a valid chain agnostic tx and can be executed.
    ///                             IMPORTANT: Expected to be called via callStatic.
    ///
    ///                             Returns true if valid, reverts otherwise:
    ///                             e.g. if input params, signature or avoNonce etc. are invalid.
    /// @param from_                Avocado owner
    /// @param index_               index number of Avocado for `owner_` EOA
    /// @param params_              Chain agnostic params containing CastParams, ForwardParams and chain id.
    ///                             Note chain id must match block.chainid.
    /// @param signaturesParams_    SignatureParams structs array for signature and signer:
    ///                             - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                               For smart contract signatures it must fulfill the requirements for the relevant
    ///                               smart contract `.isValidSignature()` EIP1271 logic
    ///                             - signer: address of the signature signer.
    ///                               Must match the actual signature signer or refer to the smart contract
    ///                               that must be an allowed signer and validates signature via EIP1271
    /// @param chainAgnosticHashes_ hashes struct for each original `CastChainAgnosticParams` struct as used when signing the
    ///                             txs to be executed. Result of `.getChainAgnosticHashes()`.
    /// @return                     returns true if everything is valid, otherwise reverts.
    //
    // @dev can not be marked as view because it does potentially modify state by deploying the
    //      AvocadoMultisig for `from_` if it does not exist yet. Thus expected to be called via callStatic
    function verifyChainAgnosticV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastChainAgnosticParams calldata params_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_,
        IAvocadoMultisigV1.ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external returns (bool) {
        // `_getDeployedAvocado()` automatically checks if Avocado has to be deployed
        // or if it already exists and simply returns the address in that case
        IAvocadoMultisigV1 avocadoMultisig_ = IAvocadoMultisigV1(_getDeployedAvocado(from_, index_));

        return avocadoMultisig_.verifyChainAgnostic(params_, signaturesParams_, chainAgnosticHashes_);
    }
}

abstract contract AvoForwarderBatchV1 is AvoForwarderCore {
    /// @notice                  Executes multiple txs as batch.
    ///                          For Avocado v1.
    ///                          Only callable by allowed broadcasters.
    /// @param batches_          Execute batch txs array, same as inputs for `executeChainAgnosticV1()` just as struct array.
    ///                          If `chainAgnosticHashes` is set (length > 0), then `executeChainAgnosticV1()` is executed,
    ///                          otherwise `executeV1()` is executed with the given array element.
    /// @param continueOnRevert_ flag to signal if one `ExecuteBatchParams` in `batches_` fails, should the rest of them
    ///                          still continue to be executed.
    function executeBatchV1(
        ExecuteBatchParams[] calldata batches_,
        bool continueOnRevert_
    ) external payable onlyBroadcaster {
        uint256 length_ = batches_.length;

        if (length_ < 2) {
            revert AvoForwarder__InvalidParams();
        }

        bool success_;
        for (uint256 i; i < length_; ) {
            if (batches_[i].chainAgnosticHashes.length > 0) {
                success_ = _executeChainAgnosticV1(
                    batches_[i].from,
                    batches_[i].index,
                    batches_[i].params,
                    batches_[i].signaturesParams,
                    batches_[i].chainAgnosticHashes
                );
            } else {
                success_ = _executeV1(
                    batches_[i].from,
                    batches_[i].index,
                    batches_[i].params.params,
                    batches_[i].params.forwardParams,
                    batches_[i].signaturesParams
                );
            }

            if (!success_ && !continueOnRevert_) {
                break;
            }

            unchecked {
                ++i;
            }
        }
    }
}

abstract contract AvoForwarderSimulateV1 is AvoForwarderCore {
    uint256 internal constant SIMULATE_WASTE_GAS_MARGIN = 10; // 10% added in used gas for simulations

    // @dev helper struct to work around Stack too deep Errors
    struct SimulationVars {
        IAvocadoMultisigV1 avocadoMultisig;
        uint256 initialGas;
    }

    /// @dev see `simulateV1()`. Reverts on `success_` = false for accurate .estimateGas() usage.
    ///                          Helpful to estimate gas for an Avocado tx. Note: resulting gas usage will usually be
    ///                          with at least ~10k gas buffer compared to actual execution.
    ///                          For Avocado v1.
    ///                          Deploys the Avocado smart wallet if necessary.
    /// @dev  Expected use with `.estimateGas()`. User signed `CastForwardParams.gas` should be set to the estimated
    ///       amount minus gas used in AvoForwarder (until AvocadoMultisig logic where the gas param is validated).
    function estimateV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastParams calldata params_,
        IAvocadoMultisigV1.CastForwardParams calldata forwardParams_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_
    ) external payable {
        (, , , bool success_, string memory revertReason_) = simulateV1(
            from_,
            index_,
            params_,
            forwardParams_,
            signaturesParams_
        );

        if (!success_) {
            revert(revertReason_);
        }
    }

    /// @notice                  Simulates a `executeV1()` tx, callable only by msg.sender = dead address
    ///                          (0x000000000000000000000000000000000000dEaD). Useful to determine success / error
    ///                          and other return values of `executeV1()` with a `.callstatic`.
    ///                          For Avocado v1.
    /// @dev                      - set `signaturesParams_` to empty to automatically simulate with required signers length.
    ///                           - if `signaturesParams_` first element signature is not set, or if first signer is set to
    ///                             0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF, then gas usage burn is simulated
    ///                             for verify signature functionality. DO NOT set signature to non-empty for subsequent
    ///                             elements then; set all signatures to empty!
    ///                           - if `signaturesParams_` is set normally, signatures are verified as in actual execute
    ///                           - buffer amounts for mock smart contract signers signature verification must be added
    ///                             off-chain as this varies on a case per case basis.
    /// @param from_             AvocadoMultisig owner
    /// @param index_            index number of Avocado for `owner_` EOA
    /// @param params_           Cast params such as id, avoNonce and actions to execute
    /// @param forwardParams_    Cast params related to validity of forwarding as instructed and signed
    /// @param signaturesParams_ SignatureParams structs array for signature and signer:
    ///                          - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                            For smart contract signatures it must fulfill the requirements for the relevant
    ///                            smart contract `.isValidSignature()` EIP1271 logic
    ///                          - signer: address of the signature signer.
    ///                            Must match the actual signature signer or refer to the smart contract
    ///                            that must be an allowed signer and validates signature via EIP1271
    /// @return castGasUsed_        amount of gas used for executing `cast`
    /// @return deploymentGasUsed_  amount of gas used for deployment (or for getting the contract if already deployed)
    /// @return isDeployed_         boolean flag indicating if Avocado is already deployed
    /// @return success_            boolean flag indicating whether executing actions reverts or not
    /// @return revertReason_       revert reason original error in default format "<action_index>_error"
    function simulateV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastParams calldata params_,
        IAvocadoMultisigV1.CastForwardParams calldata forwardParams_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_
    )
        public
        payable
        returns (
            uint256 castGasUsed_,
            uint256 deploymentGasUsed_,
            bool isDeployed_,
            bool success_,
            string memory revertReason_
        )
    {
        SimulationVars memory vars_; 

        vars_.initialGas = gasleft();

        (vars_.avocadoMultisig, deploymentGasUsed_, isDeployed_) = _getSimulateDeployedAvocado(from_, index_);

        {
            uint256 gasSnapshotBefore_;
            bytes32 avoVersion_ = keccak256(bytes(vars_.avocadoMultisig.DOMAIN_SEPARATOR_VERSION()));
            if (avoVersion_ == keccak256(bytes("1.0.0")) || avoVersion_ == keccak256(bytes("1.0.1"))) {
                gasSnapshotBefore_ = gasleft();
                (success_, revertReason_) = vars_.avocadoMultisig.cast{ value: forwardParams_.value,
                // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
                // will be kept back or 1/64th according to EIP150 (whichever is bigger).
                gas: gasleft() - _dynamicReserveGas(params_.metadata.length)
             }(
                    params_,
                    forwardParams_,
                    signaturesParams_
                );
            } else {
                gasSnapshotBefore_ = gasleft();
                (success_, revertReason_) = vars_.avocadoMultisig.simulateCast{ value: forwardParams_.value, 
                    // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
                    // will be kept back or 1/64th according to EIP150 (whichever is bigger).
                    gas: gasleft() - _dynamicReserveGas(params_.metadata.length) }(
                    params_,
                    forwardParams_,
                    signaturesParams_
                );
            }
            castGasUsed_ = gasSnapshotBefore_ - gasleft();
        }

        if (success_) {
            emit Executed(from_, index_, address(vars_.avocadoMultisig), params_.source, params_.metadata);
        } else {
            emit ExecuteFailed(
                from_,
                index_,
                address(vars_.avocadoMultisig),
                params_.source,
                params_.metadata,
                revertReason_
            );
        }

        _wasteGas(((vars_.initialGas - gasleft()) * SIMULATE_WASTE_GAS_MARGIN) / 100); // e.g. 10% of used gas
    }

    /// @dev see `simulateChainAgnosticV1()`. Reverts on `success_` = false for accurate .estimateGas() usage.
    ///                          Helpful to estimate gas for an Avocado tx. Note: resulting gas usage will usually be
    ///                          with at least ~10k gas buffer compared to actual execution.
    ///                          For Avocado v1.
    ///                          Deploys the Avocado smart wallet if necessary.
    /// @dev  Expected use with `.estimateGas()`. User signed `CastForwardParams.gas` should be set to the estimated
    ///       amount minus gas used in AvoForwarder (until AvocadoMultisig logic where the gas param is validated).
    function estimateChainAgnosticV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastChainAgnosticParams calldata params_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_,
        IAvocadoMultisigV1.ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external payable {
        (, , , bool success_, string memory revertReason_) = simulateChainAgnosticV1(
            from_,
            index_,
            params_,
            signaturesParams_,
            chainAgnosticHashes_
        );

        if (!success_) {
            revert(revertReason_);
        }
    }

    /// @notice                   Simulates a `executeChainAgnosticV1()` tx, callable only by msg.sender = dead address
    ///                           (0x000000000000000000000000000000000000dEaD). Useful to determine success / error
    ///                           and other return values of `executeV1()` with a `.callstatic`.
    ///                           For Avocado v1.
    ///                           Deploys the Avocado smart wallet if necessary.
    /// @dev                      - set `signaturesParams_` to empty to automatically simulate with required signers length.
    ///                           - if `signaturesParams_` first element signature is not set, or if first signer is set to
    ///                             0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF, then gas usage burn is simulated
    ///                             for verify signature functionality. DO NOT set signature to non-empty for subsequent
    ///                             elements then; set all signatures to empty!
    ///                           - if `signaturesParams_` is set normally, signatures are verified as in actual execute
    ///                           - buffer amounts for mock smart contract signers signature verification must be added
    ///                             off-chain as this varies on a case per case basis.
    /// @param from_                Avocado owner
    /// @param index_               index number of Avocado for `owner_` EOA
    /// @param params_              Chain agnostic params containing CastParams, ForwardParams and chain id.
    ///                             Note chain id must match block.chainid.
    /// @param signaturesParams_    SignatureParams structs array for signature and signer:
    ///                             - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                               For smart contract signatures it must fulfill the requirements for the relevant
    ///                               smart contract `.isValidSignature()` EIP1271 logic
    ///                             - signer: address of the signature signer.
    ///                               Must match the actual signature signer or refer to the smart contract
    ///                               that must be an allowed signer and validates signature via EIP1271
    /// @param chainAgnosticHashes_ hashes struct for each original `CastChainAgnosticParams` struct as used when signing the
    ///                             txs to be executed. Result of `.getChainAgnosticHashes()`.
    /// @return castGasUsed_        amount of gas used for executing `cast`
    /// @return deploymentGasUsed_  amount of gas used for deployment (or for getting the contract if already deployed)
    /// @return isDeployed_         boolean flag indicating if Avocado is already deployed
    /// @return success_            boolean flag indicating whether executing actions reverts or not
    /// @return revertReason_       revert reason original error in default format "<action_index>_error"
    function simulateChainAgnosticV1(
        address from_,
        uint32 index_,
        IAvocadoMultisigV1.CastChainAgnosticParams calldata params_,
        IAvocadoMultisigV1.SignatureParams[] calldata signaturesParams_,
        IAvocadoMultisigV1.ChainAgnosticHash[] calldata chainAgnosticHashes_
    )
        public
        payable
        returns (
            uint256 castGasUsed_,
            uint256 deploymentGasUsed_,
            bool isDeployed_,
            bool success_,
            string memory revertReason_
        )
    {
        SimulationVars memory vars_; 

        vars_.initialGas = gasleft();

        (vars_.avocadoMultisig, deploymentGasUsed_, isDeployed_) = _getSimulateDeployedAvocado(from_, index_);

        {
            uint256 gasSnapshotBefore_ = gasleft();
            (success_, revertReason_) = vars_.avocadoMultisig.simulateCastChainAgnostic{
                value: params_.forwardParams.value,
                // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
                // will be kept back or 1/64th according to EIP150 (whichever is bigger).
                gas: gasleft() - _dynamicReserveGas(params_.params.metadata.length)
            }(params_, signaturesParams_, chainAgnosticHashes_);
            castGasUsed_ = gasSnapshotBefore_ - gasleft();
        }

        if (success_) {
            emit Executed(from_, index_, address(vars_.avocadoMultisig), params_.params.source, params_.params.metadata);
        } else {
            emit ExecuteFailed(
                from_,
                index_,
                address(vars_.avocadoMultisig),
                params_.params.source,
                params_.params.metadata,
                revertReason_
            );
        }

        _wasteGas(((vars_.initialGas - gasleft()) * SIMULATE_WASTE_GAS_MARGIN) / 100); // e.g. 10% of used gas
    }

    /// @notice                  Simulates a `executeBatchV1()` tx, callable only by msg.sender = dead address
    ///                          (0x000000000000000000000000000000000000dEaD)
    ///                          Helpful to estimate gas for an Avocado tx. Note: resulting gas usage will usually be
    ///                          with at least ~10k gas buffer compared to actual execution.
    ///                          For Avocado v1.
    ///                          Deploys the Avocado smart wallet if necessary.
    /// @dev  Expected use with `.estimateGas()`.
    ///       Best to combine with a `.callstatic` to determine success / error and other return values of `executeV1()`.
    ///       For indidividual measurements of each `ExecuteBatchParams` execute the respective simulate() single method for it.
    /// @param batches_          Execute batch txs array, same as inputs for `simulateChainAgnosticV1()` just as struct array.
    /// @param continueOnRevert_ flag to signal if one `ExecuteBatchParams` in `batches_` fails, should the rest of them
    ///                          still continue to be executed.
    function simulateBatchV1(ExecuteBatchParams[] calldata batches_, bool continueOnRevert_) external payable returns(SimulateBatchResult[] memory results_){
        uint256 initialGas_ = gasleft();

        uint256 length_ = batches_.length;

        if (length_ < 2) {
            revert AvoForwarder__InvalidParams();
        }

        results_ = new SimulateBatchResult[](length_);
        IAvocadoMultisigV1 avocadoMultisig_;
        uint256 gasSnapshotBefore_;
        for (uint256 i; i < length_; ) {

             (avocadoMultisig_ , , ) = _getSimulateDeployedAvocado(batches_[i].from, batches_[i].index);

             gasSnapshotBefore_ = gasleft();
            if (batches_[i].chainAgnosticHashes.length > 0) {
                (results_[i].success, results_[i].revertReason) = avocadoMultisig_.simulateCastChainAgnostic{
                    value: batches_[i].params.forwardParams.value,
                    // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
                    // will be kept back or 1/64th according to EIP150 (whichever is bigger).
                    gas: gasleft() - _dynamicReserveGas(batches_[i].params.params.metadata.length)
                }(batches_[i].params, batches_[i].signaturesParams, batches_[i].chainAgnosticHashes);
            } else {
                (results_[i].success, results_[i].revertReason) = avocadoMultisig_.simulateCast{
                    value: batches_[i].params.forwardParams.value,
                    // keep back at least enough gas to ensure we can emit events logic below. either calculated reserve gas amount
                    // will be kept back or 1/64th according to EIP150 (whichever is bigger).
                    gas: gasleft() - _dynamicReserveGas(batches_[i].params.params.metadata.length)
                }(batches_[i].params.params, batches_[i].params.forwardParams, batches_[i].signaturesParams);
            }
            results_[i].castGasUsed = gasSnapshotBefore_ - gasleft();

            if (results_[i].success) {
                emit Executed(
                    batches_[i].from,
                    batches_[i].index,
                    address(avocadoMultisig_),
                    batches_[i].params.params.source,
                    batches_[i].params.params.metadata
                );
            } else {
                emit ExecuteFailed(
                    batches_[i].from,
                    batches_[i].index,
                    address(avocadoMultisig_),
                    batches_[i].params.params.source,
                    batches_[i].params.params.metadata,
                    results_[i].revertReason
                );
            }

            if (!results_[i].success && !continueOnRevert_) {
                break;
            }

            unchecked {
                ++i;
            }
        }

        _wasteGas(((initialGas_ - gasleft()) * SIMULATE_WASTE_GAS_MARGIN) / 100); // e.g. 10% of used gas
    }

    /// @dev uses up `wasteGasAmount_` of gas
    function _wasteGas(uint256 wasteGasAmount_) internal view {
        uint256 gasLeft_ = gasleft();
        uint256 wasteGasCounter_;
        while (gasLeft_ - gasleft() < wasteGasAmount_) wasteGasCounter_++;
    }
}

abstract contract AvoForwarderOwnerActions is AvoForwarderCore {
    /// @dev modifier checks if `msg.sender` is either owner or allowed auth, reverts if not.
    modifier onlyAuthOrOwner() {
        if (!(msg.sender == owner() || _auths[msg.sender] == 1)) {
            revert AvoForwarder__Unauthorized();
        }

        _;
    }

    /// @notice updates allowed status for broadcasters based on `broadcastersStatus_` and emits `BroadcastersUpdated`.
    /// Executable by allowed auths or owner only.
    function updateBroadcasters(AddressBool[] calldata broadcastersStatus_) external onlyAuthOrOwner {
        uint256 length_ = broadcastersStatus_.length;
        for (uint256 i; i < length_; ) {
            if (broadcastersStatus_[i].addr == address(0)) {
                revert AvoForwarder__InvalidParams();
            }

            _broadcasters[broadcastersStatus_[i].addr] = broadcastersStatus_[i].value ? 1 : 0;

            emit BroadcasterUpdated(broadcastersStatus_[i].addr, broadcastersStatus_[i].value);

            unchecked {
                ++i;
            }
        }
    }

    /// @notice updates allowed status for a auths based on `authsStatus_` and emits `AuthsUpdated`.
    /// Executable by allowed auths or owner only (auths can only remove themselves).
    function updateAuths(AddressBool[] calldata authsStatus_) external onlyAuthOrOwner {
        uint256 length_ = authsStatus_.length;

        bool isMsgSenderOwner = msg.sender == owner();

        for (uint256 i; i < length_; ) {
            if (authsStatus_[i].addr == address(0)) {
                revert AvoForwarder__InvalidParams();
            }

            uint256 setStatus_ = authsStatus_[i].value ? 1 : 0;

            // if `msg.sender` is auth, then operation must be remove and address to be removed must be auth itself
            if (!(isMsgSenderOwner || (setStatus_ == 0 && msg.sender == authsStatus_[i].addr))) {
                revert AvoForwarder__Unauthorized();
            }

            _auths[authsStatus_[i].addr] = setStatus_;

            emit AuthUpdated(authsStatus_[i].addr, authsStatus_[i].value);

            unchecked {
                ++i;
            }
        }
    }
}

contract AvoForwarder is
    AvoForwarderCore,
    AvoForwarderViews,
    AvoForwarderViewsAvocado,
    AvoForwarderV1,
    AvoForwarderChainAgnosticV1,
    AvoForwarderBatchV1,
    AvoForwarderSimulateV1,
    AvoForwarderOwnerActions
{
    /// @notice constructor sets the immutable `avoFactory` (proxy) address and cached bytecodes derived from it
    constructor(IAvoFactory avoFactory_) AvoForwarderCore(avoFactory_) {}

    /// @notice initializes the contract, setting `owner_` and initial `allowedBroadcasters_`
    /// @param owner_                address of owner_ allowed to executed auth limited methods
    /// @param allowedBroadcasters_  initial list of allowed broadcasters to be enabled right away
    function initialize(
        address owner_,
        address[] calldata allowedBroadcasters_
    ) public validAddress(owner_) initializer {
        _transferOwnership(owner_);

        // set initial allowed broadcasters
        uint256 length_ = allowedBroadcasters_.length;
        for (uint256 i; i < length_; ) {
            if (allowedBroadcasters_[i] == address(0)) {
                revert AvoForwarder__InvalidParams();
            }

            _broadcasters[allowedBroadcasters_[i]] = 1;

            emit BroadcasterUpdated(allowedBroadcasters_[i], true);

            unchecked {
                ++i;
            }
        }
    }

    /// @notice override renounce ownership as it could leave the contract in an unwanted state if called by mistake.
    function renounceOwnership() public view override onlyOwner {
        revert AvoForwarder__Unsupported();
    }
}

File 2 of 11 : OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.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.
 *
 * By default, the owner account will be the one that deploys the contract. 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 OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal onlyInitializing {
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal onlyInitializing {
        _transferOwnership(_msgSender());
    }

    /**
     * @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 {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing 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 {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _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);
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 3 of 11 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized < type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Internal function that returns the initialized version. Returns `_initialized`
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Internal function that returns the initialized version. Returns `_initializing`
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

File 4 of 11 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 5 of 11 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

/**
 * @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 ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 6 of 11 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 7 of 11 : AvocadoMultisigStructs.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

interface AvocadoMultisigStructs {
    /// @notice a combination of a bytes signature and its signer.
    struct SignatureParams {
        ///
        /// @param signature ECDSA signature of `getSigDigest()` for default flow or EIP1271 smart contract signature
        bytes signature;
        ///
        /// @param signer signer of the signature. Can be set to smart contract address that supports EIP1271
        address signer;
    }

    /// @notice an arbitrary executable action
    struct Action {
        ///
        /// @param target the target address to execute the action on
        address target;
        ///
        /// @param data the calldata to be passed to the call for each target
        bytes data;
        ///
        /// @param value the msg.value to be passed to the call for each target. set to 0 if none
        uint256 value;
        ///
        /// @param operation type of operation to execute:
        /// 0 -> .call; 1 -> .delegateCall, 2 -> flashloan (via .call)
        uint256 operation;
    }

    /// @notice common params for both `cast()` and `castAuthorized()`
    struct CastParams {
        Action[] actions;
        ///
        /// @param id             Required:
        ///                       id for actions, e.g. 0 = CALL, 1 = MIXED (call and delegatecall),
        ///                                           20 = FLASHLOAN_CALL, 21 = FLASHLOAN_MIXED
        uint256 id;
        ///
        /// @param avoNonce   Required:
        ///                       avoNonce to be used for this tx. Must equal the avoNonce value on smart
        ///                       wallet or alternatively it must be set to -1 to use a non-sequential nonce instead
        int256 avoNonce;
        ///
        /// @param salt           Optional:
        ///                       Salt to customize non-sequential nonce (if `avoNonce` is set to -1)
        bytes32 salt;
        ///
        /// @param source         Optional:
        ///                       Source / referral for this tx
        address source;
        ///
        /// @param metadata       Optional:
        ///                       metadata for any potential additional data to be tracked in the tx
        bytes metadata;
    }

    /// @notice `cast()` input params related to forwarding validity
    struct CastForwardParams {
        ///
        /// @param gas            Optional:
        ///                       As EIP-2770: user instructed minimum amount of gas that the relayer (AvoForwarder)
        ///                       must send for the execution. Sending less gas will fail the tx at the cost of the relayer.
        ///                       Also protects against potential gas griefing attacks
        ///                       See https://ronan.eth.limo/blog/ethereum-gas-dangers/
        uint256 gas;
        ///
        /// @param gasPrice       Optional:
        ///                       Not implemented / used yet
        uint256 gasPrice;
        ///
        /// @param validAfter     Optional:
        ///                       the earliest block timestamp that the request can be forwarded in,
        ///                       or 0 if the request is not time-limited to occur after a certain time.
        ///                       Protects against relayers executing a certain transaction at an earlier moment
        ///                       not intended by the user, where it might have a completely different effect.
        uint256 validAfter;
        ///
        /// @param validUntil     Optional:
        ///                       Similar to EIP-2770: the latest block timestamp (instead of block number) the request
        ///                       can be forwarded, or 0 if request should be valid forever.
        ///                       Protects against relayers executing a certain transaction at a later moment
        ///                       not intended by the user, where it might have a completely different effect.
        uint256 validUntil;
        ///
        /// @param value          Optional:
        ///                       Not implemented / used yet (`msg.value` amount the broadcaster should send along)
        uint256 value;
    }

    /// @notice `castAuthorized()` input params
    struct CastAuthorizedParams {
        ///
        /// @param maxFee         Optional:
        ///                       the maximum Avocado charge-up allowed to be paid for tx execution
        uint256 maxFee;
        ///
        /// @param gasPrice       Optional:
        ///                       Not implemented / used yet
        uint256 gasPrice;
        ///
        /// @param validAfter     Optional:
        ///                       the earliest block timestamp that the request can be forwarded in,
        ///                       or 0 if the request is not time-limited to occur after a certain time.
        ///                       Protects against relayers executing a certain transaction at an earlier moment
        ///                       not intended by the user, where it might have a completely different effect.
        uint256 validAfter;
        ///
        /// @param validUntil     Optional:
        ///                       Similar to EIP-2770: the latest block timestamp (instead of block number) the request
        ///                       can be forwarded, or 0 if request should be valid forever.
        ///                       Protects against relayers executing a certain transaction at a later moment
        ///                       not intended by the user, where it might have a completely different effect.
        uint256 validUntil;
    }

    /// @notice params for `castChainAgnostic()` to be used when casting txs on multiple chains with one signature
    struct CastChainAgnosticParams {
        ///
        /// @param params cast params containing actions to be executed etc.
        CastParams params;
        ///
        /// @param forwardParams params related to forwarding validity
        CastForwardParams forwardParams;
        ///
        /// @param chainId chainId where these actions are valid
        uint256 chainId;
    }

    /// @notice unique chain agnostic hash with chain id to be used for chain agnostic interactions
    struct ChainAgnosticHash {
        ///
        /// @param hash EIP712 type `CAST_CHAIN_AGNOSTIC_PARAMS_TYPE_HASH` hash for one specific `CastChainAgnosticParams` struct
        bytes32 hash;
        ///
        /// @param chainId chainId where this `hash` is for
        uint256 chainId;
    }
}

File 8 of 11 : IAvocadoMultisigV1.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

import { AvocadoMultisigStructs } from "../AvocadoMultisig/AvocadoMultisigStructs.sol";

// @dev base interface without getters for storage variables (to avoid overloads issues)
interface IAvocadoMultisigV1Base is AvocadoMultisigStructs {
    /// @notice initializer called by AvoFactory after deployment, sets the `owner_` as the only signer
    function initialize() external;

    /// @notice returns the domainSeparator for EIP712 signature
    function domainSeparatorV4() external view returns (bytes32);

    /// @notice returns the domainSeparator for EIP712 signature for `castChainAgnostic`
    function domainSeparatorV4ChainAgnostic() external view returns (bytes32);

    /// @notice               gets the digest (hash) used to verify an EIP712 signature for `cast()`.
    ///
    ///                       This is also used as the non-sequential nonce that will be marked as used when the
    ///                       request with the matching `params_` and `forwardParams_` is executed via `cast()`.
    /// @param params_        Cast params such as id, avoNonce and actions to execute
    /// @param forwardParams_ Cast params related to validity of forwarding as instructed and signed
    /// @return               bytes32 digest to verify signature (or used as non-sequential nonce)
    function getSigDigest(
        CastParams calldata params_,
        CastForwardParams calldata forwardParams_
    ) external view returns (bytes32);

    /// @notice                   gets the digest (hash) used to verify an EIP712 signature for `castAuthorized()`.
    ///
    ///                           This is also the non-sequential nonce that will be marked as used when the request
    ///                           with the matching `params_` and `authorizedParams_` is executed via `castAuthorized()`.
    /// @param params_            Cast params such as id, avoNonce and actions to execute
    /// @param authorizedParams_  Cast params related to authorized execution such as maxFee, as signed
    /// @return                   bytes32 digest to verify signature (or used as non-sequential nonce)
    function getSigDigestAuthorized(
        CastParams calldata params_,
        CastAuthorizedParams calldata authorizedParams_
    ) external view returns (bytes32);

    /// @notice                   Verify the signatures for a `cast()' call are valid and can be executed.
    ///                           This does not guarantuee that the tx will not revert, simply that the params are valid.
    ///                           Does not revert and returns successfully if the input is valid.
    ///                           Reverts if input params, signature or avoNonce etc. are invalid.
    /// @param params_            Cast params such as id, avoNonce and actions to execute
    /// @param forwardParams_     Cast params related to validity of forwarding as instructed and signed
    /// @param signaturesParams_  SignatureParams structs array for signature and signer:
    ///                           - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                             For smart contract signatures it must fulfill the requirements for the relevant
    ///                             smart contract `.isValidSignature()` EIP1271 logic
    ///                           - signer: address of the signature signer.
    ///                             Must match the actual signature signer or refer to the smart contract
    ///                             that must be an allowed signer and validates signature via EIP1271
    /// @return                   returns true if everything is valid, otherwise reverts
    function verify(
        CastParams calldata params_,
        CastForwardParams calldata forwardParams_,
        SignatureParams[] calldata signaturesParams_
    ) external view returns (bool);

    /// @notice                   Verify the signatures for a `castAuthorized()' call are valid and can be executed.
    ///                           This does not guarantuee that the tx will not revert, simply that the params are valid.
    ///                           Does not revert and returns successfully if the input is valid.
    ///                           Reverts if input params, signature or avoNonce etc. are invalid.
    /// @param params_            Cast params such as id, avoNonce and actions to execute
    /// @param authorizedParams_  Cast params related to authorized execution such as maxFee, as signed
    /// @param signaturesParams_  SignatureParams structs array for signature and signer:
    ///                           - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                             For smart contract signatures it must fulfill the requirements for the relevant
    ///                             smart contract `.isValidSignature()` EIP1271 logic
    ///                           - signer: address of the signature signer.
    ///                             Must match the actual signature signer or refer to the smart contract
    ///                             that must be an allowed signer and validates signature via EIP1271
    /// @return                   returns true if everything is valid, otherwise reverts
    function verifyAuthorized(
        CastParams calldata params_,
        CastAuthorizedParams calldata authorizedParams_,
        SignatureParams[] calldata signaturesParams_
    ) external view returns (bool);

    /// @notice                   Executes arbitrary actions with valid signatures. Only executable by AvoForwarder.
    ///                           If one action fails, the transaction doesn't revert, instead emits the `CastFailed` event.
    ///                           In that case, all previous actions are reverted.
    ///                           On success, emits CastExecuted event.
    /// @dev                      validates EIP712 signature then executes each action via .call or .delegatecall
    /// @param params_            Cast params such as id, avoNonce and actions to execute
    /// @param forwardParams_     Cast params related to validity of forwarding as instructed and signed
    /// @param signaturesParams_  SignatureParams structs array for signature and signer:
    ///                           - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                             For smart contract signatures it must fulfill the requirements for the relevant
    ///                             smart contract `.isValidSignature()` EIP1271 logic
    ///                           - signer: address of the signature signer.
    ///                             Must match the actual signature signer or refer to the smart contract
    ///                             that must be an allowed signer and validates signature via EIP1271
    /// @return success           true if all actions were executed succesfully, false otherwise.
    /// @return revertReason      revert reason if one of the actions fails in the following format:
    ///                           The revert reason will be prefixed with the index of the action.
    ///                           e.g. if action 1 fails, then the reason will be "1_reason".
    ///                           if an action in the flashloan callback fails (or an otherwise nested action),
    ///                           it will be prefixed with with two numbers: "1_2_reason".
    ///                           e.g. if action 1 is the flashloan, and action 2 of flashloan actions fails,
    ///                           the reason will be 1_2_reason.
    function cast(
        CastParams calldata params_,
        CastForwardParams calldata forwardParams_,
        SignatureParams[] calldata signaturesParams_
    ) external payable returns (bool success, string memory revertReason);

    /// @notice                   Simulates a `cast()` call with exact same params and execution logic except for:
    ///                           - any `gasleft()` use removed to remove potential problems when estimating gas.
    ///                           - reverts on param validations removed (verify validity with `verify` instead).
    ///                           - signature validation is skipped (must be manually added to gas estimations).
    /// @dev                      tx.origin must be dead address, msg.sender must be AvoForwarder.
    /// @dev                      - set `signaturesParams_` to empty to automatically simulate with required signers length.
    ///                           - if `signaturesParams_` first element signature is not set, or if first signer is set to
    ///                             0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF, then gas usage burn is simulated
    ///                             for verify signature functionality. DO NOT set signature to non-empty for subsequent
    ///                             elements then; set all signatures to empty!
    ///                           - if `signaturesParams_` is set normally, signatures are verified as in actual execute
    ///                           - buffer amounts for mock smart contract signers signature verification must be added
    ///                             off-chain as this varies on a case per case basis.
    function simulateCast(
        CastParams calldata params_,
        CastForwardParams calldata forwardParams_,
        SignatureParams[] memory signaturesParams_
    ) external payable returns (bool success_, string memory revertReason_);

    /// @notice                   Exact same as `simulateCast`, just reverts in case of `success_` = false to optimize
    ///                           for use with .estimateGas().
    function estimateCast(
        CastParams calldata params_,
        CastForwardParams calldata forwardParams_,
        SignatureParams[] memory signaturesParams_
    ) external payable returns (bool success_, string memory revertReason_);

    /// @notice                   Executes arbitrary actions through authorized transaction sent with valid signatures.
    ///                           Includes a fee in native network gas token, amount depends on registry `calcFee()`.
    ///                           If one action fails, the transaction doesn't revert, instead emits the `CastFailed` event.
    ///                           In that case, all previous actions are reverted.
    ///                           On success, emits CastExecuted event.
    /// @dev                      executes a .call or .delegateCall for every action (depending on params)
    /// @param params_            Cast params such as id, avoNonce and actions to execute
    /// @param authorizedParams_  Cast params related to authorized execution such as maxFee, as signed
    /// @param signaturesParams_  SignatureParams structs array for signature and signer:
    ///                           - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                             For smart contract signatures it must fulfill the requirements for the relevant
    ///                             smart contract `.isValidSignature()` EIP1271 logic
    ///                           - signer: address of the signature signer.
    ///                             Must match the actual signature signer or refer to the smart contract
    ///                             that must be an allowed signer and validates signature via EIP1271
    /// @return success           true if all actions were executed succesfully, false otherwise.
    /// @return revertReason      revert reason if one of the actions fails in the following format:
    ///                           The revert reason will be prefixed with the index of the action.
    ///                           e.g. if action 1 fails, then the reason will be "1_reason".
    ///                           if an action in the flashloan callback fails (or an otherwise nested action),
    ///                           it will be prefixed with with two numbers: "1_2_reason".
    ///                           e.g. if action 1 is the flashloan, and action 2 of flashloan actions fails,
    ///                           the reason will be 1_2_reason.
    function castAuthorized(
        CastParams calldata params_,
        CastAuthorizedParams calldata authorizedParams_,
        SignatureParams[] calldata signaturesParams_
    ) external payable returns (bool success, string memory revertReason);

    /// @notice returns the hashes struct for each `CastChainAgnosticParams` element of `params_`. The returned array must be
    ///         passed into `castChainAgnostic()` as the param `chainAgnosticHashes_` there (order must be the same).
    ///         The returned hash for each element is the EIP712 type hash for `CAST_CHAIN_AGNOSTIC_PARAMS_TYPE_HASH`,
    ///         as used when the signature digest is built.
    function getChainAgnosticHashes(
        CastChainAgnosticParams[] calldata params_
    ) external pure returns (ChainAgnosticHash[] memory chainAgnosticHashes_);

    /// @notice                   gets the digest (hash) used to verify an EIP712 signature for `castChainAgnostic()`,
    ///                           built from the `CastChainAgnosticParams`.
    ///
    ///                           This is also the non-sequential nonce that will be marked as used when the request
    ///                           with the matching `params_` is executed via `castChainAgnostic()`.
    /// @param params_            Cast params such as id, avoNonce and actions to execute
    /// @return                   bytes32 digest to verify signature (or used as non-sequential nonce)
    function getSigDigestChainAgnostic(CastChainAgnosticParams[] calldata params_) external view returns (bytes32);

    /// @notice                     gets the digest (hash) used to verify an EIP712 signature for `castChainAgnostic()`,
    ///                             built from the chain agnostic hashes (result of `getChainAgnosticHashes()`).
    ///
    ///                             This is also the non-sequential nonce that will be marked as used when the request
    ///                             with the matching `params_` is executed via `castChainAgnostic()`.
    /// @param chainAgnosticHashes_ EIP712 type hashes of `CAST_CHAIN_AGNOSTIC_PARAMS_TYPE_HASH` for all `CastChainAgnosticParams`
    ///                             struct array elements as used when creating the signature. Result of `getChainAgnosticHashes()`.
    ///                             must be set in the same order as when creating the signature.
    /// @return                     bytes32 digest to verify signature (or used as non-sequential nonce)
    function getSigDigestChainAgnosticFromHashes(
        ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external view returns (bytes32);

    /// @notice                     Executes arbitrary actions with valid signatures. Only executable by AvoForwarder.
    ///                             If one action fails, the transaction doesn't revert, instead emits the `CastFailed` event.
    ///                             In that case, all previous actions are reverted.
    ///                             On success, emits CastExecuted event.
    /// @dev                        validates EIP712 signature then executes each action via .call or .delegatecall
    /// @param params_              params containing info and intents regarding actions to be executed. Made up of
    ///                             same params as for `cast()` plus chain id.
    /// @param signaturesParams_    SignatureParams structs array for signature and signer:
    ///                             - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                               For smart contract signatures it must fulfill the requirements for the relevant
    ///                               smart contract `.isValidSignature()` EIP1271 logic
    ///                             - signer: address of the signature signer.
    ///                               Must match the actual signature signer or refer to the smart contract
    ///                               that must be an allowed signer and validates signature via EIP1271
    /// @param chainAgnosticHashes_ EIP712 type hashes of `CAST_CHAIN_AGNOSTIC_PARAMS_TYPE_HASH` for all `CastChainAgnosticParams`
    ///                             struct array elements as used when creating the signature. Result of `getChainAgnosticHashes()`.
    ///                             must be set in the same order as when creating the signature.
    /// @return success             true if all actions were executed succesfully, false otherwise.
    /// @return revertReason        revert reason if one of the actions fails in the following format:
    ///                             The revert reason will be prefixed with the index of the action.
    ///                             e.g. if action 1 fails, then the reason will be "1_reason".
    ///                             if an action in the flashloan callback fails (or an otherwise nested action),
    ///                             it will be prefixed with with two numbers: "1_2_reason".
    ///                             e.g. if action 1 is the flashloan, and action 2 of flashloan actions fails,
    ///                             the reason will be 1_2_reason.
    function castChainAgnostic(
        CastChainAgnosticParams calldata params_,
        SignatureParams[] memory signaturesParams_,
        ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external payable returns (bool success, string memory revertReason);

    /// @notice                   Simulates a `castChainAgnostic()` call with exact same params and execution logic except for:
    ///                           - any `gasleft()` use removed to remove potential problems when estimating gas.
    ///                           - reverts on param validations removed (verify validity with `verify` instead).
    ///                           - signature validation is skipped (must be manually added to gas estimations).
    /// @dev                      tx.origin must be dead address, msg.sender must be AvoForwarder.
    /// @dev                      - set `signaturesParams_` to empty to automatically simulate with required signers length.
    ///                           - if `signaturesParams_` first element signature is not set, or if first signer is set to
    ///                             0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF, then gas usage burn is simulated
    ///                             for verify signature functionality. DO NOT set signature to non-empty for subsequent
    ///                             elements then; set all signatures to empty!
    ///                           - if `signaturesParams_` is set normally, signatures are verified as in actual execute
    ///                           - buffer amounts for mock smart contract signers signature verification must be added
    ///                             off-chain as this varies on a case per case basis.
    function simulateCastChainAgnostic(
        CastChainAgnosticParams calldata params_,
        SignatureParams[] memory signaturesParams_,
        ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external payable returns (bool success_, string memory revertReason_);

    /// @notice                   Exact same as `simulateCastChainAgnostic`, just reverts in case of `success_` = false to
    ///                           optimize for use with .estimateGas().
    function estimateCastChainAgnostic(
        CastChainAgnosticParams calldata params_,
        SignatureParams[] memory signaturesParams_,
        ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external payable returns (bool success_, string memory revertReason_);

    /// @notice                     Verify the signatures for a `castChainAgnostic()' call are valid and can be executed.
    ///                             This does not guarantuee that the tx will not revert, simply that the params are valid.
    ///                             Does not revert and returns successfully if the input is valid.
    ///                             Reverts if input params, signature or avoNonce etc. are invalid.
    /// @param params_              params containing info and intents regarding actions to be executed. Made up of
    ///                             same params as for `cast()` plus chain id.
    /// @param signaturesParams_    SignatureParams structs array for signature and signer:
    ///                             - signature: the EIP712 signature, 65 bytes ECDSA signature for a default EOA.
    ///                               For smart contract signatures it must fulfill the requirements for the relevant
    ///                               smart contract `.isValidSignature()` EIP1271 logic
    ///                             - signer: address of the signature signer.
    ///                               Must match the actual signature signer or refer to the smart contract
    ///                               that must be an allowed signer and validates signature via EIP1271
    /// @param chainAgnosticHashes_ EIP712 type hashes of `CAST_CHAIN_AGNOSTIC_PARAMS_TYPE_HASH` for all `CastChainAgnosticParams`
    ///                             struct array elements as used when creating the signature. Result of `getChainAgnosticHashes()`.
    ///                             must be set in the same order as when creating the signature.
    /// @return                     returns true if everything is valid, otherwise reverts
    function verifyChainAgnostic(
        CastChainAgnosticParams calldata params_,
        SignatureParams[] calldata signaturesParams_,
        ChainAgnosticHash[] calldata chainAgnosticHashes_
    ) external view returns (bool);

    /// @notice checks if an address `signer_` is an allowed signer (returns true if allowed)
    function isSigner(address signer_) external view returns (bool);

    /// @notice returns allowed signers on Avocado wich can trigger actions if reaching quorum `requiredSigners`.
    ///         signers automatically include owner.
    function signers() external view returns (address[] memory signers_);

    /// @notice returns the number of required signers
    function requiredSigners() external view returns (uint8);

    /// @notice returns the number of allowed signers
    function signersCount() external view returns (uint8);

    /// @notice Avocado owner
    function owner() external view returns (address);

    /// @notice Avocado index (number of Avocado for EOA owner)
    function index() external view returns (uint32);
}

// @dev full interface with some getters for storage variables
interface IAvocadoMultisigV1 is IAvocadoMultisigV1Base {
    /// @notice Domain separator name for signatures
    function DOMAIN_SEPARATOR_NAME() external view returns (string memory);

    /// @notice Domain separator version for signatures
    function DOMAIN_SEPARATOR_VERSION() external view returns (string memory);

    /// @notice incrementing nonce for each valid tx executed (to ensure uniqueness)
    function avoNonce() external view returns (uint256);
}

File 9 of 11 : IAvoFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

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

interface IAvoFactory {
    /// @notice returns AvoRegistry (proxy) address
    function avoRegistry() external view returns (IAvoRegistry);

    /// @notice returns Avocado logic contract address that new Avocado deployments point to
    function avoImpl() external view returns (address);

    /// @notice                 Checks if a certain address is an Avocado smart wallet.
    ///                         Only works for already deployed wallets.
    /// @param avoSmartWallet_  address to check
    /// @return                 true if address is an Avocado
    function isAvocado(address avoSmartWallet_) external view returns (bool);

    /// @notice                     Computes the deterministic Avocado address for `owner_` based on Create2
    /// @param owner_               Avocado owner
    /// @param index_               index number of Avocado for `owner_` EOA
    /// @return computedAddress_    computed address for the Avocado contract
    function computeAvocado(address owner_, uint32 index_) external view returns (address computedAddress_);

    /// @notice         Deploys an Avocado for a certain `owner_` deterministcally using Create2.
    ///                 Does not check if contract at address already exists (AvoForwarder does that)
    /// @param owner_   Avocado owner
    /// @param index_   index number of Avocado for `owner_` EOA
    /// @return         deployed address for the Avocado contract
    function deploy(address owner_, uint32 index_) external returns (address);

    /// @notice                    Deploys an Avocado with non-default version for an `owner_`
    ///                            deterministcally using Create2.
    ///                            Does not check if contract at address already exists (AvoForwarder does that)
    /// @param owner_              Avocado owner
    /// @param index_              index number of Avocado for `owner_` EOA
    /// @param avoVersion_         Version of Avocado logic contract to deploy
    /// @return                    deployed address for the Avocado contract
    function deployWithVersion(address owner_, uint32 index_, address avoVersion_) external returns (address);

    /// @notice                 registry can update the current Avocado implementation contract set as default
    ///                         `_avoImpl` logic contract address for new deployments
    /// @param avoImpl_ the new avoImpl address
    function setAvoImpl(address avoImpl_) external;

    /// @notice returns the bytecode (hash) for the Avocado contract used for Create2 address computation
    function avocadoBytecode() external view returns (bytes32);
}

File 10 of 11 : IAvoForwarder.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

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

interface IAvoForwarder {
    /// @notice returns the AvoFactory (proxy) address
    function avoFactory() external view returns (IAvoFactory);
}

File 11 of 11 : IAvoRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

interface IAvoFeeCollector {
    /// @notice fee config params used to determine the fee for Avocado smart wallet `castAuthorized()` calls
    struct FeeConfig {
        ///
        /// @param feeCollector address that the fee should be paid to
        address payable feeCollector;
        ///
        /// @param mode current fee mode: 0 = percentage fee (gas cost markup); 1 = static fee (better for L2)
        uint8 mode;
        ///
        /// @param fee current fee amount:
        /// - for mode percentage: fee in 1e6 percentage (1e8 = 100%, 1e6 = 1%)
        /// - for static mode: absolute amount in native gas token to charge
        ///                    (max value 30_9485_009,821345068724781055 in 1e18)
        uint88 fee;
    }

    /// @notice calculates the `feeAmount_` for an Avocado (`msg.sender`) transaction `gasUsed_` based on
    ///         fee configuration present on the contract
    /// @param  gasUsed_       amount of gas used, required if mode is percentage. not used if mode is static fee.
    /// @return feeAmount_    calculated fee amount to be paid
    /// @return feeCollector_ address to send the fee to
    function calcFee(uint256 gasUsed_) external view returns (uint256 feeAmount_, address payable feeCollector_);
}

interface IAvoRegistry is IAvoFeeCollector {
    /// @notice                      checks if an address is listed as allowed AvoForwarder version, reverts if not.
    /// @param avoForwarderVersion_  address of the AvoForwarder logic contract to check
    function requireValidAvoForwarderVersion(address avoForwarderVersion_) external view;

    /// @notice                     checks if an address is listed as allowed Avocado version, reverts if not.
    /// @param avoVersion_          address of the Avocado logic contract to check
    function requireValidAvoVersion(address avoVersion_) external view;
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IAvoFactory","name":"avoFactory_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AvoForwarder__InvalidParams","type":"error"},{"inputs":[],"name":"AvoForwarder__LegacyVersionNotDeployed","type":"error"},{"inputs":[],"name":"AvoForwarder__Unauthorized","type":"error"},{"inputs":[],"name":"AvoForwarder__Unsupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"auth","type":"address"},{"indexed":true,"internalType":"bool","name":"status","type":"bool"}],"name":"AuthUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"broadcaster","type":"address"},{"indexed":true,"internalType":"bool","name":"status","type":"bool"}],"name":"BroadcasterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"avocadoOwner","type":"address"},{"indexed":false,"internalType":"uint32","name":"index","type":"uint32"},{"indexed":true,"internalType":"address","name":"avocadoAddress","type":"address"},{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"bytes","name":"metadata","type":"bytes"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"ExecuteFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"avocadoOwner","type":"address"},{"indexed":false,"internalType":"uint32","name":"index","type":"uint32"},{"indexed":true,"internalType":"address","name":"avocadoAddress","type":"address"},{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"bytes","name":"metadata","type":"bytes"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"avoFactory","outputs":[{"internalType":"contract IAvoFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"}],"name":"avoNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"avocadoBytecode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"}],"name":"avocadoVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"}],"name":"avocadoVersionName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"}],"name":"computeAvocado","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams","name":"params_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes_","type":"tuple[]"}],"name":"estimateChainAgnosticV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params_","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"}],"name":"estimateV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams","name":"params","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes","type":"tuple[]"}],"internalType":"struct AvoForwarderStructs.ExecuteBatchParams[]","name":"batches_","type":"tuple[]"},{"internalType":"bool","name":"continueOnRevert_","type":"bool"}],"name":"executeBatchV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams","name":"params_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes_","type":"tuple[]"}],"name":"executeChainAgnosticV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params_","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"}],"name":"executeV1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams[]","name":"params_","type":"tuple[]"}],"name":"getAvocadoChainAgnosticHashes","outputs":[{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes_","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address[]","name":"allowedBroadcasters_","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"auth_","type":"address"}],"name":"isAuth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"broadcaster_","type":"address"}],"name":"isBroadcaster","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams","name":"params","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes","type":"tuple[]"}],"internalType":"struct AvoForwarderStructs.ExecuteBatchParams[]","name":"batches_","type":"tuple[]"},{"internalType":"bool","name":"continueOnRevert_","type":"bool"}],"name":"simulateBatchV1","outputs":[{"components":[{"internalType":"uint256","name":"castGasUsed","type":"uint256"},{"internalType":"bool","name":"success","type":"bool"},{"internalType":"string","name":"revertReason","type":"string"}],"internalType":"struct AvoForwarderStructs.SimulateBatchResult[]","name":"results_","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams","name":"params_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes_","type":"tuple[]"}],"name":"simulateChainAgnosticV1","outputs":[{"internalType":"uint256","name":"castGasUsed_","type":"uint256"},{"internalType":"uint256","name":"deploymentGasUsed_","type":"uint256"},{"internalType":"bool","name":"isDeployed_","type":"bool"},{"internalType":"bool","name":"success_","type":"bool"},{"internalType":"string","name":"revertReason_","type":"string"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params_","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"}],"name":"simulateV1","outputs":[{"internalType":"uint256","name":"castGasUsed_","type":"uint256"},{"internalType":"uint256","name":"deploymentGasUsed_","type":"uint256"},{"internalType":"bool","name":"isDeployed_","type":"bool"},{"internalType":"bool","name":"success_","type":"bool"},{"internalType":"string","name":"revertReason_","type":"string"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct AvoForwarderStructs.AddressBool[]","name":"authsStatus_","type":"tuple[]"}],"name":"updateAuths","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct AvoForwarderStructs.AddressBool[]","name":"broadcastersStatus_","type":"tuple[]"}],"name":"updateBroadcasters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams","type":"tuple"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastChainAgnosticParams","name":"params_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.ChainAgnosticHash[]","name":"chainAgnosticHashes_","type":"tuple[]"}],"name":"verifyChainAgnosticV1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint32","name":"index_","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"operation","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.Action[]","name":"actions","type":"tuple[]"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int256","name":"avoNonce","type":"int256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct AvocadoMultisigStructs.CastParams","name":"params_","type":"tuple"},{"components":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"validAfter","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct AvocadoMultisigStructs.CastForwardParams","name":"forwardParams_","type":"tuple"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct AvocadoMultisigStructs.SignatureParams[]","name":"signaturesParams_","type":"tuple[]"}],"name":"verifyV1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b506040516200492d3803806200492d83398101604081905262000034916200013a565b6001600160a01b0381166080819052819081906200006557604051637bb8c4fb60e01b815260040160405180910390fd5b6200006f62000078565b5050506200016c565b600054610100900460ff1615620000e55760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116101562000138576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6000602082840312156200014d57600080fd5b81516001600160a01b03811681146200016557600080fd5b9392505050565b60805161476d620001c06000396000818161048001528181610a7e01528181610b9101528181610db101528181610e7601528181610fc40152818161241201528181612ee90152612fdb015261476d6000f3fe6080604052600436106101965760003560e01c8063700742eb116100e1578063ad9ddf171161008a578063d817a8c911610064578063d817a8c9146104b5578063d99f5d3a146104d5578063db421487146104f5578063f2fde38b1461052957600080fd5b8063ad9ddf171461045b578063b0c5ea881461046e578063c5e15557146104a257600080fd5b806378853bb5116100bb57806378853bb5146103a95780638da5cb5b146103ef578063946d92041461043b57600080fd5b8063700742eb14610361578063715018a614610381578063715b9fdc1461039657600080fd5b806355ecef671161014357806368626d8f1161011d57806368626d8f1461030a57806369d12c3a1461032e5780636d85c65f1461034e57600080fd5b806355ecef67146102a95780635868e124146102c957806359e727eb146102f757600080fd5b80633f66feff116101745780633f66feff1461024757806340be24e9146102695780634ad446881461029657600080fd5b8063139203eb1461019b57806322917a0c146101d15780632520e7ff14610201575b600080fd5b3480156101a757600080fd5b506101bb6101b63660046136ae565b610549565b6040516101c89190613711565b60405180910390f35b3480156101dd57600080fd5b506101f16101ec366004613760565b61061b565b60405190151581526020016101c8565b34801561020d57600080fd5b506101f161021c366004613833565b73ffffffffffffffffffffffffffffffffffffffff1660009081526066602052604090205460011490565b34801561025357600080fd5b50610267610262366004613895565b6106d0565b005b34801561027557600080fd5b506102896102843660046138d7565b6109e5565b6040516101c8919061397a565b6102676102a4366004613760565b610cb8565b3480156102b557600080fd5b506102896102c43660046138d7565b610d18565b3480156102d557600080fd5b506102e96102e43660046138d7565b610f4d565b6040519081526020016101c8565b610267610305366004613760565b6110d7565b61031d610318366004613760565b61113b565b6040516101c895949392919061398d565b34801561033a57600080fd5b506101f16103493660046139c7565b611665565b61026761035c3660046139c7565b61171d565b34801561036d57600080fd5b5061026761037c366004613895565b61177a565b34801561038d57600080fd5b5061026761199a565b6102676103a4366004613a95565b6119d4565b3480156103b557600080fd5b506101f16103c4366004613833565b73ffffffffffffffffffffffffffffffffffffffff1660009081526065602052604090205460011490565b3480156103fb57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b34801561044757600080fd5b50610267610456366004613aec565b611ce2565b61031d6104693660046139c7565b612011565b34801561047a57600080fd5b506104167f000000000000000000000000000000000000000000000000000000000000000081565b6102676104b03660046139c7565b61231b565b3480156104c157600080fd5b506104166104d03660046138d7565b612373565b6104e86104e3366004613a95565b6124ac565b6040516101c89190613b41565b34801561050157600080fd5b506102e97f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5481565b34801561053557600080fd5b50610267610544366004613833565b612dbb565b606060006105578686612e72565b6040517f8449b2c900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690638449b2c9906105ae9087908790600401613ed9565b600060405180830381865afa1580156105cb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610611919081019061401f565b9695505050505050565b6000806106288888612e72565b6040517f2a4bf79400000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690632a4bf7949061068390899089908990899060040161419b565b602060405180830381865afa1580156106a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c491906141f9565b98975050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314806107055750336000908152606660205260409020546001145b61073b576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600061075d60335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905060005b828110156109de5760008585838181106107ac576107ac614216565b6107c29260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff160361080f576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085858381811061082357610823614216565b905060400201602001602081019061083b9190614245565b610846576000610849565b60015b60ff16905082806108b55750801580156108b5575085858381811061087057610870614216565b6108869260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6108eb576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806066600088888681811061090257610902614216565b6109189260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205585858381811061095157610951614216565b90506040020160200160208101906109699190614245565b151586868481811061097d5761097d614216565b6109939260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff167fbce29f3c87027a39c8405b00ac40728d467fc8f800c6bbfbb37db8f3380400be60405160405180910390a350600101610790565b5050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff85168385015260006060808501919091528451808503820181526080850186528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a08601527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000831b1660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b15610b8f578073ffffffffffffffffffffffffffffffffffffffff166387265c956040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b41573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b8791908101906142ec565b915050610cb2565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166328807b8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1e9190614321565b73ffffffffffffffffffffffffffffffffffffffff166387265c956040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c68573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610cae91908101906142ec565b9150505b92915050565b33600090815260656020526040902054600114610d01576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0f868686868686613048565b50505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff85168385015260006060808501919091528451808503820181526080850186528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a08601527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000831b1660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b15610e74578073ffffffffffffffffffffffffffffffffffffffff1663b4907ddc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b41573d6000803e3d6000fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166328807b8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f039190614321565b73ffffffffffffffffffffffffffffffffffffffff1663b4907ddc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c68573d6000803e3d6000fd5b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff851683850152600060608085018290528551808603820181526080860187528051908401207fff0000000000000000000000000000000000000000000000000000000000000060a08701527f000000000000000000000000000000000000000000000000000000000000000090911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b156110cd578073ffffffffffffffffffffffffffffffffffffffff1663bda443316040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b87919061433e565b5060009392505050565b6000806110e888888888888861113b565b945094505050508161113157806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128919061397a565b60405180910390fd5b5050505050505050565b60008060008060606111766040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b5a60208201526111868c8c613278565b73ffffffffffffffffffffffffffffffffffffffff909216808452604080517fb4907ddc0000000000000000000000000000000000000000000000000000000081529051929850929650600092839263b4907ddc9160048082019286929091908290030181865afa1580156111ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261124591908101906142ec565b805160209182012060408051808201909152600581527f312e302e3000000000000000000000000000000000000000000000000000000092019190915290507f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c811480611306575060408051808201909152600581527f312e302e310000000000000000000000000000000000000000000000000000006020909101527ffc7f6d936935ae6385924f29da7af79e941070dafe46831a51595892abc1b97a81145b156113f1575a9150826000015173ffffffffffffffffffffffffffffffffffffffff16639428ae4e8c608001356113528f8060a001906113469190614357565b60080261213401919050565b5a61135d91906143eb565b908f8f8f8f6040518763ffffffff1660e01b8152600401611381949392919061419b565b600060405180830381858988f115801561139f573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526113e791908101906143fe565b90955093506114c7565b5a9150826000015173ffffffffffffffffffffffffffffffffffffffff16638142d4018c6080013561142c8f8060a001906113469190614357565b5a61143791906143eb565b908f8f8f8f6040518763ffffffff1660e01b815260040161145b949392919061419b565b600060405180830381858988f1158015611479573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114c191908101906143fe565b90955093505b5a6114d290836143eb565b975050508215611582576114ec60a08b0160808c01613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048e8e8060a001906115669190614357565b6040516115759392919061444f565b60405180910390a4611626565b61159260a08b0160808c01613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38e8e8060a0019061160c9190614357565b8860405161161d9493929190614478565b60405180910390a45b6116566064600a5a846020015161163d91906143eb565b61164791906144aa565b61165191906144c1565b6132e5565b50965096509650965096915050565b6000806116728989612e72565b6040517f0f0bc51500000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690630f0bc515906116cf908a908a908a908a908a906004016144fc565b602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171091906141f9565b9998505050505050505050565b60008061172f89898989898989612011565b945094505050508161176f57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128919061397a565b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314806117af5750336000908152606660205260409020546001145b6117e5576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060005b8181101561199457600084848381811061180557611805614216565b61181b9260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff1603611868576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83838281811061187a5761187a614216565b90506040020160200160208101906118929190614245565b61189d5760006118a0565b60015b60ff16606560008686858181106118b9576118b9614216565b6118cf9260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205583838281811061190857611908614216565b90506040020160200160208101906119209190614245565b151584848381811061193457611934614216565b61194a9260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff167f8e37ce4bd982978769e6e23562ee5a1c223c57e867089adf19509e1e4c6e8eed60405160405180910390a36001016117e9565b50505050565b6119a2613316565b6040517f956cbbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260656020526040902054600114611a1d576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816002811015611a59576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b82811015611cda576000868683818110611a7957611a79614216565b9050602002810190611a8b919061456e565b611a999060808101906145ac565b90501115611bad57611ba6868683818110611ab657611ab6614216565b9050602002810190611ac8919061456e565b611ad6906020810190613833565b878784818110611ae857611ae8614216565b9050602002810190611afa919061456e565b611b0b906040810190602001614614565b888885818110611b1d57611b1d614216565b9050602002810190611b2f919061456e565b611b3d90604081019061462f565b898986818110611b4f57611b4f614216565b9050602002810190611b61919061456e565b611b6f906060810190614663565b8b8b88818110611b8157611b81614216565b9050602002810190611b93919061456e565b611ba19060808101906145ac565b613399565b9150611cc2565b611cbf868683818110611bc257611bc2614216565b9050602002810190611bd4919061456e565b611be2906020810190613833565b878784818110611bf457611bf4614216565b9050602002810190611c06919061456e565b611c17906040810190602001614614565b888885818110611c2957611c29614216565b9050602002810190611c3b919061456e565b611c4990604081019061462f565b611c5390806146cb565b898986818110611c6557611c65614216565b9050602002810190611c77919061456e565b611c8590604081019061462f565b6020018a8a87818110611c9a57611c9a614216565b9050602002810190611cac919061456e565b611cba906060810190614663565b613048565b91505b81158015611cce575083155b611cda57600101611a5d565b505050505050565b8273ffffffffffffffffffffffffffffffffffffffff8116611d30576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600054610100900460ff1615808015611d505750600054600160ff909116105b80611d6a5750303b158015611d6a575060005460ff166001145b611df6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611128565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611e5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611e5d856135a5565b8260005b81811015611fa6576000868683818110611e7d57611e7d614216565b9050602002016020810190611e929190613833565b73ffffffffffffffffffffffffffffffffffffffff1603611edf576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160656000888885818110611ef757611ef7614216565b9050602002016020810190611f0c9190613833565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020556001868683818110611f4757611f47614216565b9050602002016020810190611f5c9190613833565b73ffffffffffffffffffffffffffffffffffffffff167f8e37ce4bd982978769e6e23562ee5a1c223c57e867089adf19509e1e4c6e8eed60405160405180910390a3600101611e61565b505080156109de57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600080600080606061204c6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b5a602082015261205c8d8d613278565b73ffffffffffffffffffffffffffffffffffffffff90921683529550935060005a9050816000015173ffffffffffffffffffffffffffffffffffffffff1663aecd4fb48d602001608001356120c88f80600001906120ba91906146cb565b6113469060a0810190614357565b5a6120d391906143eb565b908f8f8f8f8f6040518863ffffffff1660e01b81526004016120f99594939291906144fc565b600060405180830381858988f1158015612117573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261215f91908101906143fe565b90945092505a61216f90826143eb565b9650508215612237576121828b806146cb565b6121939060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048f8f806000019061220d91906146cb565b61221b9060a0810190614357565b60405161222a9392919061444f565b60405180910390a46122f4565b6122418b806146cb565b6122529060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38f8f80600001906122cc91906146cb565b6122da9060a0810190614357565b886040516122eb9493929190614478565b60405180910390a45b61230b6064600a5a846020015161163d91906143eb565b5097509750975097509792505050565b33600090815260656020526040902054600114612364576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61113187878787878787613399565b600073ffffffffffffffffffffffffffffffffffffffff83163b1561239a57506000610cb2565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660208084019190915263ffffffff86168385015260006060808501919091528451808503820181526080850186528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a08601527f000000000000000000000000000000000000000000000000000000000000000090911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a185015260b58401527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808501919091528451808503909101815260f590930190935281519190920120165b9392505050565b606060005a90508360028110156124ef576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff81111561250857612508613f78565b60405190808252806020026020018201604052801561255557816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816125265790505b50925060008060005b83811015612d9d576125d589898381811061257b5761257b614216565b905060200281019061258d919061456e565b61259b906020810190613833565b8a8a848181106125ad576125ad614216565b90506020028101906125bf919061456e565b6125d0906040810190602001614614565b613278565b50909350505a915060008989838181106125f1576125f1614216565b9050602002810190612603919061456e565b6126119060808101906145ac565b9050111561281e578273ffffffffffffffffffffffffffffffffffffffff1663aecd4fb48a8a8481811061264757612647614216565b9050602002810190612659919061456e565b61266790604081019061462f565b60a001356126aa8c8c8681811061268057612680614216565b9050602002810190612692919061456e565b6126a090604081019061462f565b6120ba90806146cb565b5a6126b591906143eb565b908c8c868181106126c8576126c8614216565b90506020028101906126da919061456e565b6126e890604081019061462f565b8d8d878181106126fa576126fa614216565b905060200281019061270c919061456e565b61271a906060810190614663565b8f8f8981811061272c5761272c614216565b905060200281019061273e919061456e565b61274c9060808101906145ac565b6040518863ffffffff1660e01b815260040161276c9594939291906144fc565b600060405180830381858988f115801561278a573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127d291908101906143fe565b8783815181106127e4576127e4614216565b602002602001015160200188848151811061280157612801614216565b602002602001015160400182905282151515158152505050612a01565b8273ffffffffffffffffffffffffffffffffffffffff16638142d4018a8a8481811061284c5761284c614216565b905060200281019061285e919061456e565b61286c90604081019061462f565b60a001356128858c8c8681811061268057612680614216565b5a61289091906143eb565b908c8c868181106128a3576128a3614216565b90506020028101906128b5919061456e565b6128c390604081019061462f565b6128cd90806146cb565b8d8d878181106128df576128df614216565b90506020028101906128f1919061456e565b6128ff90604081019061462f565b6020018e8e8881811061291457612914614216565b9050602002810190612926919061456e565b612934906060810190614663565b6040518763ffffffff1660e01b8152600401612953949392919061419b565b600060405180830381858988f1158015612971573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526129b991908101906143fe565b8783815181106129cb576129cb614216565b60200260200101516020018884815181106129e8576129e8614216565b6020026020010151604001829052821515151581525050505b5a612a0c90836143eb565b868281518110612a1e57612a1e614216565b60200260200101516000018181525050858181518110612a4057612a40614216565b60200260200101516020015115612bcf57888882818110612a6357612a63614216565b9050602002810190612a75919061456e565b612a8390604081019061462f565b612a8d90806146cb565b612a9e9060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168a8a84818110612add57612add614216565b9050602002810190612aef919061456e565b612afd906020810190613833565b73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048c8c86818110612b4657612b46614216565b9050602002810190612b58919061456e565b612b69906040810190602001614614565b8d8d87818110612b7b57612b7b614216565b9050602002810190612b8d919061456e565b612b9b90604081019061462f565b612ba590806146cb565b612bb39060a0810190614357565b604051612bc29392919061444f565b60405180910390a4612d68565b888882818110612be157612be1614216565b9050602002810190612bf3919061456e565b612c0190604081019061462f565b612c0b90806146cb565b612c1c9060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168a8a84818110612c5b57612c5b614216565b9050602002810190612c6d919061456e565b612c7b906020810190613833565b73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38c8c86818110612cc457612cc4614216565b9050602002810190612cd6919061456e565b612ce7906040810190602001614614565b8d8d87818110612cf957612cf9614216565b9050602002810190612d0b919061456e565b612d1990604081019061462f565b612d2390806146cb565b612d319060a0810190614357565b8c8881518110612d4357612d43614216565b602002602001015160400151604051612d5f9493929190614478565b60405180910390a45b858181518110612d7a57612d7a614216565b602002602001015160200151158015612d91575086155b612d9d5760010161255e565b50612db06064600a5a61163d90886143eb565b505050509392505050565b612dc3613316565b73ffffffffffffffffffffffffffffffffffffffff8116612e66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401611128565b612e6f816135a5565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff851683850152600060608085018290528551808603820181526080860187528051908401207fff0000000000000000000000000000000000000000000000000000000000000060a08701527f000000000000000000000000000000000000000000000000000000000000000090911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b15612f8a579050610cb2565b6040517f2adc4cf700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015263ffffffff851660248301527f00000000000000000000000000000000000000000000000000000000000000001690632adc4cf7906044016020604051808303816000875af1158015613024573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b879190614321565b6000806130558888612e72565b9050606073ffffffffffffffffffffffffffffffffffffffff8216639428ae4e608088013561308a61134660a08c018c614357565b5a61309591906143eb565b908a8a8a8a6040518763ffffffff1660e01b81526004016130b9949392919061419b565b600060405180830381858988f11580156130d7573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261311f91908101906143fe565b909350905082156131cc5761313a60a0880160808901613833565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048b8b8060a001906131b09190614357565b6040516131bf9392919061444f565b60405180910390a461326c565b6131dc60a0880160808901613833565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38b8b8060a001906132529190614357565b876040516132639493929190614478565b60405180910390a45b50509695505050505050565b6000808061dead33146132b7576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005a90506132c68686612e72565b93505a6132d390826143eb565b9250620186a083109150509250925092565b60005a905060005b825a6132f990846143eb565b10156133115780613309816146ff565b9150506132ed565b505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314613397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611128565b565b6000806133a68989612e72565b9050606073ffffffffffffffffffffffffffffffffffffffff82166333a2d58460a08a01356133d86120ba8c806146cb565b5a6133e391906143eb565b908b8b8b8b8b6040518863ffffffff1660e01b81526004016134099594939291906144fc565b600060405180830381858988f1158015613427573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261346f91908101906143fe565b9093509050821561350a5761348488806146cb565b6134959060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff90811690838116908c167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048c6134e08d806146cb565b6134ee9060a0810190614357565b6040516134fd9392919061444f565b60405180910390a4613598565b61351488806146cb565b6135259060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff90811690838116908c167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38c6135708d806146cb565b61357e9060a0810190614357565b8760405161358f9493929190614478565b60405180910390a45b5050979650505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e6f57600080fd5b80356136498161361c565b919050565b803563ffffffff8116811461364957600080fd5b60008083601f84011261367457600080fd5b50813567ffffffffffffffff81111561368c57600080fd5b6020830191508360208260051b85010111156136a757600080fd5b9250929050565b600080600080606085870312156136c457600080fd5b84356136cf8161361c565b93506136dd6020860161364e565b9250604085013567ffffffffffffffff8111156136f957600080fd5b61370587828801613662565b95989497509550505050565b602080825282518282018190526000919060409081850190868401855b828110156137535781518051855286015186850152928401929085019060010161372e565b5091979650505050505050565b60008060008060008086880361012081121561377b57600080fd5b87356137868161361c565b96506137946020890161364e565b9550604088013567ffffffffffffffff808211156137b157600080fd5b9089019060c0828c0312156137c557600080fd5b81965060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0840112156137f857600080fd5b60608a0195506101008a013592508083111561381357600080fd5b505061382189828a01613662565b979a9699509497509295939492505050565b60006020828403121561384557600080fd5b81356124a58161361c565b60008083601f84011261386257600080fd5b50813567ffffffffffffffff81111561387a57600080fd5b6020830191508360208260061b85010111156136a757600080fd5b600080602083850312156138a857600080fd5b823567ffffffffffffffff8111156138bf57600080fd5b6138cb85828601613850565b90969095509350505050565b600080604083850312156138ea57600080fd5b82356138f58161361c565b91506139036020840161364e565b90509250929050565b60005b8381101561392757818101518382015260200161390f565b50506000910152565b6000815180845261394881602086016020860161390c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006124a56020830184613930565b8581528460208201528315156040820152821515606082015260a0608082015260006139bc60a0830184613930565b979650505050505050565b600080600080600080600060a0888a0312156139e257600080fd5b87356139ed8161361c565b96506139fb6020890161364e565b9550604088013567ffffffffffffffff80821115613a1857600080fd5b9089019060e0828c031215613a2c57600080fd5b90955060608901359080821115613a4257600080fd5b613a4e8b838c01613662565b909650945060808a0135915080821115613a6757600080fd5b50613a748a828b01613850565b989b979a50959850939692959293505050565b8015158114612e6f57600080fd5b600080600060408486031215613aaa57600080fd5b833567ffffffffffffffff811115613ac157600080fd5b613acd86828701613662565b9094509250506020840135613ae181613a87565b809150509250925092565b600080600060408486031215613b0157600080fd5b8335613b0c8161361c565b9250602084013567ffffffffffffffff811115613b2857600080fd5b613b3486828701613662565b9497909650939450505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613bd2578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180518452878101511515888501528601516060878501819052613bbe81860183613930565b968901969450505090860190600101613b68565b509098975050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c1557600080fd5b830160208101925035905067ffffffffffffffff811115613c3557600080fd5b8036038213156136a757600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b81835260006020808501808196508560051b81019150846000805b88811015613d56578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81893603018112613ce6578283fd5b880160808135613cf58161361c565b73ffffffffffffffffffffffffffffffffffffffff168752613d1982890183613be0565b828a8a0152613d2b838a018284613c44565b604085810135908b015260609485013594909901939093525050509885019891850191600101613ca8565b509298975050505050505050565b600081357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112613d9857600080fd5b820160208101903567ffffffffffffffff811115613db557600080fd5b8060051b3603821315613dc757600080fd5b60c08552613dd960c086018284613c8d565b915050602083013560208501526040830135604085015260608301356060850152613e066080840161363e565b73ffffffffffffffffffffffffffffffffffffffff166080850152613e2e60a0840184613be0565b85830360a0870152610611838284613c44565b600081357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41833603018112613e7557600080fd5b60e08452613e8860e08501848301613d64565b9050613ec5602085016020850180358252602081013560208301526040810135604083015260608101356060830152608081013560808301525050565b60c083013560c08501528091505092915050565b60208082528181018390526000906040600585901b840181019084018684805b88811015613d56577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218b3603018112613f59578283fd5b613f65868c8301613e41565b9550509285019291850191600101613ef9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613fca57613fca613f78565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561401757614017613f78565b604052919050565b6000602080838503121561403257600080fd5b825167ffffffffffffffff8082111561404a57600080fd5b818501915085601f83011261405e57600080fd5b81518181111561407057614070613f78565b61407e848260051b01613fd0565b818152848101925060069190911b83018401908782111561409e57600080fd5b928401925b818410156139bc57604084890312156140bc5760008081fd5b6140c4613fa7565b8451815285850151868201528352604090930192918401916140a3565b81835260006020808501808196508560051b81019150846000805b88811015613d56578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc189360301811261413a578283fd5b880160406141488280613be0565b828952614158838a018284613c44565b9250505087820135915061416b8261361c565b73ffffffffffffffffffffffffffffffffffffffff919091169587019590955298850198918501916001016140fc565b60e0815260006141ae60e0830187613d64565b6141e6602084018780358252602081013560208301526040810135604083015260608101356060830152608081013560808301525050565b82810360c08401526139bc8185876140e1565b60006020828403121561420b57600080fd5b81516124a581613a87565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561425757600080fd5b81356124a581613a87565b600082601f83011261427357600080fd5b815167ffffffffffffffff81111561428d5761428d613f78565b6142be60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613fd0565b8181528460208386010111156142d357600080fd5b6142e482602083016020870161390c565b949350505050565b6000602082840312156142fe57600080fd5b815167ffffffffffffffff81111561431557600080fd5b610cae84828501614262565b60006020828403121561433357600080fd5b81516124a58161361c565b60006020828403121561435057600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261438c57600080fd5b83018035915067ffffffffffffffff8211156143a757600080fd5b6020019150368190038213156136a757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610cb257610cb26143bc565b6000806040838503121561441157600080fd5b825161441c81613a87565b602084015190925067ffffffffffffffff81111561443957600080fd5b61444585828601614262565b9150509250929050565b63ffffffff8416815260406020820152600061446f604083018486613c44565b95945050505050565b63ffffffff85168152606060208201526000614498606083018587613c44565b82810360408401526139bc8185613930565b8082028115828204841417610cb257610cb26143bc565b6000826144f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60608152600061450f6060830188613e41565b60208382038185015261452382888a6140e1565b84810360408681019190915286825287935090820160005b8781101561455f57843582528385013584830152938201939082019060010161453b565b509a9950505050505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126145a257600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126145e157600080fd5b83018035915067ffffffffffffffff8211156145fc57600080fd5b6020019150600681901b36038213156136a757600080fd5b60006020828403121561462657600080fd5b6124a58261364e565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218336030181126145a257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261469857600080fd5b83018035915067ffffffffffffffff8211156146b357600080fd5b6020019150600581901b36038213156136a757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126145a257600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614730576147306143bc565b506001019056fea2646970667358221220380cb1d59ec81db9112a02f4e44aa1758556f27507ba641a65199a45450eed3364736f6c63430008120033000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e687

Deployed Bytecode

0x6080604052600436106101965760003560e01c8063700742eb116100e1578063ad9ddf171161008a578063d817a8c911610064578063d817a8c9146104b5578063d99f5d3a146104d5578063db421487146104f5578063f2fde38b1461052957600080fd5b8063ad9ddf171461045b578063b0c5ea881461046e578063c5e15557146104a257600080fd5b806378853bb5116100bb57806378853bb5146103a95780638da5cb5b146103ef578063946d92041461043b57600080fd5b8063700742eb14610361578063715018a614610381578063715b9fdc1461039657600080fd5b806355ecef671161014357806368626d8f1161011d57806368626d8f1461030a57806369d12c3a1461032e5780636d85c65f1461034e57600080fd5b806355ecef67146102a95780635868e124146102c957806359e727eb146102f757600080fd5b80633f66feff116101745780633f66feff1461024757806340be24e9146102695780634ad446881461029657600080fd5b8063139203eb1461019b57806322917a0c146101d15780632520e7ff14610201575b600080fd5b3480156101a757600080fd5b506101bb6101b63660046136ae565b610549565b6040516101c89190613711565b60405180910390f35b3480156101dd57600080fd5b506101f16101ec366004613760565b61061b565b60405190151581526020016101c8565b34801561020d57600080fd5b506101f161021c366004613833565b73ffffffffffffffffffffffffffffffffffffffff1660009081526066602052604090205460011490565b34801561025357600080fd5b50610267610262366004613895565b6106d0565b005b34801561027557600080fd5b506102896102843660046138d7565b6109e5565b6040516101c8919061397a565b6102676102a4366004613760565b610cb8565b3480156102b557600080fd5b506102896102c43660046138d7565b610d18565b3480156102d557600080fd5b506102e96102e43660046138d7565b610f4d565b6040519081526020016101c8565b610267610305366004613760565b6110d7565b61031d610318366004613760565b61113b565b6040516101c895949392919061398d565b34801561033a57600080fd5b506101f16103493660046139c7565b611665565b61026761035c3660046139c7565b61171d565b34801561036d57600080fd5b5061026761037c366004613895565b61177a565b34801561038d57600080fd5b5061026761199a565b6102676103a4366004613a95565b6119d4565b3480156103b557600080fd5b506101f16103c4366004613833565b73ffffffffffffffffffffffffffffffffffffffff1660009081526065602052604090205460011490565b3480156103fb57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b34801561044757600080fd5b50610267610456366004613aec565b611ce2565b61031d6104693660046139c7565b612011565b34801561047a57600080fd5b506104167f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e68781565b6102676104b03660046139c7565b61231b565b3480156104c157600080fd5b506104166104d03660046138d7565b612373565b6104e86104e3366004613a95565b6124ac565b6040516101c89190613b41565b34801561050157600080fd5b506102e97f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5481565b34801561053557600080fd5b50610267610544366004613833565b612dbb565b606060006105578686612e72565b6040517f8449b2c900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690638449b2c9906105ae9087908790600401613ed9565b600060405180830381865afa1580156105cb573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610611919081019061401f565b9695505050505050565b6000806106288888612e72565b6040517f2a4bf79400000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690632a4bf7949061068390899089908990899060040161419b565b602060405180830381865afa1580156106a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c491906141f9565b98975050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314806107055750336000908152606660205260409020546001145b61073b576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600061075d60335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905060005b828110156109de5760008585838181106107ac576107ac614216565b6107c29260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff160361080f576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085858381811061082357610823614216565b905060400201602001602081019061083b9190614245565b610846576000610849565b60015b60ff16905082806108b55750801580156108b5575085858381811061087057610870614216565b6108869260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6108eb576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806066600088888681811061090257610902614216565b6109189260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205585858381811061095157610951614216565b90506040020160200160208101906109699190614245565b151586868481811061097d5761097d614216565b6109939260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff167fbce29f3c87027a39c8405b00ac40728d467fc8f800c6bbfbb37db8f3380400be60405160405180910390a350600101610790565b5050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff85168385015260006060808501919091528451808503820181526080850186528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a08601527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e687831b1660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b15610b8f578073ffffffffffffffffffffffffffffffffffffffff166387265c956040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b41573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b8791908101906142ec565b915050610cb2565b7f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e68773ffffffffffffffffffffffffffffffffffffffff166328807b8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1e9190614321565b73ffffffffffffffffffffffffffffffffffffffff166387265c956040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c68573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610cae91908101906142ec565b9150505b92915050565b33600090815260656020526040902054600114610d01576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0f868686868686613048565b50505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff85168385015260006060808501919091528451808503820181526080850186528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a08601527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e687831b1660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b15610e74578073ffffffffffffffffffffffffffffffffffffffff1663b4907ddc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b41573d6000803e3d6000fd5b7f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e68773ffffffffffffffffffffffffffffffffffffffff166328807b8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f039190614321565b73ffffffffffffffffffffffffffffffffffffffff1663b4907ddc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c68573d6000803e3d6000fd5b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff851683850152600060608085018290528551808603820181526080860187528051908401207fff0000000000000000000000000000000000000000000000000000000000000060a08701527f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e68790911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b156110cd578073ffffffffffffffffffffffffffffffffffffffff1663bda443316040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b87919061433e565b5060009392505050565b6000806110e888888888888861113b565b945094505050508161113157806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128919061397a565b60405180910390fd5b5050505050505050565b60008060008060606111766040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b5a60208201526111868c8c613278565b73ffffffffffffffffffffffffffffffffffffffff909216808452604080517fb4907ddc0000000000000000000000000000000000000000000000000000000081529051929850929650600092839263b4907ddc9160048082019286929091908290030181865afa1580156111ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261124591908101906142ec565b805160209182012060408051808201909152600581527f312e302e3000000000000000000000000000000000000000000000000000000092019190915290507f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c811480611306575060408051808201909152600581527f312e302e310000000000000000000000000000000000000000000000000000006020909101527ffc7f6d936935ae6385924f29da7af79e941070dafe46831a51595892abc1b97a81145b156113f1575a9150826000015173ffffffffffffffffffffffffffffffffffffffff16639428ae4e8c608001356113528f8060a001906113469190614357565b60080261213401919050565b5a61135d91906143eb565b908f8f8f8f6040518763ffffffff1660e01b8152600401611381949392919061419b565b600060405180830381858988f115801561139f573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526113e791908101906143fe565b90955093506114c7565b5a9150826000015173ffffffffffffffffffffffffffffffffffffffff16638142d4018c6080013561142c8f8060a001906113469190614357565b5a61143791906143eb565b908f8f8f8f6040518763ffffffff1660e01b815260040161145b949392919061419b565b600060405180830381858988f1158015611479573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114c191908101906143fe565b90955093505b5a6114d290836143eb565b975050508215611582576114ec60a08b0160808c01613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048e8e8060a001906115669190614357565b6040516115759392919061444f565b60405180910390a4611626565b61159260a08b0160808c01613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38e8e8060a0019061160c9190614357565b8860405161161d9493929190614478565b60405180910390a45b6116566064600a5a846020015161163d91906143eb565b61164791906144aa565b61165191906144c1565b6132e5565b50965096509650965096915050565b6000806116728989612e72565b6040517f0f0bc51500000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690630f0bc515906116cf908a908a908a908a908a906004016144fc565b602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171091906141f9565b9998505050505050505050565b60008061172f89898989898989612011565b945094505050508161176f57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611128919061397a565b505050505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314806117af5750336000908152606660205260409020546001145b6117e5576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060005b8181101561199457600084848381811061180557611805614216565b61181b9260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff1603611868576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83838281811061187a5761187a614216565b90506040020160200160208101906118929190614245565b61189d5760006118a0565b60015b60ff16606560008686858181106118b9576118b9614216565b6118cf9260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205583838281811061190857611908614216565b90506040020160200160208101906119209190614245565b151584848381811061193457611934614216565b61194a9260206040909202019081019150613833565b73ffffffffffffffffffffffffffffffffffffffff167f8e37ce4bd982978769e6e23562ee5a1c223c57e867089adf19509e1e4c6e8eed60405160405180910390a36001016117e9565b50505050565b6119a2613316565b6040517f956cbbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260656020526040902054600114611a1d576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816002811015611a59576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b82811015611cda576000868683818110611a7957611a79614216565b9050602002810190611a8b919061456e565b611a999060808101906145ac565b90501115611bad57611ba6868683818110611ab657611ab6614216565b9050602002810190611ac8919061456e565b611ad6906020810190613833565b878784818110611ae857611ae8614216565b9050602002810190611afa919061456e565b611b0b906040810190602001614614565b888885818110611b1d57611b1d614216565b9050602002810190611b2f919061456e565b611b3d90604081019061462f565b898986818110611b4f57611b4f614216565b9050602002810190611b61919061456e565b611b6f906060810190614663565b8b8b88818110611b8157611b81614216565b9050602002810190611b93919061456e565b611ba19060808101906145ac565b613399565b9150611cc2565b611cbf868683818110611bc257611bc2614216565b9050602002810190611bd4919061456e565b611be2906020810190613833565b878784818110611bf457611bf4614216565b9050602002810190611c06919061456e565b611c17906040810190602001614614565b888885818110611c2957611c29614216565b9050602002810190611c3b919061456e565b611c4990604081019061462f565b611c5390806146cb565b898986818110611c6557611c65614216565b9050602002810190611c77919061456e565b611c8590604081019061462f565b6020018a8a87818110611c9a57611c9a614216565b9050602002810190611cac919061456e565b611cba906060810190614663565b613048565b91505b81158015611cce575083155b611cda57600101611a5d565b505050505050565b8273ffffffffffffffffffffffffffffffffffffffff8116611d30576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600054610100900460ff1615808015611d505750600054600160ff909116105b80611d6a5750303b158015611d6a575060005460ff166001145b611df6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611128565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611e5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611e5d856135a5565b8260005b81811015611fa6576000868683818110611e7d57611e7d614216565b9050602002016020810190611e929190613833565b73ffffffffffffffffffffffffffffffffffffffff1603611edf576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160656000888885818110611ef757611ef7614216565b9050602002016020810190611f0c9190613833565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020556001868683818110611f4757611f47614216565b9050602002016020810190611f5c9190613833565b73ffffffffffffffffffffffffffffffffffffffff167f8e37ce4bd982978769e6e23562ee5a1c223c57e867089adf19509e1e4c6e8eed60405160405180910390a3600101611e61565b505080156109de57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600080600080606061204c6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b5a602082015261205c8d8d613278565b73ffffffffffffffffffffffffffffffffffffffff90921683529550935060005a9050816000015173ffffffffffffffffffffffffffffffffffffffff1663aecd4fb48d602001608001356120c88f80600001906120ba91906146cb565b6113469060a0810190614357565b5a6120d391906143eb565b908f8f8f8f8f6040518863ffffffff1660e01b81526004016120f99594939291906144fc565b600060405180830381858988f1158015612117573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261215f91908101906143fe565b90945092505a61216f90826143eb565b9650508215612237576121828b806146cb565b6121939060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048f8f806000019061220d91906146cb565b61221b9060a0810190614357565b60405161222a9392919061444f565b60405180910390a46122f4565b6122418b806146cb565b6122529060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38f8f80600001906122cc91906146cb565b6122da9060a0810190614357565b886040516122eb9493929190614478565b60405180910390a45b61230b6064600a5a846020015161163d91906143eb565b5097509750975097509792505050565b33600090815260656020526040902054600114612364576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61113187878787878787613399565b600073ffffffffffffffffffffffffffffffffffffffff83163b1561239a57506000610cb2565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660208084019190915263ffffffff86168385015260006060808501919091528451808503820181526080850186528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a08601527f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e68790911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a185015260b58401527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808501919091528451808503909101815260f590930190935281519190920120165b9392505050565b606060005a90508360028110156124ef576040517f7bb8c4fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff81111561250857612508613f78565b60405190808252806020026020018201604052801561255557816020015b604080516060808201835260008083526020830152918101919091528152602001906001900390816125265790505b50925060008060005b83811015612d9d576125d589898381811061257b5761257b614216565b905060200281019061258d919061456e565b61259b906020810190613833565b8a8a848181106125ad576125ad614216565b90506020028101906125bf919061456e565b6125d0906040810190602001614614565b613278565b50909350505a915060008989838181106125f1576125f1614216565b9050602002810190612603919061456e565b6126119060808101906145ac565b9050111561281e578273ffffffffffffffffffffffffffffffffffffffff1663aecd4fb48a8a8481811061264757612647614216565b9050602002810190612659919061456e565b61266790604081019061462f565b60a001356126aa8c8c8681811061268057612680614216565b9050602002810190612692919061456e565b6126a090604081019061462f565b6120ba90806146cb565b5a6126b591906143eb565b908c8c868181106126c8576126c8614216565b90506020028101906126da919061456e565b6126e890604081019061462f565b8d8d878181106126fa576126fa614216565b905060200281019061270c919061456e565b61271a906060810190614663565b8f8f8981811061272c5761272c614216565b905060200281019061273e919061456e565b61274c9060808101906145ac565b6040518863ffffffff1660e01b815260040161276c9594939291906144fc565b600060405180830381858988f115801561278a573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526127d291908101906143fe565b8783815181106127e4576127e4614216565b602002602001015160200188848151811061280157612801614216565b602002602001015160400182905282151515158152505050612a01565b8273ffffffffffffffffffffffffffffffffffffffff16638142d4018a8a8481811061284c5761284c614216565b905060200281019061285e919061456e565b61286c90604081019061462f565b60a001356128858c8c8681811061268057612680614216565b5a61289091906143eb565b908c8c868181106128a3576128a3614216565b90506020028101906128b5919061456e565b6128c390604081019061462f565b6128cd90806146cb565b8d8d878181106128df576128df614216565b90506020028101906128f1919061456e565b6128ff90604081019061462f565b6020018e8e8881811061291457612914614216565b9050602002810190612926919061456e565b612934906060810190614663565b6040518763ffffffff1660e01b8152600401612953949392919061419b565b600060405180830381858988f1158015612971573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526129b991908101906143fe565b8783815181106129cb576129cb614216565b60200260200101516020018884815181106129e8576129e8614216565b6020026020010151604001829052821515151581525050505b5a612a0c90836143eb565b868281518110612a1e57612a1e614216565b60200260200101516000018181525050858181518110612a4057612a40614216565b60200260200101516020015115612bcf57888882818110612a6357612a63614216565b9050602002810190612a75919061456e565b612a8390604081019061462f565b612a8d90806146cb565b612a9e9060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168a8a84818110612add57612add614216565b9050602002810190612aef919061456e565b612afd906020810190613833565b73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048c8c86818110612b4657612b46614216565b9050602002810190612b58919061456e565b612b69906040810190602001614614565b8d8d87818110612b7b57612b7b614216565b9050602002810190612b8d919061456e565b612b9b90604081019061462f565b612ba590806146cb565b612bb39060a0810190614357565b604051612bc29392919061444f565b60405180910390a4612d68565b888882818110612be157612be1614216565b9050602002810190612bf3919061456e565b612c0190604081019061462f565b612c0b90806146cb565b612c1c9060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168a8a84818110612c5b57612c5b614216565b9050602002810190612c6d919061456e565b612c7b906020810190613833565b73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38c8c86818110612cc457612cc4614216565b9050602002810190612cd6919061456e565b612ce7906040810190602001614614565b8d8d87818110612cf957612cf9614216565b9050602002810190612d0b919061456e565b612d1990604081019061462f565b612d2390806146cb565b612d319060a0810190614357565b8c8881518110612d4357612d43614216565b602002602001015160400151604051612d5f9493929190614478565b60405180910390a45b858181518110612d7a57612d7a614216565b602002602001015160200151158015612d91575086155b612d9d5760010161255e565b50612db06064600a5a61163d90886143eb565b505050509392505050565b612dc3613316565b73ffffffffffffffffffffffffffffffffffffffff8116612e66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401611128565b612e6f816135a5565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660208084019190915263ffffffff851683850152600060608085018290528551808603820181526080860187528051908401207fff0000000000000000000000000000000000000000000000000000000000000060a08701527f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e68790911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a186015260b58501527f6b106ae0e3afae21508569f62d81c7d826b900a2e9ccc973ba97abfae026fc5460d5808601919091528551808603909101815260f5909401909452825192019190912016803b15612f8a579050610cb2565b6040517f2adc4cf700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015263ffffffff851660248301527f000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e6871690632adc4cf7906044016020604051808303816000875af1158015613024573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b879190614321565b6000806130558888612e72565b9050606073ffffffffffffffffffffffffffffffffffffffff8216639428ae4e608088013561308a61134660a08c018c614357565b5a61309591906143eb565b908a8a8a8a6040518763ffffffff1660e01b81526004016130b9949392919061419b565b600060405180830381858988f11580156130d7573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261311f91908101906143fe565b909350905082156131cc5761313a60a0880160808901613833565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048b8b8060a001906131b09190614357565b6040516131bf9392919061444f565b60405180910390a461326c565b6131dc60a0880160808901613833565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38b8b8060a001906132529190614357565b876040516132639493929190614478565b60405180910390a45b50509695505050505050565b6000808061dead33146132b7576040517f7a3acd8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005a90506132c68686612e72565b93505a6132d390826143eb565b9250620186a083109150509250925092565b60005a905060005b825a6132f990846143eb565b10156133115780613309816146ff565b9150506132ed565b505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314613397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611128565b565b6000806133a68989612e72565b9050606073ffffffffffffffffffffffffffffffffffffffff82166333a2d58460a08a01356133d86120ba8c806146cb565b5a6133e391906143eb565b908b8b8b8b8b6040518863ffffffff1660e01b81526004016134099594939291906144fc565b600060405180830381858988f1158015613427573d6000803e3d6000fd5b5050505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261346f91908101906143fe565b9093509050821561350a5761348488806146cb565b6134959060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff90811690838116908c167fdaf1e6e151973de199f3ea25b9c6a7c3d94299dc85e269cfd20e48e517ecf7048c6134e08d806146cb565b6134ee9060a0810190614357565b6040516134fd9392919061444f565b60405180910390a4613598565b61351488806146cb565b6135259060a0810190608001613833565b73ffffffffffffffffffffffffffffffffffffffff90811690838116908c167f5350e8e0c8cacf19dd5334174c3d5a3e8b7d7e00fdb5457d7ddec04b5e4a1af38c6135708d806146cb565b61357e9060a0810190614357565b8760405161358f9493929190614478565b60405180910390a45b5050979650505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e6f57600080fd5b80356136498161361c565b919050565b803563ffffffff8116811461364957600080fd5b60008083601f84011261367457600080fd5b50813567ffffffffffffffff81111561368c57600080fd5b6020830191508360208260051b85010111156136a757600080fd5b9250929050565b600080600080606085870312156136c457600080fd5b84356136cf8161361c565b93506136dd6020860161364e565b9250604085013567ffffffffffffffff8111156136f957600080fd5b61370587828801613662565b95989497509550505050565b602080825282518282018190526000919060409081850190868401855b828110156137535781518051855286015186850152928401929085019060010161372e565b5091979650505050505050565b60008060008060008086880361012081121561377b57600080fd5b87356137868161361c565b96506137946020890161364e565b9550604088013567ffffffffffffffff808211156137b157600080fd5b9089019060c0828c0312156137c557600080fd5b81965060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0840112156137f857600080fd5b60608a0195506101008a013592508083111561381357600080fd5b505061382189828a01613662565b979a9699509497509295939492505050565b60006020828403121561384557600080fd5b81356124a58161361c565b60008083601f84011261386257600080fd5b50813567ffffffffffffffff81111561387a57600080fd5b6020830191508360208260061b85010111156136a757600080fd5b600080602083850312156138a857600080fd5b823567ffffffffffffffff8111156138bf57600080fd5b6138cb85828601613850565b90969095509350505050565b600080604083850312156138ea57600080fd5b82356138f58161361c565b91506139036020840161364e565b90509250929050565b60005b8381101561392757818101518382015260200161390f565b50506000910152565b6000815180845261394881602086016020860161390c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006124a56020830184613930565b8581528460208201528315156040820152821515606082015260a0608082015260006139bc60a0830184613930565b979650505050505050565b600080600080600080600060a0888a0312156139e257600080fd5b87356139ed8161361c565b96506139fb6020890161364e565b9550604088013567ffffffffffffffff80821115613a1857600080fd5b9089019060e0828c031215613a2c57600080fd5b90955060608901359080821115613a4257600080fd5b613a4e8b838c01613662565b909650945060808a0135915080821115613a6757600080fd5b50613a748a828b01613850565b989b979a50959850939692959293505050565b8015158114612e6f57600080fd5b600080600060408486031215613aaa57600080fd5b833567ffffffffffffffff811115613ac157600080fd5b613acd86828701613662565b9094509250506020840135613ae181613a87565b809150509250925092565b600080600060408486031215613b0157600080fd5b8335613b0c8161361c565b9250602084013567ffffffffffffffff811115613b2857600080fd5b613b3486828701613662565b9497909650939450505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613bd2578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180518452878101511515888501528601516060878501819052613bbe81860183613930565b968901969450505090860190600101613b68565b509098975050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c1557600080fd5b830160208101925035905067ffffffffffffffff811115613c3557600080fd5b8036038213156136a757600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b81835260006020808501808196508560051b81019150846000805b88811015613d56578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81893603018112613ce6578283fd5b880160808135613cf58161361c565b73ffffffffffffffffffffffffffffffffffffffff168752613d1982890183613be0565b828a8a0152613d2b838a018284613c44565b604085810135908b015260609485013594909901939093525050509885019891850191600101613ca8565b509298975050505050505050565b600081357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1833603018112613d9857600080fd5b820160208101903567ffffffffffffffff811115613db557600080fd5b8060051b3603821315613dc757600080fd5b60c08552613dd960c086018284613c8d565b915050602083013560208501526040830135604085015260608301356060850152613e066080840161363e565b73ffffffffffffffffffffffffffffffffffffffff166080850152613e2e60a0840184613be0565b85830360a0870152610611838284613c44565b600081357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41833603018112613e7557600080fd5b60e08452613e8860e08501848301613d64565b9050613ec5602085016020850180358252602081013560208301526040810135604083015260608101356060830152608081013560808301525050565b60c083013560c08501528091505092915050565b60208082528181018390526000906040600585901b840181019084018684805b88811015613d56577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218b3603018112613f59578283fd5b613f65868c8301613e41565b9550509285019291850191600101613ef9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613fca57613fca613f78565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561401757614017613f78565b604052919050565b6000602080838503121561403257600080fd5b825167ffffffffffffffff8082111561404a57600080fd5b818501915085601f83011261405e57600080fd5b81518181111561407057614070613f78565b61407e848260051b01613fd0565b818152848101925060069190911b83018401908782111561409e57600080fd5b928401925b818410156139bc57604084890312156140bc5760008081fd5b6140c4613fa7565b8451815285850151868201528352604090930192918401916140a3565b81835260006020808501808196508560051b81019150846000805b88811015613d56578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc189360301811261413a578283fd5b880160406141488280613be0565b828952614158838a018284613c44565b9250505087820135915061416b8261361c565b73ffffffffffffffffffffffffffffffffffffffff919091169587019590955298850198918501916001016140fc565b60e0815260006141ae60e0830187613d64565b6141e6602084018780358252602081013560208301526040810135604083015260608101356060830152608081013560808301525050565b82810360c08401526139bc8185876140e1565b60006020828403121561420b57600080fd5b81516124a581613a87565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561425757600080fd5b81356124a581613a87565b600082601f83011261427357600080fd5b815167ffffffffffffffff81111561428d5761428d613f78565b6142be60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613fd0565b8181528460208386010111156142d357600080fd5b6142e482602083016020870161390c565b949350505050565b6000602082840312156142fe57600080fd5b815167ffffffffffffffff81111561431557600080fd5b610cae84828501614262565b60006020828403121561433357600080fd5b81516124a58161361c565b60006020828403121561435057600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261438c57600080fd5b83018035915067ffffffffffffffff8211156143a757600080fd5b6020019150368190038213156136a757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610cb257610cb26143bc565b6000806040838503121561441157600080fd5b825161441c81613a87565b602084015190925067ffffffffffffffff81111561443957600080fd5b61444585828601614262565b9150509250929050565b63ffffffff8416815260406020820152600061446f604083018486613c44565b95945050505050565b63ffffffff85168152606060208201526000614498606083018587613c44565b82810360408401526139bc8185613930565b8082028115828204841417610cb257610cb26143bc565b6000826144f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60608152600061450f6060830188613e41565b60208382038185015261452382888a6140e1565b84810360408681019190915286825287935090820160005b8781101561455f57843582528385013584830152938201939082019060010161453b565b509a9950505050505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126145a257600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126145e157600080fd5b83018035915067ffffffffffffffff8211156145fc57600080fd5b6020019150600681901b36038213156136a757600080fd5b60006020828403121561462657600080fd5b6124a58261364e565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218336030181126145a257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261469857600080fd5b83018035915067ffffffffffffffff8211156146b357600080fd5b6020019150600581901b36038213156136a757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126145a257600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614730576147306143bc565b506001019056fea2646970667358221220380cb1d59ec81db9112a02f4e44aa1758556f27507ba641a65199a45450eed3364736f6c63430008120033

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

000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e687

-----Decoded View---------------
Arg [0] : avoFactory_ (address): 0xe981E50c7c47F0Df8826B5ce3F533f5E4440e687

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000e981e50c7c47f0df8826b5ce3f533f5e4440e687


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.