ETH Price: $3,040.21 (-4.10%)
 

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Settle With Sign...368498362025-10-15 0:43:3952 days ago1760489019IN
0xb7E565a9...5f7A4cf84
0 ETH0.00000090.00826879
Create366234202025-10-09 18:56:2757 days ago1760036187IN
0xb7E565a9...5f7A4cf84
0 ETH0.000006990.01911244
Create362451972025-10-01 0:49:0166 days ago1759279741IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000790.00220287
Join360702802025-09-26 23:38:2770 days ago1758929907IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000250.00155866
Create360630922025-09-26 19:38:5170 days ago1758915531IN
0xb7E565a9...5f7A4cf84
0 ETH0.000002230.00617788
Create357629282025-09-19 20:53:2377 days ago1758315203IN
0xb7E565a9...5f7A4cf84
0 ETH0.000001730.0047335
Create355817492025-09-15 16:14:0581 days ago1757952845IN
0xb7E565a9...5f7A4cf84
0 ETH0.000007550.02043292
Settle With Sign...354170142025-09-11 20:42:5585 days ago1757623375IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000270.00242752
Join353299982025-09-09 20:22:2387 days ago1757449343IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000730.00463977
Create353299382025-09-09 20:20:2387 days ago1757449223IN
0xb7E565a9...5f7A4cf84
0 ETH0.000001980.0054881
Create351495932025-09-05 16:08:5391 days ago1757088533IN
0xb7E565a9...5f7A4cf84
0 ETH0.000002750.0075033
Create348556312025-08-29 20:50:0998 days ago1756500609IN
0xb7E565a9...5f7A4cf84
0 ETH0.000024490.06692729
Join345505302025-08-22 19:20:07105 days ago1755890407IN
0xb7E565a9...5f7A4cf84
0 ETH0.000001550.00978716
Create345475882025-08-22 17:42:03105 days ago1755884523IN
0xb7E565a9...5f7A4cf84
0 ETH0.000011880.03232884
Settle With Sign...342522392025-08-15 21:37:05112 days ago1755293825IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000460.00422036
Settle With Sign...342522342025-08-15 21:36:55112 days ago1755293815IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000460.00422559
Join342522282025-08-15 21:36:43112 days ago1755293803IN
0xb7E565a9...5f7A4cf84
0 ETH0.000000650.00403221
Create342508992025-08-15 20:52:25112 days ago1755291145IN
0xb7E565a9...5f7A4cf84
0 ETH0.000005040.01376407
Join336402332025-08-01 17:36:53126 days ago1754069813IN
0xb7E565a9...5f7A4cf84
0 ETH0.000002410.01475565
Create336399662025-08-01 17:27:59126 days ago1754069279IN
0xb7E565a9...5f7A4cf84
0 ETH0.000004690.01282058
Settle With Sign...330450702025-07-18 22:58:07140 days ago1752879487IN
0xb7E565a9...5f7A4cf84
0 ETH0.00000120.01084202
Settle With Sign...330450632025-07-18 22:57:53140 days ago1752879473IN
0xb7E565a9...5f7A4cf84
0 ETH0.000001210.01090383
Join330450312025-07-18 22:56:49140 days ago1752879409IN
0xb7E565a9...5f7A4cf84
0 ETH0.000001480.00906294
Create330431462025-07-18 21:53:59140 days ago1752875639IN
0xb7E565a9...5f7A4cf84
0 ETH0.000003810.01037381
Create327297742025-07-11 15:48:15147 days ago1752248895IN
0xb7E565a9...5f7A4cf84
0 ETH0.000008480.02305346
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AnteMetaPoolV01

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 10000 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

