false
false
100

Contract Address Details

0xa3862d079fFf54a70a56F69B07af99324294FC5d

Contract Name
AxelarAuthWeighted
Creator
0xf52bd2–f671ab at 0x0a0788–79cb51
Balance
0 KAVA ( )
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
11601701
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
AxelarAuthWeighted




Optimization enabled
true
Compiler version
v0.8.9+commit.e5eed63a




Optimization runs
1000
EVM Version
default




Verified at
2022-12-13T22:22:59.868156Z

Constructor Arguments

0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000168b80000000000000000000000000000000000000000000000000000000000000037000000000000000000000000009a36efd0c5c7158adb642c09c996ed836eb74b000000000000000000000000014f06f66ef97f92f79614d89ef056d8a1f9afc00000000000000000000000000340e8192bcd8f1412f3eee39ae388e2999da96700000000000000000000000004b0246c8c725e9cd1197a73a2579d09a1cfee2200000000000000000000000007e88abe090a54c7245a210558ed6cfa671b50080000000000000000000000000ea0c68945b4c98969107097f38c19c14f0424ed0000000000000000000000001b163920f9fe2185c42b42a45a737152183dd47a0000000000000000000000001bef4de62d6fd9a2c1e2b8ae1f1d1a46b157b2db0000000000000000000000001c7ebfe6fd14b17c925ff6b964894d02c022753000000000000000000000000026f08c949e7d36eae5a64f2277b40449952b935b0000000000000000000000002741f384fb4dd4b241506c1eaac134ddb73e8f1c00000000000000000000000029242c931b6f1b8655ab5f16ab05f0f794b9b84d0000000000000000000000003248ea01d75b5131cbc1c0a86396689ece95cc100000000000000000000000003723d16b06f9828a3a3b50b03e8726db211022e300000000000000000000000038abf389b6bbe61ed410309e9d05c8d7251bfd0c0000000000000000000000003be58595e85f680b1c99d0609ec1a112343cb57a0000000000000000000000003fc3f7d3da5c86f98d0853c6251b6572e99f0c6600000000000000000000000041f5ffa60bb330e1e222d60b940c2bac822480a3000000000000000000000000442abd4a1b02c6a0c31a0d51f448f1a72d41795e0000000000000000000000004aeea78e511fc13695281241a493929eca60912600000000000000000000000054de4d66aa07a0c9484bae76389e3ec3402e917100000000000000000000000056b2a061617d8dc5e4482c1ba4a0c850744594af0000000000000000000000005aa6a3887c56ef26ff5736b0f2354e484afddcbc0000000000000000000000006e3b643effba68342260dcbe05409fd9802a4e5400000000000000000000000076c45aa43af363be0451b99c1887898214ab930d00000000000000000000000077038d69fedec4edff9839cc923c0c62f4fcc7520000000000000000000000007dcad4f9bb9e9585c9ca1978c52126606faf354b000000000000000000000000809b632be9a9b025187bf2b4893d2fa87558174a00000000000000000000000087f5dd531c7f9838291cc10464983c29fe1bb71a00000000000000000000000094b700667f97d0577314b5e8f886adafed40870700000000000000000000000096e32bd5d103f7f89f1e42a2f35c4cebfc5287ec0000000000000000000000009b3a3b6d76aeb5c458e1d45e0034f691fb6a3bed000000000000000000000000a730545d1302c55941355c62042d9c48fa9322d4000000000000000000000000a998f1f451683de0ebb90930b89d880c0e6034e6000000000000000000000000ad64359ab18f9dd858e0db4ebdfcf183c99cb135000000000000000000000000ad78ebcffaf59f9dae1ea2072be67400dee51f0b000000000000000000000000b0da8019bdc6aa9cc550d88745b33cc01c43c3bb000000000000000000000000b1f3bc0db216b8d845cd6d4e855fa165d8f8b113000000000000000000000000b65bb46b268d2b68d26234828c918f650472aff4000000000000000000000000bb7ceceb37a2538dfc32b2e363b6df58bb92cc35000000000000000000000000bdf7328260b64523563aefa14144e1424a228fc5000000000000000000000000beebe846a355c4a8d93874c3b58b98c98eef4645000000000000000000000000c16f53f6258ec53804ec94b13d3afb4b614dd674000000000000000000000000c7507c3a590d3b21e0e48505bafc879f68405d84000000000000000000000000c7577ff9c5fba617aec18c737716060e77b5b9d7000000000000000000000000c7bf852d830c3785cc463e5cd0e5f8419a99e408000000000000000000000000cae9234cbf680804f95c9870ac36db4abfe6b05f000000000000000000000000d0abd986c28dec5d9da31a1385fbdc3324da7bf8000000000000000000000000d3a7f36c4924bf7fed2c2d4a403cfe4636dd13bf000000000000000000000000d4cbcf45a0dcecfb70ffea2084b084a724f7856b000000000000000000000000e12605407c6ecac0972afbadeba2a152d86cf301000000000000000000000000ebaab2b70812fcac3c96ef3a62c7998614379285000000000000000000000000ecd21dc2fd55d4fcff73ee6801865c0a87fc9612000000000000000000000000fa79dde61e83b4070daaf24d365ad2e8f2df18fb000000000000000000000000ff07ce905264d12c6bf9564a40560d3d33fe656100000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000fc30000000000000000000000000000000000000000000000000000000000000ce600000000000000000000000000000000000000000000000000000000000004cc00000000000000000000000000000000000000000000000000000000000007ad0000000000000000000000000000000000000000000000000000000000000e960000000000000000000000000000000000000000000000000000000000000fe900000000000000000000000000000000000000000000000000000000000008490000000000000000000000000000000000000000000000000000000000000c0c0000000000000000000000000000000000000000000000000000000000000f9b00000000000000000000000000000000000000000000000000000000000004c8000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000011bc0000000000000000000000000000000000000000000000000000000000000c7d00000000000000000000000000000000000000000000000000000000000010140000000000000000000000000000000000000000000000000000000000000d9b0000000000000000000000000000000000000000000000000000000000000c790000000000000000000000000000000000000000000000000000000000000ab800000000000000000000000000000000000000000000000000000000000017750000000000000000000000000000000000000000000000000000000000000d5100000000000000000000000000000000000000000000000000000000000010b4000000000000000000000000000000000000000000000000000000000000077e0000000000000000000000000000000000000000000000000000000000000b0c0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000142900000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000a3f00000000000000000000000000000000000000000000000000000000000008e10000000000000000000000000000000000000000000000000000000000000c46000000000000000000000000000000000000000000000000000000000000073d00000000000000000000000000000000000000000000000000000000000010dd0000000000000000000000000000000000000000000000000000000000000bf3000000000000000000000000000000000000000000000000000000000000022d00000000000000000000000000000000000000000000000000000000000003ee0000000000000000000000000000000000000000000000000000000000000ca1000000000000000000000000000000000000000000000000000000000000096100000000000000000000000000000000000000000000000000000000000008920000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000b1900000000000000000000000000000000000000000000000000000000000019ff00000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000cb30000000000000000000000000000000000000000000000000000000000000dac000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000007b500000000000000000000000000000000000000000000000000000000000002230000000000000000000000000000000000000000000000000000000000000d6c0000000000000000000000000000000000000000000000000000000000000aaa0000000000000000000000000000000000000000000000000000000000000df9000000000000000000000000000000000000000000000000000000000000095c000000000000000000000000000000000000000000000000000000000000067a000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000cc80000000000000000000000000000000000000000000000000000000000000d28000000000000000000000000000000000000000000000000000000000000043b0000000000000000000000000000000000000000000000000000000000000c0f

Arg [0] (bytes[]) : [0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000168b80000000000000000000000000000000000000000000000000000000000000037000000000000000000000000009a36efd0c5c7158adb642c09c996ed836eb74b000000000000000000000000014f06f66ef97f92f79614d89ef056d8a1f9afc00000000000000000000000000340e8192bcd8f1412f3eee39ae388e2999da96700000000000000000000000004b0246c8c725e9cd1197a73a2579d09a1cfee2200000000000000000000000007e88abe090a54c7245a210558ed6cfa671b50080000000000000000000000000ea0c68945b4c98969107097f38c19c14f0424ed0000000000000000000000001b163920f9fe2185c42b42a45a737152183dd47a0000000000000000000000001bef4de62d6fd9a2c1e2b8ae1f1d1a46b157b2db0000000000000000000000001c7ebfe6fd14b17c925ff6b964894d02c022753000000000000000000000000026f08c949e7d36eae5a64f2277b40449952b935b0000000000000000000000002741f384fb4dd4b241506c1eaac134ddb73e8f1c00000000000000000000000029242c931b6f1b8655ab5f16ab05f0f794b9b84d0000000000000000000000003248ea01d75b5131cbc1c0a86396689ece95cc100000000000000000000000003723d16b06f9828a3a3b50b03e8726db211022e300000000000000000000000038abf389b6bbe61ed410309e9d05c8d7251bfd0c0000000000000000000000003be58595e85f680b1c99d0609ec1a112343cb57a0000000000000000000000003fc3f7d3da5c86f98d0853c6251b6572e99f0c6600000000000000000000000041f5ffa60bb330e1e222d60b940c2bac822480a3000000000000000000000000442abd4a1b02c6a0c31a0d51f448f1a72d41795e0000000000000000000000004aeea78e511fc13695281241a493929eca60912600000000000000000000000054de4d66aa07a0c9484bae76389e3ec3402e917100000000000000000000000056b2a061617d8dc5e4482c1ba4a0c850744594af0000000000000000000000005aa6a3887c56ef26ff5736b0f2354e484afddcbc0000000000000000000000006e3b643effba68342260dcbe05409fd9802a4e5400000000000000000000000076c45aa43af363be0451b99c1887898214ab930d00000000000000000000000077038d69fedec4edff9839cc923c0c62f4fcc7520000000000000000000000007dcad4f9bb9e9585c9ca1978c52126606faf354b000000000000000000000000809b632be9a9b025187bf2b4893d2fa87558174a00000000000000000000000087f5dd531c7f9838291cc10464983c29fe1bb71a00000000000000000000000094b700667f97d0577314b5e8f886adafed40870700000000000000000000000096e32bd5d103f7f89f1e42a2f35c4cebfc5287ec0000000000000000000000009b3a3b6d76aeb5c458e1d45e0034f691fb6a3bed000000000000000000000000a730545d1302c55941355c62042d9c48fa9322d4000000000000000000000000a998f1f451683de0ebb90930b89d880c0e6034e6000000000000000000000000ad64359ab18f9dd858e0db4ebdfcf183c99cb135000000000000000000000000ad78ebcffaf59f9dae1ea2072be67400dee51f0b000000000000000000000000b0da8019bdc6aa9cc550d88745b33cc01c43c3bb000000000000000000000000b1f3bc0db216b8d845cd6d4e855fa165d8f8b113000000000000000000000000b65bb46b268d2b68d26234828c918f650472aff4000000000000000000000000bb7ceceb37a2538dfc32b2e363b6df58bb92cc35000000000000000000000000bdf7328260b64523563aefa14144e1424a228fc5000000000000000000000000beebe846a355c4a8d93874c3b58b98c98eef4645000000000000000000000000c16f53f6258ec53804ec94b13d3afb4b614dd674000000000000000000000000c7507c3a590d3b21e0e48505bafc879f68405d84000000000000000000000000c7577ff9c5fba617aec18c737716060e77b5b9d7000000000000000000000000c7bf852d830c3785cc463e5cd0e5f8419a99e408000000000000000000000000cae9234cbf680804f95c9870ac36db4abfe6b05f000000000000000000000000d0abd986c28dec5d9da31a1385fbdc3324da7bf8000000000000000000000000d3a7f36c4924bf7fed2c2d4a403cfe4636dd13bf000000000000000000000000d4cbcf45a0dcecfb70ffea2084b084a724f7856b000000000000000000000000e12605407c6ecac0972afbadeba2a152d86cf301000000000000000000000000ebaab2b70812fcac3c96ef3a62c7998614379285000000000000000000000000ecd21dc2fd55d4fcff73ee6801865c0a87fc9612000000000000000000000000fa79dde61e83b4070daaf24d365ad2e8f2df18fb000000000000000000000000ff07ce905264d12c6bf9564a40560d3d33fe656100000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000fc30000000000000000000000000000000000000000000000000000000000000ce600000000000000000000000000000000000000000000000000000000000004cc00000000000000000000000000000000000000000000000000000000000007ad0000000000000000000000000000000000000000000000000000000000000e960000000000000000000000000000000000000000000000000000000000000fe900000000000000000000000000000000000000000000000000000000000008490000000000000000000000000000000000000000000000000000000000000c0c0000000000000000000000000000000000000000000000000000000000000f9b00000000000000000000000000000000000000000000000000000000000004c8000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000011bc0000000000000000000000000000000000000000000000000000000000000c7d00000000000000000000000000000000000000000000000000000000000010140000000000000000000000000000000000000000000000000000000000000d9b0000000000000000000000000000000000000000000000000000000000000c790000000000000000000000000000000000000000000000000000000000000ab800000000000000000000000000000000000000000000000000000000000017750000000000000000000000000000000000000000000000000000000000000d5100000000000000000000000000000000000000000000000000000000000010b4000000000000000000000000000000000000000000000000000000000000077e0000000000000000000000000000000000000000000000000000000000000b0c0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000142900000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000a3f00000000000000000000000000000000000000000000000000000000000008e10000000000000000000000000000000000000000000000000000000000000c46000000000000000000000000000000000000000000000000000000000000073d00000000000000000000000000000000000000000000000000000000000010dd0000000000000000000000000000000000000000000000000000000000000bf3000000000000000000000000000000000000000000000000000000000000022d00000000000000000000000000000000000000000000000000000000000003ee0000000000000000000000000000000000000000000000000000000000000ca1000000000000000000000000000000000000000000000000000000000000096100000000000000000000000000000000000000000000000000000000000008920000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000b1900000000000000000000000000000000000000000000000000000000000019ff00000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000cb30000000000000000000000000000000000000000000000000000000000000dac000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000007b500000000000000000000000000000000000000000000000000000000000002230000000000000000000000000000000000000000000000000000000000000d6c0000000000000000000000000000000000000000000000000000000000000aaa0000000000000000000000000000000000000000000000000000000000000df9000000000000000000000000000000000000000000000000000000000000095c000000000000000000000000000000000000000000000000000000000000067a000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000cc80000000000000000000000000000000000000000000000000000000000000d28000000000000000000000000000000000000000000000000000000000000043b0000000000000000000000000000000000000000000000000000000000000c0f]

              