import { IAnteGateV01 } from "./interfaces/IAnteGateV01.sol";
import { IAnteMetaPoolV01 } from "./interfaces/IAnteMetaPoolV01.sol";
import { IAnteSettlementV01 } from "./interfaces/IAnteSettlementV01.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { MetaPoolEIP712 } from "./MetaPoolEIP712.sol";
import { Errors } from "./libraries/AnteMetaPoolV01Errors.sol";
import { MetaPoolHash } from "./libraries/MetaPoolV01Hash.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract AnteMetaPoolV01 is IAnteMetaPoolV01, MetaPoolEIP712, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using MetaPoolHash for Settlement;

    /// @dev Helper to deal with division precision
    uint256 internal constant ONE = 10 ** 18;

    /// @inheritdoc IAnteMetaPoolV01
    uint256 public nextId;

    /// @dev Details of all the participants indexed by commitment id
    mapping(uint256 => mapping(address => Participant)) private participants;

    /// @dev Mapping commitments by commitment id
    mapping(uint256 => Commitment) private commitments;

    /// @dev Mapping of total stakes by commitment id
    mapping(uint256 => mapping(ParticipantSide => uint256)) public totalStakes;

    /// @dev Mapping of cancellation initiators by commitment id
    mapping(uint256 => address) public cancellationInitiatedBy;

    /// @inheritdoc IAnteMetaPoolV01
    function create(CreateCommitmentParams calldata params) external {
        if (params.joinDetails.minStake.amount == 0) {
            revert Errors.NoMinStake();
        }

        if (params.stakeAmount < params.joinDetails.minStake.amount) {
            revert Errors.MinStakeRequired(params.joinDetails.minStake.amount);
        }

        if (params.settlementDetails.settler == address(0)) {
            revert Errors.InvalidSettler();
        }

        address gate = params.joinDetails.gate;

        if (gate != address(0) && gate.code.length == 0) {
            revert Errors.GateNotContract();
        }

        if (params.joinDetails.joinStart > params.joinDetails.joinEnd || params.joinDetails.joinEnd < block.timestamp)
        {
            revert Errors.InvalidJoinParams();
        }

        if (
            params.settlementDetails.settleStart > params.settlementDetails.refundStart
                || params.settlementDetails.refundStart < params.joinDetails.joinStart
                || params.settlementDetails.refundStart < block.timestamp
        ) {
            revert Errors.InvalidSettleParams();
        }

        ParticipantSide side = ParticipantSide.A;

        uint256 anteId = _useId();

        participants[anteId][msg.sender] =
            Participant({ position: params.stakeAmount, side: side, totalAtEntry: totalStakes[anteId][side] });

        commitments[anteId] = Commitment({
            anteId: uint96(anteId),
            payload: params.payload,
            settlementDetails: params.settlementDetails,
            joinDetails: params.joinDetails,
            endDate: params.endDate,
            status: CommitmentStatus.OPEN,
            winningSide: ParticipantSide.NONE,
            firstParticipantA: msg.sender,
            firstParticipantB: address(0),
            oddMultiplier: params.oddMultiplier,
            isCancellable: params.isCancellable
        });

        totalStakes[anteId][side] += params.stakeAmount;

        if (gate != address(0)) {
            IAnteGateV01(gate).initialize(anteId, params.gateData);
        }

        IERC20(params.joinDetails.minStake.token).safeTransferFrom(msg.sender, address(this), params.stakeAmount);

        emit CommitmentCreated(anteId, msg.sender, side, params.stakeAmount);
    }

    /// @inheritdoc IAnteMetaPoolV01
    function join(JoinCommitmentParams calldata params) external nonReentrant {
        Commitment memory commitment = commitments[params.anteId];

        if (commitment.status != CommitmentStatus.OPEN && commitment.status != CommitmentStatus.ACTIVE) {
            revert Errors.NotAllowed();
        }

        if (commitment.joinDetails.joinStart > block.timestamp || commitment.joinDetails.joinEnd < block.timestamp) {
            revert Errors.OutsideJoinPeriod();
        }

        if (params.side != ParticipantSide.A && params.side != ParticipantSide.B) {
            revert Errors.InvalidSide();
        }

        if (uint8(participants[params.anteId][msg.sender].side) > 0) {
            revert Errors.AlreadyJoined();
        }

        Stake memory minStake = commitment.joinDetails.minStake;
        if (params.stakeAmount < minStake.amount) {
            revert Errors.MinStakeRequired(minStake.amount);
        }

        if (
            commitment.joinDetails.gate != address(0)
                && IAnteGateV01(commitment.joinDetails.gate).check(msg.sender, params) == false
        ) {
            revert Errors.NotAllowedByGate();
        }

        if (commitment.status == CommitmentStatus.OPEN && params.side == ParticipantSide.B) {
            commitments[params.anteId].status = CommitmentStatus.ACTIVE;
        }

        uint256 totalAtEntry = totalStakes[params.anteId][params.side];

        if (params.side == ParticipantSide.B && commitment.firstParticipantB == address(0)) {
            commitments[params.anteId].firstParticipantB = msg.sender;
        }

        participants[params.anteId][msg.sender] =
            Participant({ position: params.stakeAmount, side: params.side, totalAtEntry: totalAtEntry });

        totalStakes[params.anteId][params.side] += params.stakeAmount;

        IERC20(minStake.token).safeTransferFrom(msg.sender, address(this), params.stakeAmount);

        emit ParticipantJoined(params.anteId, msg.sender, params.side, params.stakeAmount);
    }

    /// @inheritdoc IAnteMetaPoolV01
    function settle(uint256 anteId) external nonReentrant {
        Commitment memory commitment = commitments[anteId];

        if (commitment.status != CommitmentStatus.ACTIVE) {
            revert Errors.InvalidStatus();
        }

        if (commitment.settlementDetails.settleStart > block.timestamp) {
            revert Errors.SettlementUnavailable();
        }

        address settler = commitment.settlementDetails.settler;
        bytes memory settlerData = commitment.settlementDetails.settlerData;

        if (settler.code.length == 0) {
            revert Errors.SettlerNotContract();
        }

        commitments[anteId].status = CommitmentStatus.SETTLED;

        ParticipantSide winningSide = ParticipantSide(uint8(IAnteSettlementV01(settler).settle(anteId, settlerData)));
        commitments[anteId].winningSide = winningSide;

        address winner = address(0);

        if (winningSide == ParticipantSide.A) {
            winner = commitment.firstParticipantA;
        } else if (winningSide == ParticipantSide.B) {
            winner = commitment.firstParticipantB;
        }

        if (winner != address(0)) {
            commitments[anteId].status = CommitmentStatus.SETTLED;
            _withdrawTo(anteId, winner);
        } else {
            commitments[anteId].status = CommitmentStatus.NO_WINNER;
            _withdrawRefundTo(anteId, commitment.firstParticipantA);
            _withdrawRefundTo(anteId, commitment.firstParticipantB);
        }

        emit CommitmentSettled(anteId, settler, msg.sender, winningSide);
    }

    /// @inheritdoc IAnteMetaPoolV01
    function settleWithSignature(uint256 anteId, Settlement memory settlement) external nonReentrant {
        Commitment memory commitment = commitments[anteId];

        if (settlement.anteId != anteId) {
            revert Errors.InvalidCommitment();
        }

        if (commitment.status != CommitmentStatus.ACTIVE) {
            revert Errors.InvalidStatus();
        }

        if (commitment.settlementDetails.settleStart > block.timestamp) {
            revert Errors.SettlementUnavailable();
        }

        address settler = commitment.settlementDetails.settler;

        if (settler != ECDSA.recover(_hashTypedData(settlement.hash()), settlement.v, settlement.r, settlement.s)) {
            revert Errors.InvalidSignature();
        }

        if (settlement.deadline < block.timestamp) {
            revert Errors.ExpiredSignature();
        }

        ParticipantSide winningSide = settlement.winningSide;
        commitments[anteId].winningSide = winningSide;

        address winner = address(0);
        if (winningSide == ParticipantSide.A) {
            winner = commitment.firstParticipantA;
        } else if (winningSide == ParticipantSide.B) {
            winner = commitment.firstParticipantB;
        }

        if (winner != address(0)) {
            commitments[anteId].status = CommitmentStatus.SETTLED;
            _withdrawTo(anteId, winner);
        } else {
            commitments[anteId].status = CommitmentStatus.NO_WINNER;
            _withdrawRefundTo(anteId, commitment.firstParticipantA);
            _withdrawRefundTo(anteId, commitment.firstParticipantB);
        }

        emit CommitmentSettled(anteId, settler, msg.sender, winningSide);
    }

    /// @inheritdoc IAnteMetaPoolV01
    function withdrawTo(uint256 anteId, address to) external nonReentrant {
        _withdrawTo(anteId, to);
    }

    /// @inheritdoc IAnteMetaPoolV01
    function withdrawRefundTo(uint256 anteId, address to) external nonReentrant {
        _withdrawRefundTo(anteId, to);
    }

    /// @inheritdoc IAnteMetaPoolV01
    function mutuallyCancel(uint256 anteId) external nonReentrant {
        Commitment memory commitment = commitments[anteId];

        if (!commitment.isCancellable) {
            revert Errors.NotCancellable();
        }

        if (commitment.status == CommitmentStatus.SETTLED || commitment.status == CommitmentStatus.NO_WINNER) {
            revert Errors.InvalidStatus();
        }

        if (msg.sender != commitment.firstParticipantA && msg.sender != commitment.firstParticipantB) {
            revert Errors.NotAllowed();
        }

        if (msg.sender == cancellationInitiatedBy[anteId]) {
            revert Errors.AlreadyInitiated();
        }

        if (
            (
                cancellationInitiatedBy[anteId] == commitment.firstParticipantA
                    && msg.sender == commitment.firstParticipantB
            )
                || (
                    cancellationInitiatedBy[anteId] == commitment.firstParticipantB
                        && msg.sender == commitment.firstParticipantA
                )
        ) {
            _cancelCommitment(anteId);
        } else {
            cancellationInitiatedBy[anteId] = msg.sender;
            emit CancellationInitiated(anteId, msg.sender);
        }
    }

    /// @inheritdoc IAnteMetaPoolV01
    function getCommitment(uint256 anteId) external view returns (Commitment memory) {
        return commitments[anteId];
    }

    /// @inheritdoc IAnteMetaPoolV01
    function getParticipant(
        uint256 anteId,
        address account
    )
        external
        view
        returns (uint256 position, ParticipantSide side, uint256 totalAtEntry, uint256 balance)
    {
        position = participants[anteId][account].position;
        side = participants[anteId][account].side;
        totalAtEntry = participants[anteId][account].totalAtEntry;

        Commitment memory commitment = commitments[anteId];
        if (commitment.status == CommitmentStatus.SETTLED || commitment.status == CommitmentStatus.NO_WINNER) {
            balance = _calculateAvailableFunds(anteId, account, commitment.winningSide);
        } else {
            balance = 0;
        }
    }

    /// @inheritdoc IAnteMetaPoolV01
    function getTotalStake(uint256 anteId, ParticipantSide side) external view returns (uint256) {
        return totalStakes[anteId][side];
    }

    /// @notice Returns the next Ante ID and increments it
    /// @return nextId used for the next commitment
    function _useId() internal returns (uint256) {
        unchecked {
            return nextId++;
        }
    }

    /// @notice Withdraw funds to a given address
    function _withdrawTo(uint256 anteId, address to) internal {
        Commitment memory commitment = commitments[anteId];

        if (commitment.status != CommitmentStatus.SETTLED) {
            revert Errors.InvalidStatus();
        }

        uint256 amount = _calculateAvailableFunds(anteId, to, commitment.winningSide);

        participants[anteId][to].position = 0;

        if (amount == 0) {
            revert Errors.EmptyBalance();
        }

        IERC20(commitment.joinDetails.minStake.token).safeTransfer(to, amount);

        emit Withdraw(anteId, to, amount);
    }

    function _withdrawRefundTo(uint256 anteId, address to) internal {
        Commitment memory commitment = commitments[anteId];

        if (commitment.status == CommitmentStatus.SETTLED) {
            revert Errors.InvalidStatus();
        }

        Stake memory minStake = commitment.joinDetails.minStake;

        if (commitment.status == CommitmentStatus.ACTIVE && commitment.settlementDetails.refundStart > block.timestamp)
        {
            revert Errors.PendingSettlement();
        }

        /// @dev This prevents DDoS attacks, allowing only author to early
        ///      cancel a commitment
        if (
            commitment.status == CommitmentStatus.OPEN && commitment.settlementDetails.refundStart > block.timestamp
                && msg.sender != commitment.firstParticipantA
        ) {
            revert Errors.NotAllowed();
        }

        uint256 withdrawAmount = participants[anteId][to].position;
        participants[anteId][to].position = 0;

        if (withdrawAmount == 0) {
            revert Errors.EmptyBalance();
        }

        if (commitment.status != CommitmentStatus.NO_WINNER) {
            _cancelCommitment(anteId);
        }

        IERC20(minStake.token).safeTransfer(to, withdrawAmount);

        emit WithdrawRefund(anteId, to);
    }

    function _cancelCommitment(uint256 anteId) internal {
        commitments[anteId].status = CommitmentStatus.NO_WINNER;
        emit CommitmentCanceled(anteId);
    }

    function _calculateAvailableFunds(
        uint256 anteId,
        address to,
        ParticipantSide winningSide
    )
        internal
        view
        returns (uint256)
    {
        Participant memory participant = participants[anteId][to];

        if (participant.position == 0) {
            return 0;
        }

        Commitment memory commitment = commitments[anteId];

        uint256 totalAtEntry = participant.totalAtEntry;
        uint256 totalAfterEntry = totalAtEntry + participant.position;

        uint256 oddMultiplierA = commitment.oddMultiplier;
        uint256 oddMultiplierB = ONE * ONE / oddMultiplierA;

        uint256 participantSideMultiplier = participant.side == ParticipantSide.A ? oddMultiplierA : oddMultiplierB;
        uint256 otherSideTotal = participant.side == ParticipantSide.A
            ? totalStakes[anteId][ParticipantSide.B]
            : totalStakes[anteId][ParticipantSide.A];

        uint256 amount = 0;

        /// @dev We ensure participant.side is not ParticipantSide.NONE in create/join function
        if (participant.side == winningSide) {
            if (totalAfterEntry * participantSideMultiplier / ONE <= otherSideTotal) {
                /// If there are enough funds on the losing side to pay all the
                /// participants from the winning side who joined before the currently
                /// fetched participant + the current participant,
                /// then allow the participant to redeem:
                /// his stake + his stake * odd multiplier corresponding to his side
                amount = participant.position + participantSideMultiplier * participant.position / ONE;
            } else if (totalAtEntry * participantSideMultiplier / ONE < otherSideTotal) {
                /// If there are enough funds on the losing side to pay all the
                /// participants from the winning side who joined before the currently
                /// fetched participant, but not enough to pay the current participant in full,
                /// then allow the participant to redeem:
                /// his stake + all remaining funds from losing side
                amount = participant.position + otherSideTotal - totalAtEntry * participantSideMultiplier / ONE;
            } else {
                /// If there are not enough funds on the losing side to pay the rewards,
                /// allow the winning participant to withdraw his initial stake
                amount = participant.position;
            }
        } else {
            uint256 otherSideMultiplier = participant.side == ParticipantSide.A ? oddMultiplierB : oddMultiplierA;
            uint256 winningSideRewards = otherSideTotal * otherSideMultiplier / ONE;

            if ((winningSide == ParticipantSide.NONE) || (totalAtEntry >= winningSideRewards)) {
                /// If there is no winner, allow participant to withdraw his stake.
                /// If participant has lost, but there are enough funds on his side
                /// to pay all the winners, then allow participant to withdraw his stake.
                amount = participant.position;
            } else if (totalAfterEntry > winningSideRewards) {
                /// If there are not enough funds on participant's side to pay
                /// all the winners, but the participant stake is enough to cover
                /// the gap, allow the participant to withdraw the surplus.
                amount = totalAfterEntry - winningSideRewards;
            }
        }

        return amount;
    }
}

// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

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

/// @title The interface for an AnteGate smart contract
interface IAnteGateV01 {
    /// @notice Initializes the gate with optional data
    /// @param commitmentId The ID of the commitment for which this gate is
    ///                     getting initialized
    /// @param data Data used to set the conditions of the gate
    function initialize(uint256 commitmentId, bytes memory data) external;

    /// @notice Checks if the candidate is allowed by this gate
    /// @param candidate The address of the user getting verified
    /// @param entryData Details about user participation and some arbitrary
    ///                  data used to proove the eligibility to pass the gate
    /// @return true if candidate is allowed to pass
    function check(
        address candidate,
        IAnteMetaPoolV01.JoinCommitmentParams memory entryData
    )
        external
        returns (bool);
}

// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

/// @title The interface for Ante v0.1 AnteMetaPool smart contract
interface IAnteMetaPoolV01 {
    enum CommitmentStatus {
        NONE,
        OPEN,
        ACTIVE,
        SETTLED,
        NO_WINNER
    }

    enum ParticipantSide {
        NONE,
        A,
        B
    }

    struct Participant {
        /// @notice The amount of tokens staked by participant
        uint256 position;
        /// @notice The side of the commitment on which the participant has joined
        ParticipantSide side;
        /// @notice The total stake on joining side before adding participant's
        ///         position
        uint256 totalAtEntry;
    }

    struct Commitment {
        /// @notice Unique commitment ID
        uint96 anteId;
        /// @notice The timestamp of commitment end date
        ///         Also represents the start of the settlement window
        uint64 endDate;
        /// @notice The author of the commitment
        address firstParticipantA;
        /// @notice The status of the commitment
        CommitmentStatus status;
        /// @notice The side that won the commitment
        ParticipantSide winningSide;
        /// @notice First person joining the commitment on B side
        address firstParticipantB;
        /// @notice If true, the commitment can be canceled before settlement
        ///         by firstParticipantA and firstParticipantB both calling
        ///         the mutuallyCancel function.
        ///         IMPORTANT: If firstParticipantA and firstParticipantB
        ///         are controlled by the same party, they can one-sidedly
        ///         cancel the commitment. A bad actor could use this to troll
        ///         participants by preventing settlement; this does not steal
        ///         user funds but wastes everyone's gas and time.
        ///         Please be cautious about who owns firstParticipantA and
        ///         firstParticipantB when joining a cancelable commitment.
        bool isCancellable;
        /// @notice Hashed representation of the commitment
        bytes payload;
        /// @notice The multiplier resulted from provided odds.
        ///         This is used to calculate the payout.
        ///         This is assumed to be in the format (A side):(B side)
        ///
        ///         E.g. 10:1 odds => 10 * 10 ** 18 multiplier
        ///         If A stakes $10 and win, A can get $100 + $10 (initial stake)
        ///         If B stakes $10 and win, B can get $1 + $10 (initial stake)
        ///
        ///         E.g. 3:2 odds => A multiplier: 3/2 * 10 ** 18
        ///                          B multiplier: 2/3 * 10 ** 18
        uint256 oddMultiplier;
        /// @notice The requirements for joining a commitment
        JoinDetails joinDetails;
        /// @notice The settlement details of the commitment
        SettlementDetails settlementDetails;
    }