Contract source code

// Source: contracts/auth/AxelarAuthWeighted.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.8.9;

// File contracts/interfaces/IOwnable.sol

interface IOwnable {
    error NotOwner();
    error InvalidOwner();

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

    function owner() external view returns (address);

    function transferOwnership(address newOwner) external;
}

// File contracts/interfaces/IAxelarAuth.sol

interface IAxelarAuth is IOwnable {
    function validateProof(bytes32 messageHash, bytes calldata proof) external returns (bool currentOperators);

    function transferOperatorship(bytes calldata params) external;
}

// File contracts/interfaces/IAxelarAuthWeighted.sol

interface IAxelarAuthWeighted is IAxelarAuth {
    error InvalidOperators();
    error InvalidThreshold();
    error DuplicateOperators();
    error MalformedSigners();
    error LowSignaturesWeight();
    error InvalidWeights();

    event OperatorshipTransferred(address[] newOperators, uint256[] newWeights, uint256 newThreshold);

    function currentEpoch() external view returns (uint256);

    function hashForEpoch(uint256 epoch) external view returns (bytes32);

    function epochForHash(bytes32 hash) external view returns (uint256);
}

// File contracts/ECDSA.sol

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    error InvalidSignatureLength();
    error InvalidS();
    error InvalidV();
    error InvalidSignature();

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address signer) {
        // Check the signature length
        if (signature.length != 65) revert InvalidSignatureLength();

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) revert InvalidS();

        if (v != 27 && v != 28) revert InvalidV();

        // If the signature is valid (and not malleable), return the signer address
        if ((signer = ecrecover(hash, v, r, s)) == address(0)) revert InvalidSignature();
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', hash));
    }
}

// File contracts/Ownable.sol