    struct JoinDetails {
        /// @notice The stake required to join the commitment
        Stake minStake;
        /// @notice The timestamp after which participants can join
        uint48 joinStart;
        /// @notice The end of joining period
        uint48 joinEnd;
        /// @notice The address of a contract containing logic for restricting
        ///         who can join the commitment
        address gate;
    }

    struct SettlementDetails {
        /// @notice EOA or smart contract meant to settle the outcome
        address settler;
        /// @notice The start of the settlement window
        uint48 settleStart;
        /// @notice The date after which participants can withdraw their initial
        ///         stake is a commitment has not been settled yet
        uint48 refundStart;
        /// @notice Data passed to settler in case of smart contract settlement
        bytes settlerData;
    }

    struct CreateCommitmentParams {
        /// @notice The requirements for joining a commitment
        JoinDetails joinDetails;
        /// @notice The settlement details of the commitment
        SettlementDetails settlementDetails;
        /// @notice Hashed representation of the commitment
        bytes payload;
        /// @notice The staked amount of the participant
        uint256 stakeAmount;
        /// @notice The timestamp of commitment end date
        ///         Also represents the start of the settlement window
        uint64 endDate;
        /// @notice The multiplier resulted from provided odds.
        uint256 oddMultiplier;
        /// @notice Arbitrary data used to initialize the gate contract
        bytes gateData;
        /// @notice Determines if the created commitment is cancellable
        bool isCancellable;
    }

    struct JoinCommitmentParams {
        /// @notice The ID of the commitment the user wants to join
        uint256 anteId;
        /// @notice The side on which the user wants to join
        ParticipantSide side;
        /// @notice The amount of tokens the user wants to stake
        uint256 stakeAmount;
        /// @notice Arbitrary data used to check if the user is eligible to
        ///         join this commitment. This is passed to the gate contract
        ///         if specified on creation.
        bytes entryKeyData;
    }

    struct Stake {
        /// @notice the token at stake
        address token;
        /// @notice the minimum amount of the token required to join
        uint256 amount;
    }

    struct Settlement {
        /// @notice A nicely formatted message displayed to users.
        ///         This does not require any onchain validation.
        ///         The source of truth are the other fields coming with the
        ///         signature.
        string explanation;
        /// @notice ID of the commitment that has to be settled
        uint256 anteId;
        /// @notice The winning side of the commitment
        ParticipantSide winningSide;
        /// @notice The timestamp until which the signature is valid
        uint256 deadline;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    /// @notice Event emitted after the commitment is created in MetaPool
    /// @param anteId The commitment ID
    /// @param author The address of the author creating the commitment
    /// @param side The side on which the author joined
    /// @param stakeAmount The amount of staked tokens
    event CommitmentCreated(uint256 indexed anteId, address indexed author, ParticipantSide side, uint256 stakeAmount);

    /// @notice Event emitted after a new participant joins a commitment
    /// @param anteId The commitment ID
    /// @param participant The address of the participant joining the commitment
    /// @param side The side on which the participant joined
    /// @param stakeAmount The amount of staked tokens
    event ParticipantJoined(
        uint256 indexed anteId, address indexed participant, ParticipantSide side, uint256 stakeAmount
    );

    /// @notice Event emitted after participant has withdrawn funds from a
    ///         settled commitment
    /// @param anteId The commitment ID
    /// @param participant The address of the participant joining the commitment
    /// @param amount The amount of tokens that have been withdrawn
    event Withdraw(uint256 indexed anteId, address indexed participant, uint256 amount);

    /// @notice Event emitted after the commitment was settled
    /// @param anteId The ID of the settled commitment
    /// @param settler The address who settled the commitment
    /// @param submitter The address which executed the settlement transaction
    /// @param winningSide The winning side of the commitment
    event CommitmentSettled(
        uint256 indexed anteId, address indexed settler, address submitter, ParticipantSide winningSide
    );

    /// @notice Event emitted after a participant withdraws funds
    ///         from an unsettled commitment or a commitment without winner
    /// @param anteId The ID of the commitment to withdraw from
    /// @param to The address to which to distribute funds
    event WithdrawRefund(uint256 indexed anteId, address indexed to);

    /// @notice Event emitted after the commitment cancellation was initiated
    /// @param anteId The commitment ID
    /// @param anteId The address of the party initiating the cancellation
    event CancellationInitiated(uint256 indexed anteId, address initiator);

    /// @notice Event emitted after the commitment was mutually canceled
    /// @param anteId The commitment ID
    event CommitmentCanceled(uint256 indexed anteId);

    /// @notice Retrieves the next ante ID
    function nextId() external returns (uint256);

    /// @notice Creates the provided commitment and transfers funds to MetaPool
    /// @param params parameters used to construct the commitment
    function create(CreateCommitmentParams calldata params) external;

    /// @notice Join a commitment based on commitment ID
    /// @param params parameters used to join a commitment
    function join(JoinCommitmentParams calldata params) external;

    /// @notice Settles the commitment using settler signature
    ///         and transfer funds to winner
    /// @param anteId ID of commitment to be settled
    /// @param settlement The settlement details signed by settler
    function settleWithSignature(uint256 anteId, Settlement memory settlement) external;

    /// @notice Settles the commitment via a smart contract and transfers
    ///         funds to winner
    /// @param anteId ID of commitment to be settled
    function settle(uint256 anteId) external;

    /// @notice Withdraw funds from a settled commitment
    /// @param anteId ID of commitment to be settled
    /// @param to The recipient address
    function withdrawTo(uint256 anteId, address to) external;

    /// @notice Withdraw funds from an unsettled or a no winner commitment
    /// @param anteId ID of commitment to be settled
    /// @param to The recipient address
    function withdrawRefundTo(uint256 anteId, address to) external;

    /// @notice Cancel a commitment using both sides initiators votes
    /// @param anteId The commitmentId
    function mutuallyCancel(uint256 anteId) external;

    /// @notice Get cancellation initiator for a given commitment
    /// @param anteId The commitment ID
    function cancellationInitiatedBy(uint256 anteId) external view returns (address);

    /// @notice Get the total stake for one side of a given commitment
    /// @param anteId The commitment ID
    /// @param side The stake side
    /// @return total the staked amount
    function getTotalStake(uint256 anteId, ParticipantSide side) external view returns (uint256);

    /// @notice Get commitment details based on anteId
    /// @param anteId The commitmentId
    function getCommitment(uint256 anteId) external view returns (Commitment memory);

    /// @notice Get participant details for a commitment based on anteId
    /// @param anteId The commitmentId
    /// @param account The address of the participant
    /// @return position the staked amount
    /// @return side the participant side
    /// @return totalAtEntry the total side stake at entry
    /// @return balance the available balance based on commitment outcome
    function getParticipant(
        uint256 anteId,
        address account
    )
        external
        view
        returns (uint256 position, ParticipantSide side, uint256 totalAtEntry, uint256 balance);
}

// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

/// @title The interface for a AnteSettlementV01 smart contract
interface IAnteSettlementV01 {
    enum WinningSide {
        NONE,
        A,
        B
    }

    /// @notice Settles the outcome of a given commitment
    /// @param anteId The Ante ID that is settled
    /// @param data Arbitrary data used to determine the outcome
    /// @return the winning side
    function settle(uint256 anteId, bytes memory data) external returns (WinningSide);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @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 {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError, bytes32) {
        // 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 (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): 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) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

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

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}

// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

import { IEIP712 } from "./interfaces/IEIP712.sol";

/// @notice EIP712 helpers for signature verification
/// @dev Reference:
///     https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol
contract MetaPoolEIP712 is IEIP712 {
    // Cache the domain separator as an immutable value, but also store the chain id that it
    // corresponds to, in order to invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;

    bytes32 private constant _HASHED_VERSION = keccak256("1");
    bytes32 private constant _HASHED_NAME = keccak256("AnteMetaPoolV01");
    bytes32 private constant _TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    constructor() {
        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME);
    }

    /// @notice Returns the domain separator for the current chain.
    /// @dev Uses cached version if chainid and address are unchanged from construction.
    function DOMAIN_SEPARATOR() public view override returns (bytes32) {
        return
            block.chainid == _cachedChainId ? _cachedDomainSeparator : _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME);
    }

    /// @notice Creates an EIP-712 typed data hash
    function _hashTypedData(bytes32 dataHash) internal view returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), dataHash));
    }

    /// @notice Builds a domain separator using the current chainId and contract address.
    function _buildDomainSeparator(bytes32 typeHash, bytes32 nameHash) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, _HASHED_VERSION, block.chainid, address(this)));
    }
}

File 9 of 14 : AnteMetaPoolV01Errors.sol
// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

library Errors {
    /// @notice Thrown when commitment does not allow the given action
    error NotAllowed();
    /// @notice Thrown when commitment is not in the required state
    error InvalidStatus();
    /// @notice Thrown when provided signature doesn't match the expected input
    error InvalidSignature();
    /// @notice Thrown when settlement period is active
    error PendingSettlement();
    /// @notice Thrown when settlement period has not started
    error SettlementUnavailable();
    /// @notice Thrown when the provided commitment doesn't match
    ///         the expected commitment id
    error InvalidCommitment();
    /// @notice Thrown when the deadline of a signature has passed
    error ExpiredSignature();
    /// @notice Thrown when the settlement is attepted for a EOA address
    error SettlerNotContract();
    /// @notice Thrown when there are no funds
    error EmptyBalance();
    /// @notice Thrown when staked funds are less than min stake
    error MinStakeRequired(uint256 minStake);
    /// @notice Thrown when a participant has already joined
    error AlreadyJoined();
    /// @notice Thrown when a participant tries to join with an invalid side
    error InvalidSide();
    /// @notice Thrown when a commitment is created with no settler
    error InvalidSettler();
    /// @notice Thrown when a participant already initiated a cancellation
    error AlreadyInitiated();
    /// @notice Thrown when joining period is too short
    error InvalidJoinParams();
    /// @notice Thrown when settlement window is too short
    error InvalidSettleParams();
    /// @notice Thrown when someone tries to join when outside of join period
    error OutsideJoinPeriod();
    /// @notice Thrown when the provided gate address is not a smart contract
    error GateNotContract();
    /// @notice Thrown when the user has failed to check conditions of a gate
    error NotAllowedByGate();
    /// @notice Thrown when user tries to create commitment with min stake 0
    error NoMinStake();
    /// @notice Thrown when someone tries to cancel a non cancellable commitment
    error NotCancellable();
}

// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

import { IAnteMetaPoolV01 } from "../interfaces/IAnteMetaPoolV01.sol";

library MetaPoolHash {
    bytes32 public constant SETTLEMENT_TYPEHASH =
        keccak256("Settlement(string explanation,uint256 anteId,uint8 winningSide,uint256 deadline)");

    function hash(IAnteMetaPoolV01.Settlement memory settlement) internal pure returns (bytes32) {
        return keccak256(
            abi.encode(
                SETTLEMENT_TYPEHASH,
                keccak256(bytes(settlement.explanation)),
                settlement.anteId,
                settlement.winningSide,
                settlement.deadline
            )
        );
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

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

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

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

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

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

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

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) 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 FailedInnerCall();
        }
    }
}

// SPDX-License-Identifier: GPL-3.0-only

// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pragma solidity 0.8.23;