abstract contract Ownable is IOwnable {
    address public owner;

    constructor() {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    modifier onlyOwner() {
        if (owner != msg.sender) revert NotOwner();

        _;
    }

    function transferOwnership(address newOwner) external virtual onlyOwner {
        if (newOwner == address(0)) revert InvalidOwner();

        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// File contracts/auth/AxelarAuthWeighted.sol

contract AxelarAuthWeighted is Ownable, IAxelarAuthWeighted {
    uint256 public currentEpoch;
    mapping(uint256 => bytes32) public hashForEpoch;
    mapping(bytes32 => uint256) public epochForHash;

    uint8 internal constant OLD_KEY_RETENTION = 16;

    constructor(bytes[] memory recentOperators) {
        for (uint256 i; i < recentOperators.length; ++i) {
            _transferOperatorship(recentOperators[i]);
        }
    }

    /**************************\
    |* External Functionality *|
    \**************************/

    /// @dev This function takes messageHash and proof data and reverts if proof is invalid
    /// @return True if provided operators are the current ones
    function validateProof(bytes32 messageHash, bytes calldata proof) external view returns (bool) {
        (address[] memory operators, uint256[] memory weights, uint256 threshold, bytes[] memory signatures) = abi.decode(
            proof,
            (address[], uint256[], uint256, bytes[])
        );

        bytes32 operatorsHash = keccak256(abi.encode(operators, weights, threshold));
        uint256 operatorsEpoch = epochForHash[operatorsHash];
        uint256 epoch = currentEpoch;

        if (operatorsEpoch == 0 || epoch - operatorsEpoch >= OLD_KEY_RETENTION) revert InvalidOperators();

        _validateSignatures(messageHash, operators, weights, threshold, signatures);

        return operatorsEpoch == epoch;
    }

    /***********************\
    |* Owner Functionality *|
    \***********************/

    function transferOperatorship(bytes calldata params) external onlyOwner {
        _transferOperatorship(params);
    }

    /**************************\
    |* Internal Functionality *|
    \**************************/

    function _transferOperatorship(bytes memory params) internal {
        (address[] memory newOperators, uint256[] memory newWeights, uint256 newThreshold) = abi.decode(
            params,
            (address[], uint256[], uint256)
        );
        uint256 operatorsLength = newOperators.length;
        uint256 weightsLength = newWeights.length;

        // operators must be sorted binary or alphabetically in lower case
        if (operatorsLength == 0 || !_isSortedAscAndContainsNoDuplicate(newOperators)) revert InvalidOperators();

        if (weightsLength != operatorsLength) revert InvalidWeights();

        uint256 totalWeight = 0;
        for (uint256 i = 0; i < weightsLength; ++i) {
            totalWeight += newWeights[i];
        }
        if (newThreshold == 0 || totalWeight < newThreshold) revert InvalidThreshold();

        bytes32 newOperatorsHash = keccak256(params);

        if (epochForHash[newOperatorsHash] > 0) revert DuplicateOperators();

        uint256 epoch = currentEpoch + 1;
        currentEpoch = epoch;
        hashForEpoch[epoch] = newOperatorsHash;
        epochForHash[newOperatorsHash] = epoch;

        emit OperatorshipTransferred(newOperators, newWeights, newThreshold);
    }

    function _validateSignatures(
        bytes32 messageHash,
        address[] memory operators,
        uint256[] memory weights,
        uint256 threshold,
        bytes[] memory signatures
    ) internal pure {
        uint256 operatorsLength = operators.length;
        uint256 operatorIndex = 0;
        uint256 weight = 0;
        // looking for signers within operators
        // assuming that both operators and signatures are sorted
        for (uint256 i = 0; i < signatures.length; ++i) {
            address signer = ECDSA.recover(messageHash, signatures[i]);
            // looping through remaining operators to find a match
            for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {}
            // checking if we are out of operators
            if (operatorIndex == operatorsLength) revert MalformedSigners();
            // return if weight sum above threshold
            weight += weights[operatorIndex];
            // weight needs to reach or surpass threshold
            if (weight >= threshold) return;
            // increasing operators index if match was found
            ++operatorIndex;
        }
        // if weight sum below threshold
        revert LowSignaturesWeight();
    }

    function _isSortedAscAndContainsNoDuplicate(address[] memory accounts) internal pure returns (bool) {
        for (uint256 i; i < accounts.length - 1; ++i) {
            if (accounts[i] >= accounts[i + 1]) {
                return false;
            }
        }

        return accounts[0] != address(0);
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"bytes[]","name":"recentOperators","internalType":"bytes[]"}]},{"type":"error","name":"DuplicateOperators","inputs":[]},{"type":"error","name":"InvalidOperators","inputs":[]},{"type":"error","name":"InvalidOwner","inputs":[]},{"type":"error","name":"InvalidS","inputs":[]},{"type":"error","name":"InvalidSignature","inputs":[]},{"type":"error","name":"InvalidSignatureLength","inputs":[]},{"type":"error","name":"InvalidThreshold","inputs":[]},{"type":"error","name":"InvalidV","inputs":[]},{"type":"error","name":"InvalidWeights","inputs":[]},{"type":"error","name":"LowSignaturesWeight","inputs":[]},{"type":"error","name":"MalformedSigners","inputs":[]},{"type":"error","name":"NotOwner","inputs":[]},{"type":"event","name":"OperatorshipTransferred","inputs":[{"type":"address[]","name":"newOperators","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"newWeights","internalType":"uint256[]","indexed":false},{"type":"uint256","name":"newThreshold","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentEpoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"epochForHash","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashForEpoch","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOperatorship","inputs":[{"type":"bytes","name":"params","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"validateProof","inputs":[{"type":"bytes32","name":"messageHash","internalType":"bytes32"},{"type":"bytes","name":"proof","internalType":"bytes"}]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162001693380380620016938339810160408190526200003491620003bf565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360005b8151811015620000c057620000ad828281518110620000995762000099620004fd565b6020026020010151620000c860201b60201c565b620000b88162000529565b905062000076565b505062000761565b600080600083806020019051810190620000e39190620005b4565b8251825193965091945092509081158062000106575062000104856200027e565b155b156200012557604051630849699d60e11b815260040160405180910390fd5b818114620001465760405163108cef9d60e31b815260040160405180910390fd5b6000805b828110156200019257858181518110620001685762000168620004fd565b6020026020010151826200017d91906200069b565b91506200018a8162000529565b90506200014a565b50831580620001a057508381105b15620001bf5760405163aabd5a0960e01b815260040160405180910390fd5b86516020808901919091206000818152600390925260409091205415620001f95760405163adda47f760e01b815260040160405180910390fd5b600060015460016200020c91906200069b565b60018190556000818152600260209081526040808320869055858352600390915290819020829055519091507f05b53362d4afea7533e835bd99f6c0f2c251e2f08b5c461734829516519dd5ac906200026b908a908a908a90620006b6565b60405180910390a1505050505050505050565b6000805b6001835162000292919062000747565b811015620003145782620002a88260016200069b565b81518110620002bb57620002bb620004fd565b60200260200101516001600160a01b0316838281518110620002e157620002e1620004fd565b60200260200101516001600160a01b031610620003015750600092915050565b6200030c8162000529565b905062000282565b5060006001600160a01b031682600081518110620003365762000336620004fd565b60200260200101516001600160a01b031614159050919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171562000391576200039162000350565b604052919050565b60006001600160401b03821115620003b557620003b562000350565b5060051b60200190565b60006020808385031215620003d357600080fd5b82516001600160401b0380821115620003eb57600080fd5b8185019150601f86818401126200040157600080fd5b825162000418620004128262000399565b62000366565b81815260059190911b840185019085810190898311156200043857600080fd5b8686015b83811015620004ef57805186811115620004565760008081fd5b8701603f81018c13620004695760008081fd5b888101518781111562000480576200048062000350565b62000493818801601f19168b0162000366565b81815260408e81848601011115620004ab5760008081fd5b60005b83811015620004cb578481018201518382018e01528c01620004ae565b83811115620004dd5760008d85850101525b5050855250509187019187016200043c565b509998505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141562000540576200054062000513565b5060010190565b600082601f8301126200055957600080fd5b815160206200056c620004128362000399565b82815260059290921b840181019181810190868411156200058c57600080fd5b8286015b84811015620005a9578051835291830191830162000590565b509695505050505050565b600080600060608486031215620005ca57600080fd5b83516001600160401b0380821115620005e257600080fd5b818601915086601f830112620005f757600080fd5b815160206200060a620004128362000399565b82815260059290921b8401810191818101908a8411156200062a57600080fd5b948201945b83861015620006615785516001600160a01b0381168114620006515760008081fd5b825294820194908201906200062f565b918901519197509093505050808211156200067b57600080fd5b506200068a8682870162000547565b925050604084015190509250925092565b60008219821115620006b157620006b162000513565b500190565b606080825284519082018190526000906020906080840190828801845b82811015620006fa5781516001600160a01b031684529284019290840190600101620006d3565b5050508381038285015285518082528683019183019060005b81811015620007315783518352928401929184019160010162000713565b5050809350505050826040830152949350505050565b6000828210156200075c576200075c62000513565b500390565b610f2280620007716000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063ba6742e51161005b578063ba6742e5146100ec578063d289d1cb1461010c578063f1501c8914610121578063f2fde38b1461014157600080fd5b806373e3d66a1461008257806376671808146100aa5780638da5cb5b146100c1575b600080fd5b610095610090366004610933565b610154565b60405190151581526020015b60405180910390f35b6100b360015481565b6040519081526020016100a1565b6000546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100a1565b6100b36100fa36600461097f565b60026020526000908152604090205481565b61011f61011a366004610998565b610201565b005b6100b361012f36600461097f565b60036020526000908152604090205481565b61011f61014f3660046109f2565b61026f565b60008080808061016686880188610bd0565b9350935093509350600084848460405160200161018593929190610cc0565b60408051601f19818403018152918152815160209283012060008181526003909352912054600154919250908115806101c8575060106101c58383610d63565b10155b156101e657604051630849699d60e11b815260040160405180910390fd5b6101f38b8888888861034d565b149998505050505050505050565b6000546001600160a01b0316331461022c576040516330cd747160e01b815260040160405180910390fd5b61026b82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061049d92505050565b5050565b6000546001600160a01b0316331461029a576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b0381166102da576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b8351600080805b84518110156104635760006103828a87848151811061037557610375610d7a565b6020026020010151610687565b90505b84841080156103bf57508884815181106103a1576103a1610d7a565b60200260200101516001600160a01b0316816001600160a01b031614155b156103d4576103cd84610d90565b9350610385565b8484141561040e576040517fc6fb539300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87848151811061042057610420610d7a565b6020026020010151836104339190610dab565b9250868310610446575050505050610496565b61044f84610d90565b9350508061045c90610d90565b9050610354565b506040517f203b225800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000806000838060200190518101906104b69190610e1e565b825182519396509194509250908115806104d657506104d48561082a565b155b156104f457604051630849699d60e11b815260040160405180910390fd5b81811461052d576040517f84677ce800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b828110156105705785818151811061054b5761054b610d7a565b60200260200101518261055e9190610dab565b915061056981610d90565b9050610531565b5083158061057d57508381105b156105b4576040517faabd5a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86516020808901919091206000818152600390925260409091205415610606576040517fadda47f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060015460016106179190610dab565b60018190556000818152600260209081526040808320869055858352600390915290819020829055519091507f05b53362d4afea7533e835bd99f6c0f2c251e2f08b5c461734829516519dd5ac90610674908a908a908a90610cc0565b60405180910390a1505050505050505050565b600081516041146106c4576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115610730576040517f40c1e74800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060ff16601b1415801561074857508060ff16601c14155b1561077f576040517f119bce3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845289905260ff841692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156107d3573d6000803e3d6000fd5b505050602060405103519450846001600160a01b03161415610821576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505092915050565b6000805b6001835161083c9190610d63565b8110156108b1578261084f826001610dab565b8151811061085f5761085f610d7a565b60200260200101516001600160a01b031683828151811061088257610882610d7a565b60200260200101516001600160a01b0316106108a15750600092915050565b6108aa81610d90565b905061082e565b5060006001600160a01b0316826000815181106108d0576108d0610d7a565b60200260200101516001600160a01b031614159050919050565b60008083601f8401126108fc57600080fd5b50813567ffffffffffffffff81111561091457600080fd5b60208301915083602082850101111561092c57600080fd5b9250929050565b60008060006040848603121561094857600080fd5b83359250602084013567ffffffffffffffff81111561096657600080fd5b610972868287016108ea565b9497909650939450505050565b60006020828403121561099157600080fd5b5035919050565b600080602083850312156109ab57600080fd5b823567ffffffffffffffff8111156109c257600080fd5b6109ce858286016108ea565b90969095509350505050565b6001600160a01b03811681146109ef57600080fd5b50565b600060208284031215610a0457600080fd5b8135610a0f816109da565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610a5557610a55610a16565b604052919050565b600067ffffffffffffffff821115610a7757610a77610a16565b5060051b60200190565b600082601f830112610a9257600080fd5b81356020610aa7610aa283610a5d565b610a2c565b82815260059290921b84018101918181019086841115610ac657600080fd5b8286015b84811015610ae15780358352918301918301610aca565b509695505050505050565b6000601f8381840112610afe57600080fd5b82356020610b0e610aa283610a5d565b82815260059290921b85018101918181019087841115610b2d57600080fd5b8287015b84811015610bc457803567ffffffffffffffff80821115610b525760008081fd5b818a0191508a603f830112610b675760008081fd5b85820135604082821115610b7d57610b7d610a16565b610b8e828b01601f19168901610a2c565b92508183528c81838601011115610ba55760008081fd5b8181850189850137506000908201870152845250918301918301610b31565b50979650505050505050565b60008060008060808587031215610be657600080fd5b843567ffffffffffffffff80821115610bfe57600080fd5b818701915087601f830112610c1257600080fd5b81356020610c22610aa283610a5d565b82815260059290921b8401810191818101908b841115610c4157600080fd5b948201945b83861015610c68578535610c59816109da565b82529482019490820190610c46565b98505088013592505080821115610c7e57600080fd5b610c8a88838901610a81565b9450604087013593506060870135915080821115610ca757600080fd5b50610cb487828801610aec565b91505092959194509250565b606080825284519082018190526000906020906080840190828801845b82811015610d025781516001600160a01b031684529284019290840190600101610cdd565b5050508381038285015285518082528683019183019060005b81811015610d3757835183529284019291840191600101610d1b565b5050809350505050826040830152949350505050565b634e487b7160e01b600052601160045260246000fd5b600082821015610d7557610d75610d4d565b500390565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610da457610da4610d4d565b5060010190565b60008219821115610dbe57610dbe610d4d565b500190565b600082601f830112610dd457600080fd5b81516020610de4610aa283610a5d565b82815260059290921b84018101918181019086841115610e0357600080fd5b8286015b84811015610ae15780518352918301918301610e07565b600080600060608486031215610e3357600080fd5b835167ffffffffffffffff80821115610e4b57600080fd5b818601915086601f830112610e5f57600080fd5b81516020610e6f610aa283610a5d565b82815260059290921b8401810191818101908a841115610e8e57600080fd5b948201945b83861015610eb5578551610ea6816109da565b82529482019490820190610e93565b91890151919750909350505080821115610ece57600080fd5b50610edb86828701610dc3565b92505060408401519050925092509256fea26469706673582212200ddc1b1cc323f5787654ff6b953672c656a5ae6baaac3108e31ea3b7daad1dfd64736f6c634300080900330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000168b80000000000000000000000000000000000000000000000000000000000000037000000000000000000000000009a36efd0c5c7158adb642c09c996ed836eb74b000000000000000000000000014f06f66ef97f92f79614d89ef056d8a1f9afc00000000000000000000000000340e8192bcd8f1412f3eee39ae388e2999da96700000000000000000000000004b0246c8c725e9cd1197a73a2579d09a1cfee2200000000000000000000000007e88abe090a54c7245a210558ed6cfa671b50080000000000000000000000000ea0c68945b4c98969107097f38c19c14f0424ed0000000000000000000000001b163920f9fe2185c42b42a45a737152183dd47a0000000000000000000000001bef4de62d6fd9a2c1e2b8ae1f1d1a46b157b2db0000000000000000000000001c7ebfe6fd14b17c925ff6b964894d02c022753000000000000000000000000026f08c949e7d36eae5a64f2277b40449952b935b0000000000000000000000002741f384fb4dd4b241506c1eaac134ddb73e8f1c00000000000000000000000029242c931b6f1b8655ab5f16ab05f0f794b9b84d0000000000000000000000003248ea01d75b5131cbc1c0a86396689ece95cc100000000000000000000000003723d16b06f9828a3a3b50b03e8726db211022e300000000000000000000000038abf389b6bbe61ed410309e9d05c8d7251bfd0c0000000000000000000000003be58595e85f680b1c99d0609ec1a112343cb57a0000000000000000000000003fc3f7d3da5c86f98d0853c6251b6572e99f0c6600000000000000000000000041f5ffa60bb330e1e222d60b940c2bac822480a3000000000000000000000000442abd4a1b02c6a0c31a0d51f448f1a72d41795e0000000000000000000000004aeea78e511fc13695281241a493929eca60912600000000000000000000000054de4d66aa07a0c9484bae76389e3ec3402e917100000000000000000000000056b2a061617d8dc5e4482c1ba4a0c850744594af0000000000000000000000005aa6a3887c56ef26ff5736b0f2354e484afddcbc0000000000000000000000006e3b643effba68342260dcbe05409fd9802a4e5400000000000000000000000076c45aa43af363be0451b99c1887898214ab930d00000000000000000000000077038d69fedec4edff9839cc923c0c62f4fcc7520000000000000000000000007dcad4f9bb9e9585c9ca1978c52126606faf354b000000000000000000000000809b632be9a9b025187bf2b4893d2fa87558174a00000000000000000000000087f5dd531c7f9838291cc10464983c29fe1bb71a00000000000000000000000094b700667f97d0577314b5e8f886adafed40870700000000000000000000000096e32bd5d103f7f89f1e42a2f35c4cebfc5287ec0000000000000000000000009b3a3b6d76aeb5c458e1d45e0034f691fb6a3bed000000000000000000000000a730545d1302c55941355c62042d9c48fa9322d4000000000000000000000000a998f1f451683de0ebb90930b89d880c0e6034e6000000000000000000000000ad64359ab18f9dd858e0db4ebdfcf183c99cb135000000000000000000000000ad78ebcffaf59f9dae1ea2072be67400dee51f0b000000000000000000000000b0da8019bdc6aa9cc550d88745b33cc01c43c3bb000000000000000000000000b1f3bc0db216b8d845cd6d4e855fa165d8f8b113000000000000000000000000b65bb46b268d2b68d26234828c918f650472aff4000000000000000000000000bb7ceceb37a2538dfc32b2e363b6df58bb92cc35000000000000000000000000bdf7328260b64523563aefa14144e1424a228fc5000000000000000000000000beebe846a355c4a8d93874c3b58b98c98eef4645000000000000000000000000c16f53f6258ec53804ec94b13d3afb4b614dd674000000000000000000000000c7507c3a590d3b21e0e48505bafc879f68405d84000000000000000000000000c7577ff9c5fba617aec18c737716060e77b5b9d7000000000000000000000000c7bf852d830c3785cc463e5cd0e5f8419a99e408000000000000000000000000cae9234cbf680804f95c9870ac36db4abfe6b05f000000000000000000000000d0abd986c28dec5d9da31a1385fbdc3324da7bf8000000000000000000000000d3a7f36c4924bf7fed2c2d4a403cfe4636dd13bf000000000000000000000000d4cbcf45a0dcecfb70ffea2084b084a724f7856b000000000000000000000000e12605407c6ecac0972afbadeba2a152d86cf301000000000000000000000000ebaab2b70812fcac3c96ef3a62c7998614379285000000000000000000000000ecd21dc2fd55d4fcff73ee6801865c0a87fc9612000000000000000000000000fa79dde61e83b4070daaf24d365ad2e8f2df18fb000000000000000000000000ff07ce905264d12c6bf9564a40560d3d33fe656100000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000fc30000000000000000000000000000000000000000000000000000000000000ce600000000000000000000000000000000000000000000000000000000000004cc00000000000000000000000000000000000000000000000000000000000007ad0000000000000000000000000000000000000000000000000000000000000e960000000000000000000000000000000000000000000000000000000000000fe900000000000000000000000000000000000000000000000000000000000008490000000000000000000000000000000000000000000000000000000000000c0c0000000000000000000000000000000000000000000000000000000000000f9b00000000000000000000000000000000000000000000000000000000000004c8000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000011bc0000000000000000000000000000000000000000000000000000000000000c7d00000000000000000000000000000000000000000000000000000000000010140000000000000000000000000000000000000000000000000000000000000d9b0000000000000000000000000000000000000000000000000000000000000c790000000000000000000000000000000000000000000000000000000000000ab800000000000000000000000000000000000000000000000000000000000017750000000000000000000000000000000000000000000000000000000000000d5100000000000000000000000000000000000000000000000000000000000010b4000000000000000000000000000000000000000000000000000000000000077e0000000000000000000000000000000000000000000000000000000000000b0c0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000142900000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000a3f00000000000000000000000000000000000000000000000000000000000008e10000000000000000000000000000000000000000000000000000000000000c46000000000000000000000000000000000000000000000000000000000000073d00000000000000000000000000000000000000000000000000000000000010dd0000000000000000000000000000000000000000000000000000000000000bf3000000000000000000000000000000000000000000000000000000000000022d00000000000000000000000000000000000000000000000000000000000003ee0000000000000000000000000000000000000000000000000000000000000ca1000000000000000000000000000000000000000000000000000000000000096100000000000000000000000000000000000000000000000000000000000008920000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000b1900000000000000000000000000000000000000000000000000000000000019ff00000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000cb30000000000000000000000000000000000000000000000000000000000000dac000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000007b500000000000000000000000000000000000000000000000000000000000002230000000000000000000000000000000000000000000000000000000000000d6c0000000000000000000000000000000000000000000000000000000000000aaa0000000000000000000000000000000000000000000000000000000000000df9000000000000000000000000000000000000000000000000000000000000095c000000000000000000000000000000000000000000000000000000000000067a000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000cc80000000000000000000000000000000000000000000000000000000000000d28000000000000000000000000000000000000000000000000000000000000043b0000000000000000000000000000000000000000000000000000000000000c0f

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063ba6742e51161005b578063ba6742e5146100ec578063d289d1cb1461010c578063f1501c8914610121578063f2fde38b1461014157600080fd5b806373e3d66a1461008257806376671808146100aa5780638da5cb5b146100c1575b600080fd5b610095610090366004610933565b610154565b60405190151581526020015b60405180910390f35b6100b360015481565b6040519081526020016100a1565b6000546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100a1565b6100b36100fa36600461097f565b60026020526000908152604090205481565b61011f61011a366004610998565b610201565b005b6100b361012f36600461097f565b60036020526000908152604090205481565b61011f61014f3660046109f2565b61026f565b60008080808061016686880188610bd0565b9350935093509350600084848460405160200161018593929190610cc0565b60408051601f19818403018152918152815160209283012060008181526003909352912054600154919250908115806101c8575060106101c58383610d63565b10155b156101e657604051630849699d60e11b815260040160405180910390fd5b6101f38b8888888861034d565b149998505050505050505050565b6000546001600160a01b0316331461022c576040516330cd747160e01b815260040160405180910390fd5b61026b82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061049d92505050565b5050565b6000546001600160a01b0316331461029a576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b0381166102da576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b8351600080805b84518110156104635760006103828a87848151811061037557610375610d7a565b6020026020010151610687565b90505b84841080156103bf57508884815181106103a1576103a1610d7a565b60200260200101516001600160a01b0316816001600160a01b031614155b156103d4576103cd84610d90565b9350610385565b8484141561040e576040517fc6fb539300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87848151811061042057610420610d7a565b6020026020010151836104339190610dab565b9250868310610446575050505050610496565b61044f84610d90565b9350508061045c90610d90565b9050610354565b506040517f203b225800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000806000838060200190518101906104b69190610e1e565b825182519396509194509250908115806104d657506104d48561082a565b155b156104f457604051630849699d60e11b815260040160405180910390fd5b81811461052d576040517f84677ce800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805b828110156105705785818151811061054b5761054b610d7a565b60200260200101518261055e9190610dab565b915061056981610d90565b9050610531565b5083158061057d57508381105b156105b4576040517faabd5a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86516020808901919091206000818152600390925260409091205415610606576040517fadda47f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060015460016106179190610dab565b60018190556000818152600260209081526040808320869055858352600390915290819020829055519091507f05b53362d4afea7533e835bd99f6c0f2c251e2f08b5c461734829516519dd5ac90610674908a908a908a90610cc0565b60405180910390a1505050505050505050565b600081516041146106c4576040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115610730576040517f40c1e74800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060ff16601b1415801561074857508060ff16601c14155b1561077f576040517f119bce3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845289905260ff841692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156107d3573d6000803e3d6000fd5b505050602060405103519450846001600160a01b03161415610821576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505092915050565b6000805b6001835161083c9190610d63565b8110156108b1578261084f826001610dab565b8151811061085f5761085f610d7a565b60200260200101516001600160a01b031683828151811061088257610882610d7a565b60200260200101516001600160a01b0316106108a15750600092915050565b6108aa81610d90565b905061082e565b5060006001600160a01b0316826000815181106108d0576108d0610d7a565b60200260200101516001600160a01b031614159050919050565b60008083601f8401126108fc57600080fd5b50813567ffffffffffffffff81111561091457600080fd5b60208301915083602082850101111561092c57600080fd5b9250929050565b60008060006040848603121561094857600080fd5b83359250602084013567ffffffffffffffff81111561096657600080fd5b610972868287016108ea565b9497909650939450505050565b60006020828403121561099157600080fd5b5035919050565b600080602083850312156109ab57600080fd5b823567ffffffffffffffff8111156109c257600080fd5b6109ce858286016108ea565b90969095509350505050565b6001600160a01b03811681146109ef57600080fd5b50565b600060208284031215610a0457600080fd5b8135610a0f816109da565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610a5557610a55610a16565b604052919050565b600067ffffffffffffffff821115610a7757610a77610a16565b5060051b60200190565b600082601f830112610a9257600080fd5b81356020610aa7610aa283610a5d565b610a2c565b82815260059290921b84018101918181019086841115610ac657600080fd5b8286015b84811015610ae15780358352918301918301610aca565b509695505050505050565b6000601f8381840112610afe57600080fd5b82356020610b0e610aa283610a5d565b82815260059290921b85018101918181019087841115610b2d57600080fd5b8287015b84811015610bc457803567ffffffffffffffff80821115610b525760008081fd5b818a0191508a603f830112610b675760008081fd5b85820135604082821115610b7d57610b7d610a16565b610b8e828b01601f19168901610a2c565b92508183528c81838601011115610ba55760008081fd5b8181850189850137506000908201870152845250918301918301610b31565b50979650505050505050565b60008060008060808587031215610be657600080fd5b843567ffffffffffffffff80821115610bfe57600080fd5b818701915087601f830112610c1257600080fd5b81356020610c22610aa283610a5d565b82815260059290921b8401810191818101908b841115610c4157600080fd5b948201945b83861015610c68578535610c59816109da565b82529482019490820190610c46565b98505088013592505080821115610c7e57600080fd5b610c8a88838901610a81565b9450604087013593506060870135915080821115610ca757600080fd5b50610cb487828801610aec565b91505092959194509250565b606080825284519082018190526000906020906080840190828801845b82811015610d025781516001600160a01b031684529284019290840190600101610cdd565b5050508381038285015285518082528683019183019060005b81811015610d3757835183529284019291840191600101610d1b565b5050809350505050826040830152949350505050565b634e487b7160e01b600052601160045260246000fd5b600082821015610d7557610d75610d4d565b500390565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610da457610da4610d4d565b5060010190565b60008219821115610dbe57610dbe610d4d565b500190565b600082601f830112610dd457600080fd5b81516020610de4610aa283610a5d565b82815260059290921b84018101918181019086841115610e0357600080fd5b8286015b84811015610ae15780518352918301918301610e07565b600080600060608486031215610e3357600080fd5b835167ffffffffffffffff80821115610e4b57600080fd5b818601915086601f830112610e5f57600080fd5b81516020610e6f610aa283610a5d565b82815260059290921b8401810191818101908a841115610e8e57600080fd5b948201945b83861015610eb5578551610ea6816109da565b82529482019490820190610e93565b91890151919750909350505080821115610ece57600080fd5b50610edb86828701610dc3565b92505060408401519050925092509256fea26469706673582212200ddc1b1cc323f5787654ff6b953672c656a5ae6baaac3108e31ea3b7daad1dfd64736f6c63430008090033