interface IEIP712 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "forge-std/=lib/forge-std/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "hardhat/=node_modules/hardhat/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AlreadyInitiated","type":"error"},{"inputs":[],"name":"AlreadyJoined","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"EmptyBalance","type":"error"},{"inputs":[],"name":"ExpiredSignature","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"GateNotContract","type":"error"},{"inputs":[],"name":"InvalidCommitment","type":"error"},{"inputs":[],"name":"InvalidJoinParams","type":"error"},{"inputs":[],"name":"InvalidSettleParams","type":"error"},{"inputs":[],"name":"InvalidSettler","type":"error"},{"inputs":[],"name":"InvalidSide","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidStatus","type":"error"},{"inputs":[{"internalType":"uint256","name":"minStake","type":"uint256"}],"name":"MinStakeRequired","type":"error"},{"inputs":[],"name":"NoMinStake","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"inputs":[],"name":"NotAllowedByGate","type":"error"},{"inputs":[],"name":"NotCancellable","type":"error"},{"inputs":[],"name":"OutsideJoinPeriod","type":"error"},{"inputs":[],"name":"PendingSettlement","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SettlementUnavailable","type":"error"},{"inputs":[],"name":"SettlerNotContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"},{"indexed":false,"internalType":"address","name":"initiator","type":"address"}],"name":"CancellationInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"}],"name":"CommitmentCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"},{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":false,"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"side","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"stakeAmount","type":"uint256"}],"name":"CommitmentCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"},{"indexed":true,"internalType":"address","name":"settler","type":"address"},{"indexed":false,"internalType":"address","name":"submitter","type":"address"},{"indexed":false,"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"winningSide","type":"uint8"}],"name":"CommitmentSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"},{"indexed":false,"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"side","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"stakeAmount","type":"uint256"}],"name":"ParticipantJoined","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"},{"indexed":true,"internalType":"address","name":"participant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"anteId","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"WithdrawRefund","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"cancellationInitiatedBy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IAnteMetaPoolV01.Stake","name":"minStake","type":"tuple"},{"internalType":"uint48","name":"joinStart","type":"uint48"},{"internalType":"uint48","name":"joinEnd","type":"uint48"},{"internalType":"address","name":"gate","type":"address"}],"internalType":"struct IAnteMetaPoolV01.JoinDetails","name":"joinDetails","type":"tuple"},{"components":[{"internalType":"address","name":"settler","type":"address"},{"internalType":"uint48","name":"settleStart","type":"uint48"},{"internalType":"uint48","name":"refundStart","type":"uint48"},{"internalType":"bytes","name":"settlerData","type":"bytes"}],"internalType":"struct IAnteMetaPoolV01.SettlementDetails","name":"settlementDetails","type":"tuple"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"stakeAmount","type":"uint256"},{"internalType":"uint64","name":"endDate","type":"uint64"},{"internalType":"uint256","name":"oddMultiplier","type":"uint256"},{"internalType":"bytes","name":"gateData","type":"bytes"},{"internalType":"bool","name":"isCancellable","type":"bool"}],"internalType":"struct IAnteMetaPoolV01.CreateCommitmentParams","name":"params","type":"tuple"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"}],"name":"getCommitment","outputs":[{"components":[{"internalType":"uint96","name":"anteId","type":"uint96"},{"internalType":"uint64","name":"endDate","type":"uint64"},{"internalType":"address","name":"firstParticipantA","type":"address"},{"internalType":"enum IAnteMetaPoolV01.CommitmentStatus","name":"status","type":"uint8"},{"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"winningSide","type":"uint8"},{"internalType":"address","name":"firstParticipantB","type":"address"},{"internalType":"bool","name":"isCancellable","type":"bool"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"oddMultiplier","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IAnteMetaPoolV01.Stake","name":"minStake","type":"tuple"},{"internalType":"uint48","name":"joinStart","type":"uint48"},{"internalType":"uint48","name":"joinEnd","type":"uint48"},{"internalType":"address","name":"gate","type":"address"}],"internalType":"struct IAnteMetaPoolV01.JoinDetails","name":"joinDetails","type":"tuple"},{"components":[{"internalType":"address","name":"settler","type":"address"},{"internalType":"uint48","name":"settleStart","type":"uint48"},{"internalType":"uint48","name":"refundStart","type":"uint48"},{"internalType":"bytes","name":"settlerData","type":"bytes"}],"internalType":"struct IAnteMetaPoolV01.SettlementDetails","name":"settlementDetails","type":"tuple"}],"internalType":"struct IAnteMetaPoolV01.Commitment","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"getParticipant","outputs":[{"internalType":"uint256","name":"position","type":"uint256"},{"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"side","type":"uint8"},{"internalType":"uint256","name":"totalAtEntry","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"},{"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"side","type":"uint8"}],"name":"getTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"anteId","type":"uint256"},{"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"side","type":"uint8"},{"internalType":"uint256","name":"stakeAmount","type":"uint256"},{"internalType":"bytes","name":"entryKeyData","type":"bytes"}],"internalType":"struct IAnteMetaPoolV01.JoinCommitmentParams","name":"params","type":"tuple"}],"name":"join","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"}],"name":"mutuallyCancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"}],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"},{"components":[{"internalType":"string","name":"explanation","type":"string"},{"internalType":"uint256","name":"anteId","type":"uint256"},{"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"winningSide","type":"uint8"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IAnteMetaPoolV01.Settlement","name":"settlement","type":"tuple"}],"name":"settleWithSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"enum IAnteMetaPoolV01.ParticipantSide","name":"","type":"uint8"}],"name":"totalStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawRefundTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"anteId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c060405234801561001057600080fd5b504660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6e5a829d57aafb43b4a73e4df8ca22dbd0f87728fa64ba69deb61d60ace6b92d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060830152608082019490945230818401528151808203909301835260c00190528051910120608052600160005560805160a05161509f6100de6000396000610f1001526000610fdc015261509f6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063562c880d1161008c57806387305c711161006657806387305c71146101e25780638df82800146101f5578063aeda886714610208578063c86283c81461024957600080fd5b8063562c880d146101a657806361b8ce8c146101b957806369bcdb7d146101c257600080fd5b806335f3ad7a116100c857806335f3ad7a146101555780633644e5151461017857806339842505146101805780634e6859761461019357600080fd5b8063029f1dea146100ef5780630a8d09901461010457806326e5a7af14610117575b600080fd5b6101026100fd366004614489565b61025c565b005b6101026101123660046144e0565b610b5c565b610142610125366004614524565b600460209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101686101633660046144e0565b610b7c565b60405161014c9493929190614597565b610142610f0c565b61010261018e3660046146df565b610ffe565b6101026101a13660046147a2565b61166c565b6101426101b4366004614524565b611f36565b61014260015481565b6101d56101d03660046147de565b611f80565b60405161014c91906148a9565b6101026101f03660046147de565b61228a565b6101026102033660046147de565b612817565b6102316102163660046147de565b6005602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161014c565b6101026102573660046144e0565b612edc565b610264612eee565b8035600090815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156102eb576102eb614554565b60048111156102fc576102fc614554565b81526020016001820160159054906101000a900460ff16600281111561032457610324614554565b600281111561033557610335614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610371906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461039d906149e2565b80156103ea5780601f106103bf576101008083540402835291602001916103ea565b820191906000526020600020905b8154815290600101906020018083116103cd57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916104da906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610506906149e2565b80156105535780601f1061052857610100808354040283529160200191610553565b820191906000526020600020905b81548152906001019060200180831161053657829003601f168201915b50505091909252505050905250905060018160600151600481111561057a5761057a614554565b1415801561059e575060028160600151600481111561059b5761059b614554565b14155b156105d5576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161012001516020015165ffffffffffff1611806106045750428161012001516040015165ffffffffffff16105b1561063b576040517f3fa1e77700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600161064d6040840160208501614a35565b600281111561065e5761065e614554565b1415801561068d575060026106796040840160208501614a35565b600281111561068a5761068a614554565b14155b156106c4576040517f0dfa289a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8135600090815260026020818152604080842033855290915282206001015460ff16908111156106f6576106f6614554565b60ff161115610730576040517e3b268200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160208101516040840135101561078a5780602001516040517fc155354500000000000000000000000000000000000000000000000000000000815260040161078191815260200190565b60405180910390fd5b610120820151606001516001600160a01b0316158015906108225750816101200151606001516001600160a01b0316636bf31afe33856040518363ffffffff1660e01b81526004016107dd929190614a7d565b6020604051808303816000875af11580156107fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108209190614b43565b155b15610859576040517f20815a6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561087157610871614554565b14801561089e5750600261088b6040850160208601614a35565b600281111561089c5761089c614554565b145b156108f4578235600090815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790555b8235600090815260046020908152604080832091839161091991908801908801614a35565b600281111561092a5761092a614554565b600281111561093b5761093b614554565b8152602081019190915260400160002054905060026109606040860160208701614a35565b600281111561097157610971614554565b148015610989575060a08301516001600160a01b0316155b156109ca578335600090815260036020526040902060020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b60408051606081018252908501803582526020808301916109ec918801614a35565b60028111156109fd576109fd614554565b8152602090810183905285356000908152600280835260408083203384528452909120835181559183015160018084018054929390927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691908490811115610a6857610a68614554565b021790555060409182015160029091015584356000908152600460209081528282209287018035939291610a9e91908901614a35565b6002811115610aaf57610aaf614554565b6002811115610ac057610ac0614554565b81526020019081526020016000206000828254610add9190614b8f565b90915550508151610afd906001600160a01b031633306040880135612f31565b3384357fd863744651582721a04a30bd72905fbdb34e0ab6e0397e0d9c601e730ad3e65e610b316040880160208901614a35565b8760400135604051610b44929190614ba2565b60405180910390a3505050610b596001600055565b50565b610b64612eee565b610b6e8282612fb3565b610b786001600055565b5050565b60008281526002602081815260408084206001600160a01b038681168652908352818520805460018083015492909601548988526003865284882085516101608101875281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169781019790975296870154938416948601949094529560ff91821695939490938493919290916060840191600160a01b909104166004811115610c3257610c32614554565b6004811115610c4357610c43614554565b81526020016001820160159054906101000a900460ff166002811115610c6b57610c6b614554565b6002811115610c7c57610c7c614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610cb8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce4906149e2565b8015610d315780601f10610d0657610100808354040283529160200191610d31565b820191906000526020600020905b815481529060010190602001808311610d1457829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191610e21906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4d906149e2565b8015610e9a5780601f10610e6f57610100808354040283529160200191610e9a565b820191906000526020600020905b815481529060010190602001808311610e7d57829003601f168201915b505050919092525050509052509050600381606001516004811115610ec157610ec1614554565b1480610ee25750600481606001516004811115610ee057610ee0614554565b145b15610efd57610ef6878783608001516134da565b9150610f02565b600091505b5092959194509250565b60007f00000000000000000000000000000000000000000000000000000000000000004614610fd95750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6e5a829d57aafb43b4a73e4df8ca22dbd0f87728fa64ba69deb61d60ace6b92d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b611006612eee565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561108b5761108b614554565b600481111561109c5761109c614554565b81526020016001820160159054906101000a900460ff1660028111156110c4576110c4614554565b60028111156110d5576110d5614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191611111906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461113d906149e2565b801561118a5780601f1061115f5761010080835404028352916020019161118a565b820191906000526020600020905b81548152906001019060200180831161116d57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a01000000000000000000000000000000000000000000000000000090920490911692810192909252600985018054948201949293929184019161127a906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546112a6906149e2565b80156112f35780601f106112c8576101008083540402835291602001916112f3565b820191906000526020600020905b8154815290600101906020018083116112d657829003601f168201915b5050505050815250508152505090508282602001511461133f576040517fc06789fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160600151600481111561135757611357614554565b1461138e576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff1611156113d9576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610140810151516114086113f46113ef85613aad565b613b1c565b84608001518560a001518660c00151613b66565b6001600160a01b0316816001600160a01b031614611452576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4283606001511015611490576040517fdf4cc36d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080840151600086815260036020529190912060010180548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000008360028111156114f7576114f7614554565b02179055506000600182600281111561151257611512614554565b0361152257506040830151611542565b600282600281111561153657611536614554565b03611542575060a08301515b6001600160a01b038116156115ae57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740300000000000000000000000000000000000000001790556115a98682613b94565b61161a565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167404000000000000000000000000000000000000000017905584015161160c908790612fb3565b61161a868560a00151612fb3565b826001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051611656929190614bbd565b60405180910390a350505050610b786001600055565b60208101356000036116aa576040517fd26abf5900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081013560e082013510156116f2576040517fc155354500000000000000000000000000000000000000000000000000000000815260208201356004820152602401610781565b600061170160a0830183614bda565b61170f906020810190614c18565b6001600160a01b03160361174f576040517f3a731e2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061176160a0830160808401614c18565b90506001600160a01b0381161580159061178357506001600160a01b0381163b155b156117ba576040517fed59fdca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117ca6080830160608401614c49565b65ffffffffffff166117e26060840160408501614c49565b65ffffffffffff16118061180c5750426118026080840160608501614c49565b65ffffffffffff16105b15611843576040517fde4f7e9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61185060a0830183614bda565b611861906060810190604001614c49565b65ffffffffffff1661187660a0840184614bda565b611887906040810190602001614c49565b65ffffffffffff1611806118d657506118a66060830160408401614c49565b65ffffffffffff166118bb60a0840184614bda565b6118cc906060810190604001614c49565b65ffffffffffff16105b806119055750426118ea60a0840184614bda565b6118fb906060810190604001614c49565b65ffffffffffff16105b1561193c576040517f58f2e95d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805480820182556040805160608101825260e086013581526020808201858152600085815260048352848120878252835284812054848601528581526002808452858220338352909352939093208251815592518386018054939493919290917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690879084908111156119d4576119d4614554565b0217905550604091820151600290910155805161016081019091526bffffffffffffffffffffffff8216815260208101611a1661012087016101008801614c64565b67ffffffffffffffff168152336020820152604001600181526020016000815260006020820152604001611a5261018087016101608801614c8e565b15158152602001611a6660c0870187614cab565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506101208601356020820152604001611aba36879003870187614d17565b8152602001611acc60a0870187614bda565b611ad590614db7565b9052600082815260036020908152604091829020835181549285015167ffffffffffffffff166c01000000000000000000000000027fffffffffffffffffffffffff00000000000000000000000000000000000000009384166bffffffffffffffffffffffff90921691909117178155918301516001830180546001600160a01b039092169282168317815560608501519290917fffffffffffffffffffffff0000000000000000000000000000000000000000001617600160a01b836004811115611ba357611ba3614554565b021790555060808201516001820180547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115611bfe57611bfe614554565b021790555060a082015160028201805460c08501511515600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b039093169290921791909117905560e08201516003820190611c689082614e94565b506101008201516004820155610120820151805180516005840180546001600160a01b039283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560209182015160068501558183015160078501805460408087015160609788015186166c01000000000000000000000000026bffffffffffffffffffffffff65ffffffffffff9283166601000000000000027fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909516968316969096179390931794909416919091179091556101408701518051600888018054968301519383015185167a0100000000000000000000000000000000000000000000000000000279ffffffffffffffffffffffffffffffffffffffffffffffffffff94909516600160a01b027fffffffffffff000000000000000000000000000000000000000000000000000090971691909516179490941716178155918101519091906009840190611de39082614e94565b505050600083815260046020526040812060e088013593509150846002811115611e0f57611e0f614554565b6002811115611e2057611e20614554565b81526020019081526020016000206000828254611e3d9190614b8f565b90915550506001600160a01b03831615611ec0576001600160a01b03831663edd146cc82611e6f610140880188614cab565b6040518463ffffffff1660e01b8152600401611e8d93929190614f90565b600060405180830381600087803b158015611ea757600080fd5b505af1158015611ebb573d6000803e3d6000fd5b505050505b611ee8333060e0870135611ed76020890189614c18565b6001600160a01b0316929190612f31565b336001600160a01b0316817fa91de7b3d13d8ea9fe2fcd5f0040dc4f1caed875e44595952dc2a04a2517c39c848760e00135604051611f28929190614ba2565b60405180910390a350505050565b600082815260046020526040812081836002811115611f5757611f57614554565b6002811115611f6857611f68614554565b81526020019081526020016000205490505b92915050565b611f886143df565b60008281526003602090815260409182902082516101608101845281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169281019290925260018101546001600160a01b0381169383019390935290916060830190600160a01b900460ff16600481111561200f5761200f614554565b600481111561202057612020614554565b81526020016001820160159054906101000a900460ff16600281111561204857612048614554565b600281111561205957612059614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191612095906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546120c1906149e2565b801561210e5780601f106120e35761010080835404028352916020019161210e565b820191906000526020600020905b8154815290600101906020018083116120f157829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916121fe906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461222a906149e2565b80156122775780601f1061224c57610100808354040283529160200191612277565b820191906000526020600020905b81548152906001019060200180831161225a57829003601f168201915b5050509190925250505090525092915050565b612292612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561231757612317614554565b600481111561232857612328614554565b81526020016001820160159054906101000a900460ff16600281111561235057612350614554565b600281111561236157612361614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161239d906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546123c9906149e2565b80156124165780601f106123eb57610100808354040283529160200191612416565b820191906000526020600020905b8154815290600101906020018083116123f957829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612506906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612532906149e2565b801561257f5780601f106125545761010080835404028352916020019161257f565b820191906000526020600020905b81548152906001019060200180831161256257829003601f168201915b5050505050815250508152505090508060c001516125c9576040517f67909b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816060015160048111156125e1576125e1614554565b1480612602575060048160600151600481111561260057612600614554565b145b15612639576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001516001600160a01b0316336001600160a01b03161415801561267557508060a001516001600160a01b0316336001600160a01b031614155b156126ac576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560205260409020546001600160a01b031633036126fc576040517f36d80ace00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000848152600560205291909120546001600160a01b03908116911614801561274057508060a001516001600160a01b0316336001600160a01b0316145b80612789575060a08101516000838152600560205260409020546001600160a01b039081169116148015612789575080604001516001600160a01b0316336001600160a01b0316145b1561279c5761279782613fa9565b61280c565b60008281526005602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633908117909155915191825283917f57ff98e3b14205ced980e44c40046c02eedbbdc67510b19f6c7848547a589d6c910160405180910390a25b50610b596001600055565b61281f612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156128a4576128a4614554565b60048111156128b5576128b5614554565b81526020016001820160159054906101000a900460ff1660028111156128dd576128dd614554565b60028111156128ee576128ee614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161292a906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612956906149e2565b80156129a35780601f10612978576101008083540402835291602001916129a3565b820191906000526020600020905b81548152906001019060200180831161298657829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612a93906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612abf906149e2565b8015612b0c5780601f10612ae157610100808354040283529160200191612b0c565b820191906000526020600020905b815481529060010190602001808311612aef57829003601f168201915b505050919092525050509052509050600281606001516004811115612b3357612b33614554565b14612b6a576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff161115612bb5576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61014081015180516060909101516001600160a01b0382163b600003612c07576040517faf98a96600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055517f39c2ebb90000000000000000000000000000000000000000000000000000000081526001600160a01b038416906339c2ebb990612c9b9088908690600401614fb3565b6020604051808303816000875af1158015612cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cde9190614fcc565b6002811115612cef57612cef614554565b60ff166002811115612d0357612d03614554565b6000868152600360205260409020600101805491925082917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115612d6657612d66614554565b021790555060006001826002811115612d8157612d81614554565b03612d9157506040840151612db1565b6002826002811115612da557612da5614554565b03612db1575060a08401515b6001600160a01b03811615612e1d57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055612e188682613b94565b612e89565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674040000000000000000000000000000000000000000179055850151612e7b908790612fb3565b612e89868660a00151612fb3565b836001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051612ec5929190614bbd565b60405180910390a35050505050610b596001600055565b612ee4612eee565b610b6e8282613b94565b600260005403612f2a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600055565b6040516001600160a01b038481166024830152838116604483015260648201839052612fad9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050614021565b50505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561303857613038614554565b600481111561304957613049614554565b81526020016001820160159054906101000a900460ff16600281111561307157613071614554565b600281111561308257613082614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff16151560408201526003820180546060909201916130be906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546130ea906149e2565b80156131375780601f1061310c57610100808354040283529160200191613137565b820191906000526020600020905b81548152906001019060200180831161311a57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613227906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613253906149e2565b80156132a05780601f10613275576101008083540402835291602001916132a0565b820191906000526020600020905b81548152906001019060200180831161328357829003601f168201915b5050509190925250505090525090506003816060015160048111156132c7576132c7614554565b036132fe576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160028260600151600481111561331d5761331d614554565b14801561333a5750428261014001516040015165ffffffffffff16115b15613371576040517fd63e68ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561338957613389614554565b1480156133a65750428261014001516040015165ffffffffffff16115b80156133c8575081604001516001600160a01b0316336001600160a01b031614155b156133ff576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526002602090815260408083206001600160a01b0387168452909152812080549082905590819003613461576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60048360600151600481111561347957613479614554565b146134875761348785613fa9565b815161349d906001600160a01b031685836140a2565b6040516001600160a01b0385169086907fbb50b495cfa1f9c6d8d479d4df77a080f4bed07f572d4aa3e89715f21c597da990600090a35050505050565b60008381526002602081815260408084206001600160a01b038716855282528084208151606081019092528054825260018101548594929391929184019160ff9091169081111561352d5761352d614554565b600281111561353e5761353e614554565b815260200160028201548152505090508060000151600003613564576000915050613aa6565b600085815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156135e9576135e9614554565b60048111156135fa576135fa614554565b81526020016001820160159054906101000a900460ff16600281111561362257613622614554565b600281111561363357613633614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161366f906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461369b906149e2565b80156136e85780601f106136bd576101008083540402835291602001916136e8565b820191906000526020600020905b8154815290600101906020018083116136cb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916137d8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613804906149e2565b80156138515780601f1061382657610100808354040283529160200191613851565b820191906000526020600020905b81548152906001019060200180831161383457829003601f168201915b5050509190925250505090525060408301518351919250906000906138769083614b8f565b610100840151909150600081613894670de0b6b3a764000080614fe9565b61389e9190615000565b905060006001876020015160028111156138ba576138ba614554565b146138c557816138c7565b825b905060006001886020015160028111156138e3576138e3614554565b146139085760008c815260046020908152604080832060018452909152902054613924565b60008c8152600460209081526040808320600284529091529020545b905060008a600281111561393a5761393a614554565b8960200151600281111561395057613950614554565b03613a0b5781670de0b6b3a76400006139698589614fe9565b6139739190615000565b116139ab578851670de0b6b3a76400009061398e9085614fe9565b6139989190615000565b89516139a49190614b8f565b9050613a9b565b81670de0b6b3a76400006139bf858a614fe9565b6139c99190615000565b1015613a0357670de0b6b3a76400006139e28489614fe9565b6139ec9190615000565b89516139f9908490614b8f565b6139a4919061503b565b508751613a9b565b600060018a602001516002811115613a2557613a25614554565b14613a305785613a32565b845b90506000670de0b6b3a7640000613a498386614fe9565b613a539190615000565b905060008d6002811115613a6957613a69614554565b1480613a755750808910155b15613a83578a519250613a98565b80881115613a9857613a95818961503b565b92505b50505b985050505050505050505b9392505050565b60007feeebb728eb76a15c65cd720cefd2d1d0bc97ac4e7adc73802393b2d78f8a268f826000015180519060200120836020015184604001518560600151604051602001613aff95949392919061504e565b604051602081830303815290604052805190602001209050919050565b6000613b26610f0c565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201613aff565b600080600080613b78888888886140d3565b925092509250613b8882826141a2565b50909695505050505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff166004811115613c1957613c19614554565b6004811115613c2a57613c2a614554565b81526020016001820160159054906101000a900460ff166002811115613c5257613c52614554565b6002811115613c6357613c63614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191613c9f906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613ccb906149e2565b8015613d185780601f10613ced57610100808354040283529160200191613d18565b820191906000526020600020905b815481529060010190602001808311613cfb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613e08906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613e34906149e2565b8015613e815780601f10613e5657610100808354040283529160200191613e81565b820191906000526020600020905b815481529060010190602001808311613e6457829003601f168201915b505050919092525050509052509050600381606001516004811115613ea857613ea8614554565b14613edf576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613ef0848484608001516134da565b60008581526002602090815260408083206001600160a01b03881684529091528120819055909150819003613f51576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208201515151613f6d906001600160a01b031684836140a2565b826001600160a01b0316847f9da6493a92039daf47d1f2d7a782299c5994c6323eb1e972f69c432089ec52bf83604051611f2891815260200190565b60008181526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740400000000000000000000000000000000000000001790555182917f8950be7004a37e2fd94d3fb6f4c5f4375077f766cc1f518f8651515b9ebe235491a250565b60006140366001600160a01b038416836142a6565b9050805160001415801561405b5750808060200190518101906140599190614b43565b155b1561409d576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610781565b505050565b6040516001600160a01b0383811660248301526044820183905261409d91859182169063a9059cbb90606401612f66565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561410e5750600091506003905082614198565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015614162573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661418e57506000925060019150829050614198565b9250600091508190505b9450945094915050565b60008260038111156141b6576141b6614554565b036141bf575050565b60018260038111156141d3576141d3614554565b0361420a576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561421e5761421e614554565b03614258576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b600382600381111561426c5761426c614554565b03610b78576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b6060613aa68383600084600080856001600160a01b031684866040516142cc9190615080565b60006040518083038185875af1925050503d8060008114614309576040519150601f19603f3d011682016040523d82523d6000602084013e61430e565b606091505b509150915061431e868383614328565b9695505050505050565b60608261433d576143388261439d565b613aa6565b815115801561435457506001600160a01b0384163b155b15614396576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610781565b5080613aa6565b8051156143ad5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516101608101825260008082526020820181905291810182905290606082019081526020016000815260006020820181905260408201819052606080830152608082015260a0016144606040805160c08101825260006080820181815260a08301829052825260208201819052918101829052606081019190915290565b815260408051608081018252600080825260208281018290529282015260608082015291015290565b60006020828403121561449b57600080fd5b813567ffffffffffffffff8111156144b257600080fd5b820160808185031215613aa657600080fd5b80356001600160a01b03811681146144db57600080fd5b919050565b600080604083850312156144f357600080fd5b82359150614503602084016144c4565b90509250929050565b60038110610b5957600080fd5b80356144db8161450c565b6000806040838503121561453757600080fd5b8235915060208301356145498161450c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811061459357614593614554565b9052565b848152608081016145ab6020830186614583565b60408201939093526060015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff8111828210171561460f5761460f6145bd565b60405290565b6040516080810167ffffffffffffffff8111828210171561460f5761460f6145bd565b600067ffffffffffffffff80841115614653576146536145bd565b604051601f8501601f19908116603f0116810190828211818310171561467b5761467b6145bd565b8160405280935085815286868601111561469457600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126146bf57600080fd5b613aa683833560208501614638565b803560ff811681146144db57600080fd5b600080604083850312156146f257600080fd5b82359150602083013567ffffffffffffffff8082111561471157600080fd5b9084019060e0828703121561472557600080fd5b61472d6145ec565b82358281111561473c57600080fd5b614748888286016146ae565b8252506020830135602082015261476160408401614519565b60408201526060830135606082015261477c608084016146ce565b608082015260a083013560a082015260c083013560c08201528093505050509250929050565b6000602082840312156147b457600080fd5b813567ffffffffffffffff8111156147cb57600080fd5b82016101808185031215613aa657600080fd5b6000602082840312156147f057600080fd5b5035919050565b6005811061459357614593614554565b60005b8381101561482257818101518382015260200161480a565b50506000910152565b60008151808452614843816020860160208601614807565b601f01601f19169290920160200192915050565b6001600160a01b0381511682526000602082015165ffffffffffff808216602086015280604085015116604086015250506060820151608060608501526148a1608085018261482b565b949350505050565b602081526148c86020820183516bffffffffffffffffffffffff169052565b600060208301516148e5604084018267ffffffffffffffff169052565b5060408301516001600160a01b038116606084015250606083015161490d60808401826147f7565b50608083015161492060a0840182614583565b5060a08301516001600160a01b03811660c08401525060c083015180151560e08401525060e08301516101e0610100818186015261496261020086018461482b565b9086015161012086810191909152860151805180516001600160a01b03908116610140808a01919091526020928301516101608a01529183015165ffffffffffff9081166101808a01526040840151166101a08901526060830151166101c088015291935090860151858403601f190183870152905061431e8382614857565b600181811c908216806149f657607f821691505b602082108103614a2f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215614a4757600080fd5b8135613aa68161450c565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6001600160a01b0383168152604060208201528135604082015260006020830135614aa78161450c565b614ab46060840182614583565b506040830135608083015260608301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614af457600080fd5b830160208101903567ffffffffffffffff811115614b1157600080fd5b803603821315614b2057600080fd5b608060a085015261431e60c085018284614a52565b8015158114610b5957600080fd5b600060208284031215614b5557600080fd5b8151613aa681614b35565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611f7a57611f7a614b60565b60408101614bb08285614583565b8260208301529392505050565b6001600160a01b038316815260408101613aa66020830184614583565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c0e57600080fd5b9190910192915050565b600060208284031215614c2a57600080fd5b613aa6826144c4565b803565ffffffffffff811681146144db57600080fd5b600060208284031215614c5b57600080fd5b613aa682614c33565b600060208284031215614c7657600080fd5b813567ffffffffffffffff81168114613aa657600080fd5b600060208284031215614ca057600080fd5b8135613aa681614b35565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614ce057600080fd5b83018035915067ffffffffffffffff821115614cfb57600080fd5b602001915036819003821315614d1057600080fd5b9250929050565b600081830360a0811215614d2a57600080fd5b614d32614615565b604080831215614d4157600080fd5b8051925080830183811067ffffffffffffffff82111715614d6457614d646145bd565b8152614d6f856144c4565b835260208501356020840152828252614d89818601614c33565b6020830152614d9a60608601614c33565b90820152614daa608085016144c4565b6060820152949350505050565b600060808236031215614dc957600080fd5b614dd1614615565b614dda836144c4565b8152614de860208401614c33565b6020820152614df960408401614c33565b6040820152606083013567ffffffffffffffff811115614e1857600080fd5b830136601f820112614e2957600080fd5b614e3836823560208401614638565b60608301525092915050565b601f82111561409d576000816000526020600020601f850160051c81016020861015614e6d5750805b601f850160051c820191505b81811015614e8c57828155600101614e79565b505050505050565b815167ffffffffffffffff811115614eae57614eae6145bd565b614ec281614ebc84546149e2565b84614e44565b602080601f831160018114614f155760008415614edf5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614e8c565b600085815260208120601f198616915b82811015614f4457888601518255948401946001909101908401614f25565b5085821015614f8057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b838152604060208201526000614faa604083018486614a52565b95945050505050565b8281526040602082015260006148a1604083018461482b565b600060208284031215614fde57600080fd5b8151613aa68161450c565b8082028115828204841417611f7a57611f7a614b60565b600082615036577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115611f7a57611f7a614b60565b858152602081018590526040810184905260a081016150706060830185614583565b8260808301529695505050505050565b60008251614c0e81846020870161480756fea164736f6c6343000817000a

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063562c880d1161008c57806387305c711161006657806387305c71146101e25780638df82800146101f5578063aeda886714610208578063c86283c81461024957600080fd5b8063562c880d146101a657806361b8ce8c146101b957806369bcdb7d146101c257600080fd5b806335f3ad7a116100c857806335f3ad7a146101555780633644e5151461017857806339842505146101805780634e6859761461019357600080fd5b8063029f1dea146100ef5780630a8d09901461010457806326e5a7af14610117575b600080fd5b6101026100fd366004614489565b61025c565b005b6101026101123660046144e0565b610b5c565b610142610125366004614524565b600460209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101686101633660046144e0565b610b7c565b60405161014c9493929190614597565b610142610f0c565b61010261018e3660046146df565b610ffe565b6101026101a13660046147a2565b61166c565b6101426101b4366004614524565b611f36565b61014260015481565b6101d56101d03660046147de565b611f80565b60405161014c91906148a9565b6101026101f03660046147de565b61228a565b6101026102033660046147de565b612817565b6102316102163660046147de565b6005602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161014c565b6101026102573660046144e0565b612edc565b610264612eee565b8035600090815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156102eb576102eb614554565b60048111156102fc576102fc614554565b81526020016001820160159054906101000a900460ff16600281111561032457610324614554565b600281111561033557610335614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610371906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461039d906149e2565b80156103ea5780601f106103bf576101008083540402835291602001916103ea565b820191906000526020600020905b8154815290600101906020018083116103cd57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916104da906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610506906149e2565b80156105535780601f1061052857610100808354040283529160200191610553565b820191906000526020600020905b81548152906001019060200180831161053657829003601f168201915b50505091909252505050905250905060018160600151600481111561057a5761057a614554565b1415801561059e575060028160600151600481111561059b5761059b614554565b14155b156105d5576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161012001516020015165ffffffffffff1611806106045750428161012001516040015165ffffffffffff16105b1561063b576040517f3fa1e77700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600161064d6040840160208501614a35565b600281111561065e5761065e614554565b1415801561068d575060026106796040840160208501614a35565b600281111561068a5761068a614554565b14155b156106c4576040517f0dfa289a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8135600090815260026020818152604080842033855290915282206001015460ff16908111156106f6576106f6614554565b60ff161115610730576040517e3b268200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160208101516040840135101561078a5780602001516040517fc155354500000000000000000000000000000000000000000000000000000000815260040161078191815260200190565b60405180910390fd5b610120820151606001516001600160a01b0316158015906108225750816101200151606001516001600160a01b0316636bf31afe33856040518363ffffffff1660e01b81526004016107dd929190614a7d565b6020604051808303816000875af11580156107fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108209190614b43565b155b15610859576040517f20815a6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561087157610871614554565b14801561089e5750600261088b6040850160208601614a35565b600281111561089c5761089c614554565b145b156108f4578235600090815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790555b8235600090815260046020908152604080832091839161091991908801908801614a35565b600281111561092a5761092a614554565b600281111561093b5761093b614554565b8152602081019190915260400160002054905060026109606040860160208701614a35565b600281111561097157610971614554565b148015610989575060a08301516001600160a01b0316155b156109ca578335600090815260036020526040902060020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b60408051606081018252908501803582526020808301916109ec918801614a35565b60028111156109fd576109fd614554565b8152602090810183905285356000908152600280835260408083203384528452909120835181559183015160018084018054929390927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691908490811115610a6857610a68614554565b021790555060409182015160029091015584356000908152600460209081528282209287018035939291610a9e91908901614a35565b6002811115610aaf57610aaf614554565b6002811115610ac057610ac0614554565b81526020019081526020016000206000828254610add9190614b8f565b90915550508151610afd906001600160a01b031633306040880135612f31565b3384357fd863744651582721a04a30bd72905fbdb34e0ab6e0397e0d9c601e730ad3e65e610b316040880160208901614a35565b8760400135604051610b44929190614ba2565b60405180910390a3505050610b596001600055565b50565b610b64612eee565b610b6e8282612fb3565b610b786001600055565b5050565b60008281526002602081815260408084206001600160a01b038681168652908352818520805460018083015492909601548988526003865284882085516101608101875281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169781019790975296870154938416948601949094529560ff91821695939490938493919290916060840191600160a01b909104166004811115610c3257610c32614554565b6004811115610c4357610c43614554565b81526020016001820160159054906101000a900460ff166002811115610c6b57610c6b614554565b6002811115610c7c57610c7c614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610cb8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce4906149e2565b8015610d315780601f10610d0657610100808354040283529160200191610d31565b820191906000526020600020905b815481529060010190602001808311610d1457829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191610e21906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4d906149e2565b8015610e9a5780601f10610e6f57610100808354040283529160200191610e9a565b820191906000526020600020905b815481529060010190602001808311610e7d57829003601f168201915b505050919092525050509052509050600381606001516004811115610ec157610ec1614554565b1480610ee25750600481606001516004811115610ee057610ee0614554565b145b15610efd57610ef6878783608001516134da565b9150610f02565b600091505b5092959194509250565b60007f00000000000000000000000000000000000000000000000000000000000021054614610fd95750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6e5a829d57aafb43b4a73e4df8ca22dbd0f87728fa64ba69deb61d60ace6b92d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f3f6f73c14b77a6d24238d37f3dce6ef87cb02d62082e16d8354dc14ccf7b348390565b611006612eee565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561108b5761108b614554565b600481111561109c5761109c614554565b81526020016001820160159054906101000a900460ff1660028111156110c4576110c4614554565b60028111156110d5576110d5614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191611111906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461113d906149e2565b801561118a5780601f1061115f5761010080835404028352916020019161118a565b820191906000526020600020905b81548152906001019060200180831161116d57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a01000000000000000000000000000000000000000000000000000090920490911692810192909252600985018054948201949293929184019161127a906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546112a6906149e2565b80156112f35780601f106112c8576101008083540402835291602001916112f3565b820191906000526020600020905b8154815290600101906020018083116112d657829003601f168201915b5050505050815250508152505090508282602001511461133f576040517fc06789fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160600151600481111561135757611357614554565b1461138e576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff1611156113d9576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610140810151516114086113f46113ef85613aad565b613b1c565b84608001518560a001518660c00151613b66565b6001600160a01b0316816001600160a01b031614611452576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4283606001511015611490576040517fdf4cc36d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080840151600086815260036020529190912060010180548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000008360028111156114f7576114f7614554565b02179055506000600182600281111561151257611512614554565b0361152257506040830151611542565b600282600281111561153657611536614554565b03611542575060a08301515b6001600160a01b038116156115ae57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740300000000000000000000000000000000000000001790556115a98682613b94565b61161a565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167404000000000000000000000000000000000000000017905584015161160c908790612fb3565b61161a868560a00151612fb3565b826001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051611656929190614bbd565b60405180910390a350505050610b786001600055565b60208101356000036116aa576040517fd26abf5900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081013560e082013510156116f2576040517fc155354500000000000000000000000000000000000000000000000000000000815260208201356004820152602401610781565b600061170160a0830183614bda565b61170f906020810190614c18565b6001600160a01b03160361174f576040517f3a731e2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061176160a0830160808401614c18565b90506001600160a01b0381161580159061178357506001600160a01b0381163b155b156117ba576040517fed59fdca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117ca6080830160608401614c49565b65ffffffffffff166117e26060840160408501614c49565b65ffffffffffff16118061180c5750426118026080840160608501614c49565b65ffffffffffff16105b15611843576040517fde4f7e9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61185060a0830183614bda565b611861906060810190604001614c49565b65ffffffffffff1661187660a0840184614bda565b611887906040810190602001614c49565b65ffffffffffff1611806118d657506118a66060830160408401614c49565b65ffffffffffff166118bb60a0840184614bda565b6118cc906060810190604001614c49565b65ffffffffffff16105b806119055750426118ea60a0840184614bda565b6118fb906060810190604001614c49565b65ffffffffffff16105b1561193c576040517f58f2e95d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805480820182556040805160608101825260e086013581526020808201858152600085815260048352848120878252835284812054848601528581526002808452858220338352909352939093208251815592518386018054939493919290917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690879084908111156119d4576119d4614554565b0217905550604091820151600290910155805161016081019091526bffffffffffffffffffffffff8216815260208101611a1661012087016101008801614c64565b67ffffffffffffffff168152336020820152604001600181526020016000815260006020820152604001611a5261018087016101608801614c8e565b15158152602001611a6660c0870187614cab565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506101208601356020820152604001611aba36879003870187614d17565b8152602001611acc60a0870187614bda565b611ad590614db7565b9052600082815260036020908152604091829020835181549285015167ffffffffffffffff166c01000000000000000000000000027fffffffffffffffffffffffff00000000000000000000000000000000000000009384166bffffffffffffffffffffffff90921691909117178155918301516001830180546001600160a01b039092169282168317815560608501519290917fffffffffffffffffffffff0000000000000000000000000000000000000000001617600160a01b836004811115611ba357611ba3614554565b021790555060808201516001820180547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115611bfe57611bfe614554565b021790555060a082015160028201805460c08501511515600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b039093169290921791909117905560e08201516003820190611c689082614e94565b506101008201516004820155610120820151805180516005840180546001600160a01b039283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560209182015160068501558183015160078501805460408087015160609788015186166c01000000000000000000000000026bffffffffffffffffffffffff65ffffffffffff9283166601000000000000027fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909516968316969096179390931794909416919091179091556101408701518051600888018054968301519383015185167a0100000000000000000000000000000000000000000000000000000279ffffffffffffffffffffffffffffffffffffffffffffffffffff94909516600160a01b027fffffffffffff000000000000000000000000000000000000000000000000000090971691909516179490941716178155918101519091906009840190611de39082614e94565b505050600083815260046020526040812060e088013593509150846002811115611e0f57611e0f614554565b6002811115611e2057611e20614554565b81526020019081526020016000206000828254611e3d9190614b8f565b90915550506001600160a01b03831615611ec0576001600160a01b03831663edd146cc82611e6f610140880188614cab565b6040518463ffffffff1660e01b8152600401611e8d93929190614f90565b600060405180830381600087803b158015611ea757600080fd5b505af1158015611ebb573d6000803e3d6000fd5b505050505b611ee8333060e0870135611ed76020890189614c18565b6001600160a01b0316929190612f31565b336001600160a01b0316817fa91de7b3d13d8ea9fe2fcd5f0040dc4f1caed875e44595952dc2a04a2517c39c848760e00135604051611f28929190614ba2565b60405180910390a350505050565b600082815260046020526040812081836002811115611f5757611f57614554565b6002811115611f6857611f68614554565b81526020019081526020016000205490505b92915050565b611f886143df565b60008281526003602090815260409182902082516101608101845281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169281019290925260018101546001600160a01b0381169383019390935290916060830190600160a01b900460ff16600481111561200f5761200f614554565b600481111561202057612020614554565b81526020016001820160159054906101000a900460ff16600281111561204857612048614554565b600281111561205957612059614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191612095906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546120c1906149e2565b801561210e5780601f106120e35761010080835404028352916020019161210e565b820191906000526020600020905b8154815290600101906020018083116120f157829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916121fe906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461222a906149e2565b80156122775780601f1061224c57610100808354040283529160200191612277565b820191906000526020600020905b81548152906001019060200180831161225a57829003601f168201915b5050509190925250505090525092915050565b612292612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561231757612317614554565b600481111561232857612328614554565b81526020016001820160159054906101000a900460ff16600281111561235057612350614554565b600281111561236157612361614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161239d906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546123c9906149e2565b80156124165780601f106123eb57610100808354040283529160200191612416565b820191906000526020600020905b8154815290600101906020018083116123f957829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612506906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612532906149e2565b801561257f5780601f106125545761010080835404028352916020019161257f565b820191906000526020600020905b81548152906001019060200180831161256257829003601f168201915b5050505050815250508152505090508060c001516125c9576040517f67909b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816060015160048111156125e1576125e1614554565b1480612602575060048160600151600481111561260057612600614554565b145b15612639576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001516001600160a01b0316336001600160a01b03161415801561267557508060a001516001600160a01b0316336001600160a01b031614155b156126ac576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560205260409020546001600160a01b031633036126fc576040517f36d80ace00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000848152600560205291909120546001600160a01b03908116911614801561274057508060a001516001600160a01b0316336001600160a01b0316145b80612789575060a08101516000838152600560205260409020546001600160a01b039081169116148015612789575080604001516001600160a01b0316336001600160a01b0316145b1561279c5761279782613fa9565b61280c565b60008281526005602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633908117909155915191825283917f57ff98e3b14205ced980e44c40046c02eedbbdc67510b19f6c7848547a589d6c910160405180910390a25b50610b596001600055565b61281f612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156128a4576128a4614554565b60048111156128b5576128b5614554565b81526020016001820160159054906101000a900460ff1660028111156128dd576128dd614554565b60028111156128ee576128ee614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161292a906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612956906149e2565b80156129a35780601f10612978576101008083540402835291602001916129a3565b820191906000526020600020905b81548152906001019060200180831161298657829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612a93906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612abf906149e2565b8015612b0c5780601f10612ae157610100808354040283529160200191612b0c565b820191906000526020600020905b815481529060010190602001808311612aef57829003601f168201915b505050919092525050509052509050600281606001516004811115612b3357612b33614554565b14612b6a576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff161115612bb5576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61014081015180516060909101516001600160a01b0382163b600003612c07576040517faf98a96600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055517f39c2ebb90000000000000000000000000000000000000000000000000000000081526001600160a01b038416906339c2ebb990612c9b9088908690600401614fb3565b6020604051808303816000875af1158015612cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cde9190614fcc565b6002811115612cef57612cef614554565b60ff166002811115612d0357612d03614554565b6000868152600360205260409020600101805491925082917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115612d6657612d66614554565b021790555060006001826002811115612d8157612d81614554565b03612d9157506040840151612db1565b6002826002811115612da557612da5614554565b03612db1575060a08401515b6001600160a01b03811615612e1d57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055612e188682613b94565b612e89565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674040000000000000000000000000000000000000000179055850151612e7b908790612fb3565b612e89868660a00151612fb3565b836001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051612ec5929190614bbd565b60405180910390a35050505050610b596001600055565b612ee4612eee565b610b6e8282613b94565b600260005403612f2a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600055565b6040516001600160a01b038481166024830152838116604483015260648201839052612fad9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050614021565b50505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561303857613038614554565b600481111561304957613049614554565b81526020016001820160159054906101000a900460ff16600281111561307157613071614554565b600281111561308257613082614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff16151560408201526003820180546060909201916130be906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546130ea906149e2565b80156131375780601f1061310c57610100808354040283529160200191613137565b820191906000526020600020905b81548152906001019060200180831161311a57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613227906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613253906149e2565b80156132a05780601f10613275576101008083540402835291602001916132a0565b820191906000526020600020905b81548152906001019060200180831161328357829003601f168201915b5050509190925250505090525090506003816060015160048111156132c7576132c7614554565b036132fe576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160028260600151600481111561331d5761331d614554565b14801561333a5750428261014001516040015165ffffffffffff16115b15613371576040517fd63e68ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561338957613389614554565b1480156133a65750428261014001516040015165ffffffffffff16115b80156133c8575081604001516001600160a01b0316336001600160a01b031614155b156133ff576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526002602090815260408083206001600160a01b0387168452909152812080549082905590819003613461576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60048360600151600481111561347957613479614554565b146134875761348785613fa9565b815161349d906001600160a01b031685836140a2565b6040516001600160a01b0385169086907fbb50b495cfa1f9c6d8d479d4df77a080f4bed07f572d4aa3e89715f21c597da990600090a35050505050565b60008381526002602081815260408084206001600160a01b038716855282528084208151606081019092528054825260018101548594929391929184019160ff9091169081111561352d5761352d614554565b600281111561353e5761353e614554565b815260200160028201548152505090508060000151600003613564576000915050613aa6565b600085815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156135e9576135e9614554565b60048111156135fa576135fa614554565b81526020016001820160159054906101000a900460ff16600281111561362257613622614554565b600281111561363357613633614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161366f906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461369b906149e2565b80156136e85780601f106136bd576101008083540402835291602001916136e8565b820191906000526020600020905b8154815290600101906020018083116136cb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916137d8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613804906149e2565b80156138515780601f1061382657610100808354040283529160200191613851565b820191906000526020600020905b81548152906001019060200180831161383457829003601f168201915b5050509190925250505090525060408301518351919250906000906138769083614b8f565b610100840151909150600081613894670de0b6b3a764000080614fe9565b61389e9190615000565b905060006001876020015160028111156138ba576138ba614554565b146138c557816138c7565b825b905060006001886020015160028111156138e3576138e3614554565b146139085760008c815260046020908152604080832060018452909152902054613924565b60008c8152600460209081526040808320600284529091529020545b905060008a600281111561393a5761393a614554565b8960200151600281111561395057613950614554565b03613a0b5781670de0b6b3a76400006139698589614fe9565b6139739190615000565b116139ab578851670de0b6b3a76400009061398e9085614fe9565b6139989190615000565b89516139a49190614b8f565b9050613a9b565b81670de0b6b3a76400006139bf858a614fe9565b6139c99190615000565b1015613a0357670de0b6b3a76400006139e28489614fe9565b6139ec9190615000565b89516139f9908490614b8f565b6139a4919061503b565b508751613a9b565b600060018a602001516002811115613a2557613a25614554565b14613a305785613a32565b845b90506000670de0b6b3a7640000613a498386614fe9565b613a539190615000565b905060008d6002811115613a6957613a69614554565b1480613a755750808910155b15613a83578a519250613a98565b80881115613a9857613a95818961503b565b92505b50505b985050505050505050505b9392505050565b60007feeebb728eb76a15c65cd720cefd2d1d0bc97ac4e7adc73802393b2d78f8a268f826000015180519060200120836020015184604001518560600151604051602001613aff95949392919061504e565b604051602081830303815290604052805190602001209050919050565b6000613b26610f0c565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201613aff565b600080600080613b78888888886140d3565b925092509250613b8882826141a2565b50909695505050505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff166004811115613c1957613c19614554565b6004811115613c2a57613c2a614554565b81526020016001820160159054906101000a900460ff166002811115613c5257613c52614554565b6002811115613c6357613c63614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191613c9f906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613ccb906149e2565b8015613d185780601f10613ced57610100808354040283529160200191613d18565b820191906000526020600020905b815481529060010190602001808311613cfb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613e08906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613e34906149e2565b8015613e815780601f10613e5657610100808354040283529160200191613e81565b820191906000526020600020905b815481529060010190602001808311613e6457829003601f168201915b505050919092525050509052509050600381606001516004811115613ea857613ea8614554565b14613edf576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613ef0848484608001516134da565b60008581526002602090815260408083206001600160a01b03881684529091528120819055909150819003613f51576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208201515151613f6d906001600160a01b031684836140a2565b826001600160a01b0316847f9da6493a92039daf47d1f2d7a782299c5994c6323eb1e972f69c432089ec52bf83604051611f2891815260200190565b60008181526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740400000000000000000000000000000000000000001790555182917f8950be7004a37e2fd94d3fb6f4c5f4375077f766cc1f518f8651515b9ebe235491a250565b60006140366001600160a01b038416836142a6565b9050805160001415801561405b5750808060200190518101906140599190614b43565b155b1561409d576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610781565b505050565b6040516001600160a01b0383811660248301526044820183905261409d91859182169063a9059cbb90606401612f66565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561410e5750600091506003905082614198565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015614162573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661418e57506000925060019150829050614198565b9250600091508190505b9450945094915050565b60008260038111156141b6576141b6614554565b036141bf575050565b60018260038111156141d3576141d3614554565b0361420a576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561421e5761421e614554565b03614258576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b600382600381111561426c5761426c614554565b03610b78576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b6060613aa68383600084600080856001600160a01b031684866040516142cc9190615080565b60006040518083038185875af1925050503d8060008114614309576040519150601f19603f3d011682016040523d82523d6000602084013e61430e565b606091505b509150915061431e868383614328565b9695505050505050565b60608261433d576143388261439d565b613aa6565b815115801561435457506001600160a01b0384163b155b15614396576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610781565b5080613aa6565b8051156143ad5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516101608101825260008082526020820181905291810182905290606082019081526020016000815260006020820181905260408201819052606080830152608082015260a0016144606040805160c08101825260006080820181815260a08301829052825260208201819052918101829052606081019190915290565b815260408051608081018252600080825260208281018290529282015260608082015291015290565b60006020828403121561449b57600080fd5b813567ffffffffffffffff8111156144b257600080fd5b820160808185031215613aa657600080fd5b80356001600160a01b03811681146144db57600080fd5b919050565b600080604083850312156144f357600080fd5b82359150614503602084016144c4565b90509250929050565b60038110610b5957600080fd5b80356144db8161450c565b6000806040838503121561453757600080fd5b8235915060208301356145498161450c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811061459357614593614554565b9052565b848152608081016145ab6020830186614583565b60408201939093526060015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff8111828210171561460f5761460f6145bd565b60405290565b6040516080810167ffffffffffffffff8111828210171561460f5761460f6145bd565b600067ffffffffffffffff80841115614653576146536145bd565b604051601f8501601f19908116603f0116810190828211818310171561467b5761467b6145bd565b8160405280935085815286868601111561469457600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126146bf57600080fd5b613aa683833560208501614638565b803560ff811681146144db57600080fd5b600080604083850312156146f257600080fd5b82359150602083013567ffffffffffffffff8082111561471157600080fd5b9084019060e0828703121561472557600080fd5b61472d6145ec565b82358281111561473c57600080fd5b614748888286016146ae565b8252506020830135602082015261476160408401614519565b60408201526060830135606082015261477c608084016146ce565b608082015260a083013560a082015260c083013560c08201528093505050509250929050565b6000602082840312156147b457600080fd5b813567ffffffffffffffff8111156147cb57600080fd5b82016101808185031215613aa657600080fd5b6000602082840312156147f057600080fd5b5035919050565b6005811061459357614593614554565b60005b8381101561482257818101518382015260200161480a565b50506000910152565b60008151808452614843816020860160208601614807565b601f01601f19169290920160200192915050565b6001600160a01b0381511682526000602082015165ffffffffffff808216602086015280604085015116604086015250506060820151608060608501526148a1608085018261482b565b949350505050565b602081526148c86020820183516bffffffffffffffffffffffff169052565b600060208301516148e5604084018267ffffffffffffffff169052565b5060408301516001600160a01b038116606084015250606083015161490d60808401826147f7565b50608083015161492060a0840182614583565b5060a08301516001600160a01b03811660c08401525060c083015180151560e08401525060e08301516101e0610100818186015261496261020086018461482b565b9086015161012086810191909152860151805180516001600160a01b03908116610140808a01919091526020928301516101608a01529183015165ffffffffffff9081166101808a01526040840151166101a08901526060830151166101c088015291935090860151858403601f190183870152905061431e8382614857565b600181811c908216806149f657607f821691505b602082108103614a2f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215614a4757600080fd5b8135613aa68161450c565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6001600160a01b0383168152604060208201528135604082015260006020830135614aa78161450c565b614ab46060840182614583565b506040830135608083015260608301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614af457600080fd5b830160208101903567ffffffffffffffff811115614b1157600080fd5b803603821315614b2057600080fd5b608060a085015261431e60c085018284614a52565b8015158114610b5957600080fd5b600060208284031215614b5557600080fd5b8151613aa681614b35565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611f7a57611f7a614b60565b60408101614bb08285614583565b8260208301529392505050565b6001600160a01b038316815260408101613aa66020830184614583565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c0e57600080fd5b9190910192915050565b600060208284031215614c2a57600080fd5b613aa6826144c4565b803565ffffffffffff811681146144db57600080fd5b600060208284031215614c5b57600080fd5b613aa682614c33565b600060208284031215614c7657600080fd5b813567ffffffffffffffff81168114613aa657600080fd5b600060208284031215614ca057600080fd5b8135613aa681614b35565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614ce057600080fd5b83018035915067ffffffffffffffff821115614cfb57600080fd5b602001915036819003821315614d1057600080fd5b9250929050565b600081830360a0811215614d2a57600080fd5b614d32614615565b604080831215614d4157600080fd5b8051925080830183811067ffffffffffffffff82111715614d6457614d646145bd565b8152614d6f856144c4565b835260208501356020840152828252614d89818601614c33565b6020830152614d9a60608601614c33565b90820152614daa608085016144c4565b6060820152949350505050565b600060808236031215614dc957600080fd5b614dd1614615565b614dda836144c4565b8152614de860208401614c33565b6020820152614df960408401614c33565b6040820152606083013567ffffffffffffffff811115614e1857600080fd5b830136601f820112614e2957600080fd5b614e3836823560208401614638565b60608301525092915050565b601f82111561409d576000816000526020600020601f850160051c81016020861015614e6d5750805b601f850160051c820191505b81811015614e8c57828155600101614e79565b505050505050565b815167ffffffffffffffff811115614eae57614eae6145bd565b614ec281614ebc84546149e2565b84614e44565b602080601f831160018114614f155760008415614edf5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614e8c565b600085815260208120601f198616915b82811015614f4457888601518255948401946001909101908401614f25565b5085821015614f8057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b838152604060208201526000614faa604083018486614a52565b95945050505050565b8281526040602082015260006148a1604083018461482b565b600060208284031215614fde57600080fd5b8151613aa68161450c565b8082028115828204841417611f7a57611f7a614b60565b600082615036577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115611f7a57611f7a614b60565b858152602081018590526040810184905260a081016150706060830185614583565b8260808301529695505050505050565b60008251614c0e81846020870161480756fea164736f6c6343000817000a

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.