Source Code
Latest 25 from a total of 782 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Settle With Sign... | 36849836 | 52 days ago | IN | 0 ETH | 0.0000009 | ||||
| Create | 36623420 | 57 days ago | IN | 0 ETH | 0.00000699 | ||||
| Create | 36245197 | 66 days ago | IN | 0 ETH | 0.00000079 | ||||
| Join | 36070280 | 70 days ago | IN | 0 ETH | 0.00000025 | ||||
| Create | 36063092 | 70 days ago | IN | 0 ETH | 0.00000223 | ||||
| Create | 35762928 | 77 days ago | IN | 0 ETH | 0.00000173 | ||||
| Create | 35581749 | 81 days ago | IN | 0 ETH | 0.00000755 | ||||
| Settle With Sign... | 35417014 | 85 days ago | IN | 0 ETH | 0.00000027 | ||||
| Join | 35329998 | 87 days ago | IN | 0 ETH | 0.00000073 | ||||
| Create | 35329938 | 87 days ago | IN | 0 ETH | 0.00000198 | ||||
| Create | 35149593 | 91 days ago | IN | 0 ETH | 0.00000275 | ||||
| Create | 34855631 | 98 days ago | IN | 0 ETH | 0.00002449 | ||||
| Join | 34550530 | 105 days ago | IN | 0 ETH | 0.00000155 | ||||
| Create | 34547588 | 105 days ago | IN | 0 ETH | 0.00001188 | ||||
| Settle With Sign... | 34252239 | 112 days ago | IN | 0 ETH | 0.00000046 | ||||
| Settle With Sign... | 34252234 | 112 days ago | IN | 0 ETH | 0.00000046 | ||||
| Join | 34252228 | 112 days ago | IN | 0 ETH | 0.00000065 | ||||
| Create | 34250899 | 112 days ago | IN | 0 ETH | 0.00000504 | ||||
| Join | 33640233 | 126 days ago | IN | 0 ETH | 0.00000241 | ||||
| Create | 33639966 | 126 days ago | IN | 0 ETH | 0.00000469 | ||||
| Settle With Sign... | 33045070 | 140 days ago | IN | 0 ETH | 0.0000012 | ||||
| Settle With Sign... | 33045063 | 140 days ago | IN | 0 ETH | 0.00000121 | ||||
| Join | 33045031 | 140 days ago | IN | 0 ETH | 0.00000148 | ||||
| Create | 33043146 | 140 days ago | IN | 0 ETH | 0.00000381 | ||||
| Create | 32729774 | 147 days ago | IN | 0 ETH | 0.00000848 |
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
Contract Source Code (Solidity Standard Json-Input format)
// 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)));
}
}// 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);
}{
"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
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
60c060405234801561001057600080fd5b504660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6e5a829d57aafb43b4a73e4df8ca22dbd0f87728fa64ba69deb61d60ace6b92d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060830152608082019490945230818401528151808203909301835260c00190528051910120608052600160005560805160a05161509f6100de6000396000610f1001526000610fdc015261509f6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063562c880d1161008c57806387305c711161006657806387305c71146101e25780638df82800146101f5578063aeda886714610208578063c86283c81461024957600080fd5b8063562c880d146101a657806361b8ce8c146101b957806369bcdb7d146101c257600080fd5b806335f3ad7a116100c857806335f3ad7a146101555780633644e5151461017857806339842505146101805780634e6859761461019357600080fd5b8063029f1dea146100ef5780630a8d09901461010457806326e5a7af14610117575b600080fd5b6101026100fd366004614489565b61025c565b005b6101026101123660046144e0565b610b5c565b610142610125366004614524565b600460209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101686101633660046144e0565b610b7c565b60405161014c9493929190614597565b610142610f0c565b61010261018e3660046146df565b610ffe565b6101026101a13660046147a2565b61166c565b6101426101b4366004614524565b611f36565b61014260015481565b6101d56101d03660046147de565b611f80565b60405161014c91906148a9565b6101026101f03660046147de565b61228a565b6101026102033660046147de565b612817565b6102316102163660046147de565b6005602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161014c565b6101026102573660046144e0565b612edc565b610264612eee565b8035600090815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156102eb576102eb614554565b60048111156102fc576102fc614554565b81526020016001820160159054906101000a900460ff16600281111561032457610324614554565b600281111561033557610335614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610371906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461039d906149e2565b80156103ea5780601f106103bf576101008083540402835291602001916103ea565b820191906000526020600020905b8154815290600101906020018083116103cd57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916104da906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610506906149e2565b80156105535780601f1061052857610100808354040283529160200191610553565b820191906000526020600020905b81548152906001019060200180831161053657829003601f168201915b50505091909252505050905250905060018160600151600481111561057a5761057a614554565b1415801561059e575060028160600151600481111561059b5761059b614554565b14155b156105d5576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161012001516020015165ffffffffffff1611806106045750428161012001516040015165ffffffffffff16105b1561063b576040517f3fa1e77700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600161064d6040840160208501614a35565b600281111561065e5761065e614554565b1415801561068d575060026106796040840160208501614a35565b600281111561068a5761068a614554565b14155b156106c4576040517f0dfa289a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8135600090815260026020818152604080842033855290915282206001015460ff16908111156106f6576106f6614554565b60ff161115610730576040517e3b268200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160208101516040840135101561078a5780602001516040517fc155354500000000000000000000000000000000000000000000000000000000815260040161078191815260200190565b60405180910390fd5b610120820151606001516001600160a01b0316158015906108225750816101200151606001516001600160a01b0316636bf31afe33856040518363ffffffff1660e01b81526004016107dd929190614a7d565b6020604051808303816000875af11580156107fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108209190614b43565b155b15610859576040517f20815a6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561087157610871614554565b14801561089e5750600261088b6040850160208601614a35565b600281111561089c5761089c614554565b145b156108f4578235600090815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790555b8235600090815260046020908152604080832091839161091991908801908801614a35565b600281111561092a5761092a614554565b600281111561093b5761093b614554565b8152602081019190915260400160002054905060026109606040860160208701614a35565b600281111561097157610971614554565b148015610989575060a08301516001600160a01b0316155b156109ca578335600090815260036020526040902060020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b60408051606081018252908501803582526020808301916109ec918801614a35565b60028111156109fd576109fd614554565b8152602090810183905285356000908152600280835260408083203384528452909120835181559183015160018084018054929390927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691908490811115610a6857610a68614554565b021790555060409182015160029091015584356000908152600460209081528282209287018035939291610a9e91908901614a35565b6002811115610aaf57610aaf614554565b6002811115610ac057610ac0614554565b81526020019081526020016000206000828254610add9190614b8f565b90915550508151610afd906001600160a01b031633306040880135612f31565b3384357fd863744651582721a04a30bd72905fbdb34e0ab6e0397e0d9c601e730ad3e65e610b316040880160208901614a35565b8760400135604051610b44929190614ba2565b60405180910390a3505050610b596001600055565b50565b610b64612eee565b610b6e8282612fb3565b610b786001600055565b5050565b60008281526002602081815260408084206001600160a01b038681168652908352818520805460018083015492909601548988526003865284882085516101608101875281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169781019790975296870154938416948601949094529560ff91821695939490938493919290916060840191600160a01b909104166004811115610c3257610c32614554565b6004811115610c4357610c43614554565b81526020016001820160159054906101000a900460ff166002811115610c6b57610c6b614554565b6002811115610c7c57610c7c614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610cb8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce4906149e2565b8015610d315780601f10610d0657610100808354040283529160200191610d31565b820191906000526020600020905b815481529060010190602001808311610d1457829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191610e21906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4d906149e2565b8015610e9a5780601f10610e6f57610100808354040283529160200191610e9a565b820191906000526020600020905b815481529060010190602001808311610e7d57829003601f168201915b505050919092525050509052509050600381606001516004811115610ec157610ec1614554565b1480610ee25750600481606001516004811115610ee057610ee0614554565b145b15610efd57610ef6878783608001516134da565b9150610f02565b600091505b5092959194509250565b60007f00000000000000000000000000000000000000000000000000000000000000004614610fd95750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6e5a829d57aafb43b4a73e4df8ca22dbd0f87728fa64ba69deb61d60ace6b92d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b611006612eee565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561108b5761108b614554565b600481111561109c5761109c614554565b81526020016001820160159054906101000a900460ff1660028111156110c4576110c4614554565b60028111156110d5576110d5614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191611111906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461113d906149e2565b801561118a5780601f1061115f5761010080835404028352916020019161118a565b820191906000526020600020905b81548152906001019060200180831161116d57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a01000000000000000000000000000000000000000000000000000090920490911692810192909252600985018054948201949293929184019161127a906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546112a6906149e2565b80156112f35780601f106112c8576101008083540402835291602001916112f3565b820191906000526020600020905b8154815290600101906020018083116112d657829003601f168201915b5050505050815250508152505090508282602001511461133f576040517fc06789fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160600151600481111561135757611357614554565b1461138e576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff1611156113d9576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610140810151516114086113f46113ef85613aad565b613b1c565b84608001518560a001518660c00151613b66565b6001600160a01b0316816001600160a01b031614611452576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4283606001511015611490576040517fdf4cc36d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080840151600086815260036020529190912060010180548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000008360028111156114f7576114f7614554565b02179055506000600182600281111561151257611512614554565b0361152257506040830151611542565b600282600281111561153657611536614554565b03611542575060a08301515b6001600160a01b038116156115ae57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740300000000000000000000000000000000000000001790556115a98682613b94565b61161a565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167404000000000000000000000000000000000000000017905584015161160c908790612fb3565b61161a868560a00151612fb3565b826001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051611656929190614bbd565b60405180910390a350505050610b786001600055565b60208101356000036116aa576040517fd26abf5900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081013560e082013510156116f2576040517fc155354500000000000000000000000000000000000000000000000000000000815260208201356004820152602401610781565b600061170160a0830183614bda565b61170f906020810190614c18565b6001600160a01b03160361174f576040517f3a731e2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061176160a0830160808401614c18565b90506001600160a01b0381161580159061178357506001600160a01b0381163b155b156117ba576040517fed59fdca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117ca6080830160608401614c49565b65ffffffffffff166117e26060840160408501614c49565b65ffffffffffff16118061180c5750426118026080840160608501614c49565b65ffffffffffff16105b15611843576040517fde4f7e9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61185060a0830183614bda565b611861906060810190604001614c49565b65ffffffffffff1661187660a0840184614bda565b611887906040810190602001614c49565b65ffffffffffff1611806118d657506118a66060830160408401614c49565b65ffffffffffff166118bb60a0840184614bda565b6118cc906060810190604001614c49565b65ffffffffffff16105b806119055750426118ea60a0840184614bda565b6118fb906060810190604001614c49565b65ffffffffffff16105b1561193c576040517f58f2e95d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805480820182556040805160608101825260e086013581526020808201858152600085815260048352848120878252835284812054848601528581526002808452858220338352909352939093208251815592518386018054939493919290917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690879084908111156119d4576119d4614554565b0217905550604091820151600290910155805161016081019091526bffffffffffffffffffffffff8216815260208101611a1661012087016101008801614c64565b67ffffffffffffffff168152336020820152604001600181526020016000815260006020820152604001611a5261018087016101608801614c8e565b15158152602001611a6660c0870187614cab565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506101208601356020820152604001611aba36879003870187614d17565b8152602001611acc60a0870187614bda565b611ad590614db7565b9052600082815260036020908152604091829020835181549285015167ffffffffffffffff166c01000000000000000000000000027fffffffffffffffffffffffff00000000000000000000000000000000000000009384166bffffffffffffffffffffffff90921691909117178155918301516001830180546001600160a01b039092169282168317815560608501519290917fffffffffffffffffffffff0000000000000000000000000000000000000000001617600160a01b836004811115611ba357611ba3614554565b021790555060808201516001820180547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115611bfe57611bfe614554565b021790555060a082015160028201805460c08501511515600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b039093169290921791909117905560e08201516003820190611c689082614e94565b506101008201516004820155610120820151805180516005840180546001600160a01b039283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560209182015160068501558183015160078501805460408087015160609788015186166c01000000000000000000000000026bffffffffffffffffffffffff65ffffffffffff9283166601000000000000027fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909516968316969096179390931794909416919091179091556101408701518051600888018054968301519383015185167a0100000000000000000000000000000000000000000000000000000279ffffffffffffffffffffffffffffffffffffffffffffffffffff94909516600160a01b027fffffffffffff000000000000000000000000000000000000000000000000000090971691909516179490941716178155918101519091906009840190611de39082614e94565b505050600083815260046020526040812060e088013593509150846002811115611e0f57611e0f614554565b6002811115611e2057611e20614554565b81526020019081526020016000206000828254611e3d9190614b8f565b90915550506001600160a01b03831615611ec0576001600160a01b03831663edd146cc82611e6f610140880188614cab565b6040518463ffffffff1660e01b8152600401611e8d93929190614f90565b600060405180830381600087803b158015611ea757600080fd5b505af1158015611ebb573d6000803e3d6000fd5b505050505b611ee8333060e0870135611ed76020890189614c18565b6001600160a01b0316929190612f31565b336001600160a01b0316817fa91de7b3d13d8ea9fe2fcd5f0040dc4f1caed875e44595952dc2a04a2517c39c848760e00135604051611f28929190614ba2565b60405180910390a350505050565b600082815260046020526040812081836002811115611f5757611f57614554565b6002811115611f6857611f68614554565b81526020019081526020016000205490505b92915050565b611f886143df565b60008281526003602090815260409182902082516101608101845281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169281019290925260018101546001600160a01b0381169383019390935290916060830190600160a01b900460ff16600481111561200f5761200f614554565b600481111561202057612020614554565b81526020016001820160159054906101000a900460ff16600281111561204857612048614554565b600281111561205957612059614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191612095906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546120c1906149e2565b801561210e5780601f106120e35761010080835404028352916020019161210e565b820191906000526020600020905b8154815290600101906020018083116120f157829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916121fe906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461222a906149e2565b80156122775780601f1061224c57610100808354040283529160200191612277565b820191906000526020600020905b81548152906001019060200180831161225a57829003601f168201915b5050509190925250505090525092915050565b612292612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561231757612317614554565b600481111561232857612328614554565b81526020016001820160159054906101000a900460ff16600281111561235057612350614554565b600281111561236157612361614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161239d906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546123c9906149e2565b80156124165780601f106123eb57610100808354040283529160200191612416565b820191906000526020600020905b8154815290600101906020018083116123f957829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612506906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612532906149e2565b801561257f5780601f106125545761010080835404028352916020019161257f565b820191906000526020600020905b81548152906001019060200180831161256257829003601f168201915b5050505050815250508152505090508060c001516125c9576040517f67909b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816060015160048111156125e1576125e1614554565b1480612602575060048160600151600481111561260057612600614554565b145b15612639576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001516001600160a01b0316336001600160a01b03161415801561267557508060a001516001600160a01b0316336001600160a01b031614155b156126ac576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560205260409020546001600160a01b031633036126fc576040517f36d80ace00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000848152600560205291909120546001600160a01b03908116911614801561274057508060a001516001600160a01b0316336001600160a01b0316145b80612789575060a08101516000838152600560205260409020546001600160a01b039081169116148015612789575080604001516001600160a01b0316336001600160a01b0316145b1561279c5761279782613fa9565b61280c565b60008281526005602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633908117909155915191825283917f57ff98e3b14205ced980e44c40046c02eedbbdc67510b19f6c7848547a589d6c910160405180910390a25b50610b596001600055565b61281f612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156128a4576128a4614554565b60048111156128b5576128b5614554565b81526020016001820160159054906101000a900460ff1660028111156128dd576128dd614554565b60028111156128ee576128ee614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161292a906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612956906149e2565b80156129a35780601f10612978576101008083540402835291602001916129a3565b820191906000526020600020905b81548152906001019060200180831161298657829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612a93906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612abf906149e2565b8015612b0c5780601f10612ae157610100808354040283529160200191612b0c565b820191906000526020600020905b815481529060010190602001808311612aef57829003601f168201915b505050919092525050509052509050600281606001516004811115612b3357612b33614554565b14612b6a576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff161115612bb5576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61014081015180516060909101516001600160a01b0382163b600003612c07576040517faf98a96600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055517f39c2ebb90000000000000000000000000000000000000000000000000000000081526001600160a01b038416906339c2ebb990612c9b9088908690600401614fb3565b6020604051808303816000875af1158015612cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cde9190614fcc565b6002811115612cef57612cef614554565b60ff166002811115612d0357612d03614554565b6000868152600360205260409020600101805491925082917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115612d6657612d66614554565b021790555060006001826002811115612d8157612d81614554565b03612d9157506040840151612db1565b6002826002811115612da557612da5614554565b03612db1575060a08401515b6001600160a01b03811615612e1d57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055612e188682613b94565b612e89565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674040000000000000000000000000000000000000000179055850151612e7b908790612fb3565b612e89868660a00151612fb3565b836001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051612ec5929190614bbd565b60405180910390a35050505050610b596001600055565b612ee4612eee565b610b6e8282613b94565b600260005403612f2a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600055565b6040516001600160a01b038481166024830152838116604483015260648201839052612fad9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050614021565b50505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561303857613038614554565b600481111561304957613049614554565b81526020016001820160159054906101000a900460ff16600281111561307157613071614554565b600281111561308257613082614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff16151560408201526003820180546060909201916130be906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546130ea906149e2565b80156131375780601f1061310c57610100808354040283529160200191613137565b820191906000526020600020905b81548152906001019060200180831161311a57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613227906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613253906149e2565b80156132a05780601f10613275576101008083540402835291602001916132a0565b820191906000526020600020905b81548152906001019060200180831161328357829003601f168201915b5050509190925250505090525090506003816060015160048111156132c7576132c7614554565b036132fe576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160028260600151600481111561331d5761331d614554565b14801561333a5750428261014001516040015165ffffffffffff16115b15613371576040517fd63e68ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561338957613389614554565b1480156133a65750428261014001516040015165ffffffffffff16115b80156133c8575081604001516001600160a01b0316336001600160a01b031614155b156133ff576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526002602090815260408083206001600160a01b0387168452909152812080549082905590819003613461576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60048360600151600481111561347957613479614554565b146134875761348785613fa9565b815161349d906001600160a01b031685836140a2565b6040516001600160a01b0385169086907fbb50b495cfa1f9c6d8d479d4df77a080f4bed07f572d4aa3e89715f21c597da990600090a35050505050565b60008381526002602081815260408084206001600160a01b038716855282528084208151606081019092528054825260018101548594929391929184019160ff9091169081111561352d5761352d614554565b600281111561353e5761353e614554565b815260200160028201548152505090508060000151600003613564576000915050613aa6565b600085815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156135e9576135e9614554565b60048111156135fa576135fa614554565b81526020016001820160159054906101000a900460ff16600281111561362257613622614554565b600281111561363357613633614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161366f906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461369b906149e2565b80156136e85780601f106136bd576101008083540402835291602001916136e8565b820191906000526020600020905b8154815290600101906020018083116136cb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916137d8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613804906149e2565b80156138515780601f1061382657610100808354040283529160200191613851565b820191906000526020600020905b81548152906001019060200180831161383457829003601f168201915b5050509190925250505090525060408301518351919250906000906138769083614b8f565b610100840151909150600081613894670de0b6b3a764000080614fe9565b61389e9190615000565b905060006001876020015160028111156138ba576138ba614554565b146138c557816138c7565b825b905060006001886020015160028111156138e3576138e3614554565b146139085760008c815260046020908152604080832060018452909152902054613924565b60008c8152600460209081526040808320600284529091529020545b905060008a600281111561393a5761393a614554565b8960200151600281111561395057613950614554565b03613a0b5781670de0b6b3a76400006139698589614fe9565b6139739190615000565b116139ab578851670de0b6b3a76400009061398e9085614fe9565b6139989190615000565b89516139a49190614b8f565b9050613a9b565b81670de0b6b3a76400006139bf858a614fe9565b6139c99190615000565b1015613a0357670de0b6b3a76400006139e28489614fe9565b6139ec9190615000565b89516139f9908490614b8f565b6139a4919061503b565b508751613a9b565b600060018a602001516002811115613a2557613a25614554565b14613a305785613a32565b845b90506000670de0b6b3a7640000613a498386614fe9565b613a539190615000565b905060008d6002811115613a6957613a69614554565b1480613a755750808910155b15613a83578a519250613a98565b80881115613a9857613a95818961503b565b92505b50505b985050505050505050505b9392505050565b60007feeebb728eb76a15c65cd720cefd2d1d0bc97ac4e7adc73802393b2d78f8a268f826000015180519060200120836020015184604001518560600151604051602001613aff95949392919061504e565b604051602081830303815290604052805190602001209050919050565b6000613b26610f0c565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201613aff565b600080600080613b78888888886140d3565b925092509250613b8882826141a2565b50909695505050505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff166004811115613c1957613c19614554565b6004811115613c2a57613c2a614554565b81526020016001820160159054906101000a900460ff166002811115613c5257613c52614554565b6002811115613c6357613c63614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191613c9f906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613ccb906149e2565b8015613d185780601f10613ced57610100808354040283529160200191613d18565b820191906000526020600020905b815481529060010190602001808311613cfb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613e08906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613e34906149e2565b8015613e815780601f10613e5657610100808354040283529160200191613e81565b820191906000526020600020905b815481529060010190602001808311613e6457829003601f168201915b505050919092525050509052509050600381606001516004811115613ea857613ea8614554565b14613edf576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613ef0848484608001516134da565b60008581526002602090815260408083206001600160a01b03881684529091528120819055909150819003613f51576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208201515151613f6d906001600160a01b031684836140a2565b826001600160a01b0316847f9da6493a92039daf47d1f2d7a782299c5994c6323eb1e972f69c432089ec52bf83604051611f2891815260200190565b60008181526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740400000000000000000000000000000000000000001790555182917f8950be7004a37e2fd94d3fb6f4c5f4375077f766cc1f518f8651515b9ebe235491a250565b60006140366001600160a01b038416836142a6565b9050805160001415801561405b5750808060200190518101906140599190614b43565b155b1561409d576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610781565b505050565b6040516001600160a01b0383811660248301526044820183905261409d91859182169063a9059cbb90606401612f66565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561410e5750600091506003905082614198565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015614162573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661418e57506000925060019150829050614198565b9250600091508190505b9450945094915050565b60008260038111156141b6576141b6614554565b036141bf575050565b60018260038111156141d3576141d3614554565b0361420a576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561421e5761421e614554565b03614258576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b600382600381111561426c5761426c614554565b03610b78576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b6060613aa68383600084600080856001600160a01b031684866040516142cc9190615080565b60006040518083038185875af1925050503d8060008114614309576040519150601f19603f3d011682016040523d82523d6000602084013e61430e565b606091505b509150915061431e868383614328565b9695505050505050565b60608261433d576143388261439d565b613aa6565b815115801561435457506001600160a01b0384163b155b15614396576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610781565b5080613aa6565b8051156143ad5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516101608101825260008082526020820181905291810182905290606082019081526020016000815260006020820181905260408201819052606080830152608082015260a0016144606040805160c08101825260006080820181815260a08301829052825260208201819052918101829052606081019190915290565b815260408051608081018252600080825260208281018290529282015260608082015291015290565b60006020828403121561449b57600080fd5b813567ffffffffffffffff8111156144b257600080fd5b820160808185031215613aa657600080fd5b80356001600160a01b03811681146144db57600080fd5b919050565b600080604083850312156144f357600080fd5b82359150614503602084016144c4565b90509250929050565b60038110610b5957600080fd5b80356144db8161450c565b6000806040838503121561453757600080fd5b8235915060208301356145498161450c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811061459357614593614554565b9052565b848152608081016145ab6020830186614583565b60408201939093526060015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff8111828210171561460f5761460f6145bd565b60405290565b6040516080810167ffffffffffffffff8111828210171561460f5761460f6145bd565b600067ffffffffffffffff80841115614653576146536145bd565b604051601f8501601f19908116603f0116810190828211818310171561467b5761467b6145bd565b8160405280935085815286868601111561469457600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126146bf57600080fd5b613aa683833560208501614638565b803560ff811681146144db57600080fd5b600080604083850312156146f257600080fd5b82359150602083013567ffffffffffffffff8082111561471157600080fd5b9084019060e0828703121561472557600080fd5b61472d6145ec565b82358281111561473c57600080fd5b614748888286016146ae565b8252506020830135602082015261476160408401614519565b60408201526060830135606082015261477c608084016146ce565b608082015260a083013560a082015260c083013560c08201528093505050509250929050565b6000602082840312156147b457600080fd5b813567ffffffffffffffff8111156147cb57600080fd5b82016101808185031215613aa657600080fd5b6000602082840312156147f057600080fd5b5035919050565b6005811061459357614593614554565b60005b8381101561482257818101518382015260200161480a565b50506000910152565b60008151808452614843816020860160208601614807565b601f01601f19169290920160200192915050565b6001600160a01b0381511682526000602082015165ffffffffffff808216602086015280604085015116604086015250506060820151608060608501526148a1608085018261482b565b949350505050565b602081526148c86020820183516bffffffffffffffffffffffff169052565b600060208301516148e5604084018267ffffffffffffffff169052565b5060408301516001600160a01b038116606084015250606083015161490d60808401826147f7565b50608083015161492060a0840182614583565b5060a08301516001600160a01b03811660c08401525060c083015180151560e08401525060e08301516101e0610100818186015261496261020086018461482b565b9086015161012086810191909152860151805180516001600160a01b03908116610140808a01919091526020928301516101608a01529183015165ffffffffffff9081166101808a01526040840151166101a08901526060830151166101c088015291935090860151858403601f190183870152905061431e8382614857565b600181811c908216806149f657607f821691505b602082108103614a2f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215614a4757600080fd5b8135613aa68161450c565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6001600160a01b0383168152604060208201528135604082015260006020830135614aa78161450c565b614ab46060840182614583565b506040830135608083015260608301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614af457600080fd5b830160208101903567ffffffffffffffff811115614b1157600080fd5b803603821315614b2057600080fd5b608060a085015261431e60c085018284614a52565b8015158114610b5957600080fd5b600060208284031215614b5557600080fd5b8151613aa681614b35565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611f7a57611f7a614b60565b60408101614bb08285614583565b8260208301529392505050565b6001600160a01b038316815260408101613aa66020830184614583565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c0e57600080fd5b9190910192915050565b600060208284031215614c2a57600080fd5b613aa6826144c4565b803565ffffffffffff811681146144db57600080fd5b600060208284031215614c5b57600080fd5b613aa682614c33565b600060208284031215614c7657600080fd5b813567ffffffffffffffff81168114613aa657600080fd5b600060208284031215614ca057600080fd5b8135613aa681614b35565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614ce057600080fd5b83018035915067ffffffffffffffff821115614cfb57600080fd5b602001915036819003821315614d1057600080fd5b9250929050565b600081830360a0811215614d2a57600080fd5b614d32614615565b604080831215614d4157600080fd5b8051925080830183811067ffffffffffffffff82111715614d6457614d646145bd565b8152614d6f856144c4565b835260208501356020840152828252614d89818601614c33565b6020830152614d9a60608601614c33565b90820152614daa608085016144c4565b6060820152949350505050565b600060808236031215614dc957600080fd5b614dd1614615565b614dda836144c4565b8152614de860208401614c33565b6020820152614df960408401614c33565b6040820152606083013567ffffffffffffffff811115614e1857600080fd5b830136601f820112614e2957600080fd5b614e3836823560208401614638565b60608301525092915050565b601f82111561409d576000816000526020600020601f850160051c81016020861015614e6d5750805b601f850160051c820191505b81811015614e8c57828155600101614e79565b505050505050565b815167ffffffffffffffff811115614eae57614eae6145bd565b614ec281614ebc84546149e2565b84614e44565b602080601f831160018114614f155760008415614edf5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614e8c565b600085815260208120601f198616915b82811015614f4457888601518255948401946001909101908401614f25565b5085821015614f8057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b838152604060208201526000614faa604083018486614a52565b95945050505050565b8281526040602082015260006148a1604083018461482b565b600060208284031215614fde57600080fd5b8151613aa68161450c565b8082028115828204841417611f7a57611f7a614b60565b600082615036577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115611f7a57611f7a614b60565b858152602081018590526040810184905260a081016150706060830185614583565b8260808301529695505050505050565b60008251614c0e81846020870161480756fea164736f6c6343000817000a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063562c880d1161008c57806387305c711161006657806387305c71146101e25780638df82800146101f5578063aeda886714610208578063c86283c81461024957600080fd5b8063562c880d146101a657806361b8ce8c146101b957806369bcdb7d146101c257600080fd5b806335f3ad7a116100c857806335f3ad7a146101555780633644e5151461017857806339842505146101805780634e6859761461019357600080fd5b8063029f1dea146100ef5780630a8d09901461010457806326e5a7af14610117575b600080fd5b6101026100fd366004614489565b61025c565b005b6101026101123660046144e0565b610b5c565b610142610125366004614524565b600460209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101686101633660046144e0565b610b7c565b60405161014c9493929190614597565b610142610f0c565b61010261018e3660046146df565b610ffe565b6101026101a13660046147a2565b61166c565b6101426101b4366004614524565b611f36565b61014260015481565b6101d56101d03660046147de565b611f80565b60405161014c91906148a9565b6101026101f03660046147de565b61228a565b6101026102033660046147de565b612817565b6102316102163660046147de565b6005602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161014c565b6101026102573660046144e0565b612edc565b610264612eee565b8035600090815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156102eb576102eb614554565b60048111156102fc576102fc614554565b81526020016001820160159054906101000a900460ff16600281111561032457610324614554565b600281111561033557610335614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610371906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461039d906149e2565b80156103ea5780601f106103bf576101008083540402835291602001916103ea565b820191906000526020600020905b8154815290600101906020018083116103cd57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916104da906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610506906149e2565b80156105535780601f1061052857610100808354040283529160200191610553565b820191906000526020600020905b81548152906001019060200180831161053657829003601f168201915b50505091909252505050905250905060018160600151600481111561057a5761057a614554565b1415801561059e575060028160600151600481111561059b5761059b614554565b14155b156105d5576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161012001516020015165ffffffffffff1611806106045750428161012001516040015165ffffffffffff16105b1561063b576040517f3fa1e77700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600161064d6040840160208501614a35565b600281111561065e5761065e614554565b1415801561068d575060026106796040840160208501614a35565b600281111561068a5761068a614554565b14155b156106c4576040517f0dfa289a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8135600090815260026020818152604080842033855290915282206001015460ff16908111156106f6576106f6614554565b60ff161115610730576040517e3b268200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160208101516040840135101561078a5780602001516040517fc155354500000000000000000000000000000000000000000000000000000000815260040161078191815260200190565b60405180910390fd5b610120820151606001516001600160a01b0316158015906108225750816101200151606001516001600160a01b0316636bf31afe33856040518363ffffffff1660e01b81526004016107dd929190614a7d565b6020604051808303816000875af11580156107fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108209190614b43565b155b15610859576040517f20815a6000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561087157610871614554565b14801561089e5750600261088b6040850160208601614a35565b600281111561089c5761089c614554565b145b156108f4578235600090815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790555b8235600090815260046020908152604080832091839161091991908801908801614a35565b600281111561092a5761092a614554565b600281111561093b5761093b614554565b8152602081019190915260400160002054905060026109606040860160208701614a35565b600281111561097157610971614554565b148015610989575060a08301516001600160a01b0316155b156109ca578335600090815260036020526040902060020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555b60408051606081018252908501803582526020808301916109ec918801614a35565b60028111156109fd576109fd614554565b8152602090810183905285356000908152600280835260408083203384528452909120835181559183015160018084018054929390927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691908490811115610a6857610a68614554565b021790555060409182015160029091015584356000908152600460209081528282209287018035939291610a9e91908901614a35565b6002811115610aaf57610aaf614554565b6002811115610ac057610ac0614554565b81526020019081526020016000206000828254610add9190614b8f565b90915550508151610afd906001600160a01b031633306040880135612f31565b3384357fd863744651582721a04a30bd72905fbdb34e0ab6e0397e0d9c601e730ad3e65e610b316040880160208901614a35565b8760400135604051610b44929190614ba2565b60405180910390a3505050610b596001600055565b50565b610b64612eee565b610b6e8282612fb3565b610b786001600055565b5050565b60008281526002602081815260408084206001600160a01b038681168652908352818520805460018083015492909601548988526003865284882085516101608101875281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169781019790975296870154938416948601949094529560ff91821695939490938493919290916060840191600160a01b909104166004811115610c3257610c32614554565b6004811115610c4357610c43614554565b81526020016001820160159054906101000a900460ff166002811115610c6b57610c6b614554565b6002811115610c7c57610c7c614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191610cb8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce4906149e2565b8015610d315780601f10610d0657610100808354040283529160200191610d31565b820191906000526020600020905b815481529060010190602001808311610d1457829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191610e21906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4d906149e2565b8015610e9a5780601f10610e6f57610100808354040283529160200191610e9a565b820191906000526020600020905b815481529060010190602001808311610e7d57829003601f168201915b505050919092525050509052509050600381606001516004811115610ec157610ec1614554565b1480610ee25750600481606001516004811115610ee057610ee0614554565b145b15610efd57610ef6878783608001516134da565b9150610f02565b600091505b5092959194509250565b60007f00000000000000000000000000000000000000000000000000000000000021054614610fd95750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6e5a829d57aafb43b4a73e4df8ca22dbd0f87728fa64ba69deb61d60ace6b92d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f3f6f73c14b77a6d24238d37f3dce6ef87cb02d62082e16d8354dc14ccf7b348390565b611006612eee565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561108b5761108b614554565b600481111561109c5761109c614554565b81526020016001820160159054906101000a900460ff1660028111156110c4576110c4614554565b60028111156110d5576110d5614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191611111906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461113d906149e2565b801561118a5780601f1061115f5761010080835404028352916020019161118a565b820191906000526020600020905b81548152906001019060200180831161116d57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a01000000000000000000000000000000000000000000000000000090920490911692810192909252600985018054948201949293929184019161127a906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546112a6906149e2565b80156112f35780601f106112c8576101008083540402835291602001916112f3565b820191906000526020600020905b8154815290600101906020018083116112d657829003601f168201915b5050505050815250508152505090508282602001511461133f576040517fc06789fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028160600151600481111561135757611357614554565b1461138e576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff1611156113d9576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610140810151516114086113f46113ef85613aad565b613b1c565b84608001518560a001518660c00151613b66565b6001600160a01b0316816001600160a01b031614611452576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4283606001511015611490576040517fdf4cc36d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080840151600086815260036020529190912060010180548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000008360028111156114f7576114f7614554565b02179055506000600182600281111561151257611512614554565b0361152257506040830151611542565b600282600281111561153657611536614554565b03611542575060a08301515b6001600160a01b038116156115ae57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740300000000000000000000000000000000000000001790556115a98682613b94565b61161a565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167404000000000000000000000000000000000000000017905584015161160c908790612fb3565b61161a868560a00151612fb3565b826001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051611656929190614bbd565b60405180910390a350505050610b786001600055565b60208101356000036116aa576040517fd26abf5900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081013560e082013510156116f2576040517fc155354500000000000000000000000000000000000000000000000000000000815260208201356004820152602401610781565b600061170160a0830183614bda565b61170f906020810190614c18565b6001600160a01b03160361174f576040517f3a731e2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061176160a0830160808401614c18565b90506001600160a01b0381161580159061178357506001600160a01b0381163b155b156117ba576040517fed59fdca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117ca6080830160608401614c49565b65ffffffffffff166117e26060840160408501614c49565b65ffffffffffff16118061180c5750426118026080840160608501614c49565b65ffffffffffff16105b15611843576040517fde4f7e9d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61185060a0830183614bda565b611861906060810190604001614c49565b65ffffffffffff1661187660a0840184614bda565b611887906040810190602001614c49565b65ffffffffffff1611806118d657506118a66060830160408401614c49565b65ffffffffffff166118bb60a0840184614bda565b6118cc906060810190604001614c49565b65ffffffffffff16105b806119055750426118ea60a0840184614bda565b6118fb906060810190604001614c49565b65ffffffffffff16105b1561193c576040517f58f2e95d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805480820182556040805160608101825260e086013581526020808201858152600085815260048352848120878252835284812054848601528581526002808452858220338352909352939093208251815592518386018054939493919290917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690879084908111156119d4576119d4614554565b0217905550604091820151600290910155805161016081019091526bffffffffffffffffffffffff8216815260208101611a1661012087016101008801614c64565b67ffffffffffffffff168152336020820152604001600181526020016000815260006020820152604001611a5261018087016101608801614c8e565b15158152602001611a6660c0870187614cab565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506101208601356020820152604001611aba36879003870187614d17565b8152602001611acc60a0870187614bda565b611ad590614db7565b9052600082815260036020908152604091829020835181549285015167ffffffffffffffff166c01000000000000000000000000027fffffffffffffffffffffffff00000000000000000000000000000000000000009384166bffffffffffffffffffffffff90921691909117178155918301516001830180546001600160a01b039092169282168317815560608501519290917fffffffffffffffffffffff0000000000000000000000000000000000000000001617600160a01b836004811115611ba357611ba3614554565b021790555060808201516001820180547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115611bfe57611bfe614554565b021790555060a082015160028201805460c08501511515600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b039093169290921791909117905560e08201516003820190611c689082614e94565b506101008201516004820155610120820151805180516005840180546001600160a01b039283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560209182015160068501558183015160078501805460408087015160609788015186166c01000000000000000000000000026bffffffffffffffffffffffff65ffffffffffff9283166601000000000000027fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909516968316969096179390931794909416919091179091556101408701518051600888018054968301519383015185167a0100000000000000000000000000000000000000000000000000000279ffffffffffffffffffffffffffffffffffffffffffffffffffff94909516600160a01b027fffffffffffff000000000000000000000000000000000000000000000000000090971691909516179490941716178155918101519091906009840190611de39082614e94565b505050600083815260046020526040812060e088013593509150846002811115611e0f57611e0f614554565b6002811115611e2057611e20614554565b81526020019081526020016000206000828254611e3d9190614b8f565b90915550506001600160a01b03831615611ec0576001600160a01b03831663edd146cc82611e6f610140880188614cab565b6040518463ffffffff1660e01b8152600401611e8d93929190614f90565b600060405180830381600087803b158015611ea757600080fd5b505af1158015611ebb573d6000803e3d6000fd5b505050505b611ee8333060e0870135611ed76020890189614c18565b6001600160a01b0316929190612f31565b336001600160a01b0316817fa91de7b3d13d8ea9fe2fcd5f0040dc4f1caed875e44595952dc2a04a2517c39c848760e00135604051611f28929190614ba2565b60405180910390a350505050565b600082815260046020526040812081836002811115611f5757611f57614554565b6002811115611f6857611f68614554565b81526020019081526020016000205490505b92915050565b611f886143df565b60008281526003602090815260409182902082516101608101845281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169281019290925260018101546001600160a01b0381169383019390935290916060830190600160a01b900460ff16600481111561200f5761200f614554565b600481111561202057612020614554565b81526020016001820160159054906101000a900460ff16600281111561204857612048614554565b600281111561205957612059614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191612095906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546120c1906149e2565b801561210e5780601f106120e35761010080835404028352916020019161210e565b820191906000526020600020905b8154815290600101906020018083116120f157829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916121fe906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461222a906149e2565b80156122775780601f1061224c57610100808354040283529160200191612277565b820191906000526020600020905b81548152906001019060200180831161225a57829003601f168201915b5050509190925250505090525092915050565b612292612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561231757612317614554565b600481111561232857612328614554565b81526020016001820160159054906101000a900460ff16600281111561235057612350614554565b600281111561236157612361614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161239d906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546123c9906149e2565b80156124165780601f106123eb57610100808354040283529160200191612416565b820191906000526020600020905b8154815290600101906020018083116123f957829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612506906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612532906149e2565b801561257f5780601f106125545761010080835404028352916020019161257f565b820191906000526020600020905b81548152906001019060200180831161256257829003601f168201915b5050505050815250508152505090508060c001516125c9576040517f67909b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003816060015160048111156125e1576125e1614554565b1480612602575060048160600151600481111561260057612600614554565b145b15612639576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80604001516001600160a01b0316336001600160a01b03161415801561267557508060a001516001600160a01b0316336001600160a01b031614155b156126ac576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560205260409020546001600160a01b031633036126fc576040517f36d80ace00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040808201516000848152600560205291909120546001600160a01b03908116911614801561274057508060a001516001600160a01b0316336001600160a01b0316145b80612789575060a08101516000838152600560205260409020546001600160a01b039081169116148015612789575080604001516001600160a01b0316336001600160a01b0316145b1561279c5761279782613fa9565b61280c565b60008281526005602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633908117909155915191825283917f57ff98e3b14205ced980e44c40046c02eedbbdc67510b19f6c7848547a589d6c910160405180910390a25b50610b596001600055565b61281f612eee565b600081815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156128a4576128a4614554565b60048111156128b5576128b5614554565b81526020016001820160159054906101000a900460ff1660028111156128dd576128dd614554565b60028111156128ee576128ee614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161292a906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612956906149e2565b80156129a35780601f10612978576101008083540402835291602001916129a3565b820191906000526020600020905b81548152906001019060200180831161298657829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191612a93906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054612abf906149e2565b8015612b0c5780601f10612ae157610100808354040283529160200191612b0c565b820191906000526020600020905b815481529060010190602001808311612aef57829003601f168201915b505050919092525050509052509050600281606001516004811115612b3357612b33614554565b14612b6a576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b428161014001516020015165ffffffffffff161115612bb5576040517f0e470deb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61014081015180516060909101516001600160a01b0382163b600003612c07576040517faf98a96600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055517f39c2ebb90000000000000000000000000000000000000000000000000000000081526001600160a01b038416906339c2ebb990612c9b9088908690600401614fb3565b6020604051808303816000875af1158015612cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cde9190614fcc565b6002811115612cef57612cef614554565b60ff166002811115612d0357612d03614554565b6000868152600360205260409020600101805491925082917fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115612d6657612d66614554565b021790555060006001826002811115612d8157612d81614554565b03612d9157506040840151612db1565b6002826002811115612da557612da5614554565b03612db1575060a08401515b6001600160a01b03811615612e1d57600086815260036020526040902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674030000000000000000000000000000000000000000179055612e188682613b94565b612e89565b6000868152600360205260409081902060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674040000000000000000000000000000000000000000179055850151612e7b908790612fb3565b612e89868660a00151612fb3565b836001600160a01b0316867fa9878236d7197f1ae1bf20d7bd97a921ea4e5463078a71cb8ac87b6fae6877eb3385604051612ec5929190614bbd565b60405180910390a35050505050610b596001600055565b612ee4612eee565b610b6e8282613b94565b600260005403612f2a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600055565b6040516001600160a01b038481166024830152838116604483015260648201839052612fad9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050614021565b50505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff16600481111561303857613038614554565b600481111561304957613049614554565b81526020016001820160159054906101000a900460ff16600281111561307157613071614554565b600281111561308257613082614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff16151560408201526003820180546060909201916130be906149e2565b80601f01602080910402602001604051908101604052809291908181526020018280546130ea906149e2565b80156131375780601f1061310c57610100808354040283529160200191613137565b820191906000526020600020905b81548152906001019060200180831161311a57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613227906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613253906149e2565b80156132a05780601f10613275576101008083540402835291602001916132a0565b820191906000526020600020905b81548152906001019060200180831161328357829003601f168201915b5050509190925250505090525090506003816060015160048111156132c7576132c7614554565b036132fe576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208101515160028260600151600481111561331d5761331d614554565b14801561333a5750428261014001516040015165ffffffffffff16115b15613371576040517fd63e68ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018260600151600481111561338957613389614554565b1480156133a65750428261014001516040015165ffffffffffff16115b80156133c8575081604001516001600160a01b0316336001600160a01b031614155b156133ff576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526002602090815260408083206001600160a01b0387168452909152812080549082905590819003613461576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60048360600151600481111561347957613479614554565b146134875761348785613fa9565b815161349d906001600160a01b031685836140a2565b6040516001600160a01b0385169086907fbb50b495cfa1f9c6d8d479d4df77a080f4bed07f572d4aa3e89715f21c597da990600090a35050505050565b60008381526002602081815260408084206001600160a01b038716855282528084208151606081019092528054825260018101548594929391929184019160ff9091169081111561352d5761352d614554565b600281111561353e5761353e614554565b815260200160028201548152505090508060000151600003613564576000915050613aa6565b600085815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff1660048111156135e9576135e9614554565b60048111156135fa576135fa614554565b81526020016001820160159054906101000a900460ff16600281111561362257613622614554565b600281111561363357613633614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff161515604082015260038201805460609092019161366f906149e2565b80601f016020809104026020016040519081016040528092919081815260200182805461369b906149e2565b80156136e85780601f106136bd576101008083540402835291602001916136e8565b820191906000526020600020905b8154815290600101906020018083116136cb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a0100000000000000000000000000000000000000000000000000009092049091169281019290925260098501805494820194929392918401916137d8906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613804906149e2565b80156138515780601f1061382657610100808354040283529160200191613851565b820191906000526020600020905b81548152906001019060200180831161383457829003601f168201915b5050509190925250505090525060408301518351919250906000906138769083614b8f565b610100840151909150600081613894670de0b6b3a764000080614fe9565b61389e9190615000565b905060006001876020015160028111156138ba576138ba614554565b146138c557816138c7565b825b905060006001886020015160028111156138e3576138e3614554565b146139085760008c815260046020908152604080832060018452909152902054613924565b60008c8152600460209081526040808320600284529091529020545b905060008a600281111561393a5761393a614554565b8960200151600281111561395057613950614554565b03613a0b5781670de0b6b3a76400006139698589614fe9565b6139739190615000565b116139ab578851670de0b6b3a76400009061398e9085614fe9565b6139989190615000565b89516139a49190614b8f565b9050613a9b565b81670de0b6b3a76400006139bf858a614fe9565b6139c99190615000565b1015613a0357670de0b6b3a76400006139e28489614fe9565b6139ec9190615000565b89516139f9908490614b8f565b6139a4919061503b565b508751613a9b565b600060018a602001516002811115613a2557613a25614554565b14613a305785613a32565b845b90506000670de0b6b3a7640000613a498386614fe9565b613a539190615000565b905060008d6002811115613a6957613a69614554565b1480613a755750808910155b15613a83578a519250613a98565b80881115613a9857613a95818961503b565b92505b50505b985050505050505050505b9392505050565b60007feeebb728eb76a15c65cd720cefd2d1d0bc97ac4e7adc73802393b2d78f8a268f826000015180519060200120836020015184604001518560600151604051602001613aff95949392919061504e565b604051602081830303815290604052805190602001209050919050565b6000613b26610f0c565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201613aff565b600080600080613b78888888886140d3565b925092509250613b8882826141a2565b50909695505050505050565b600082815260036020908152604080832081516101608101835281546bffffffffffffffffffffffff811682526c01000000000000000000000000900467ffffffffffffffff169381019390935260018101546001600160a01b03811692840192909252906060830190600160a01b900460ff166004811115613c1957613c19614554565b6004811115613c2a57613c2a614554565b81526020016001820160159054906101000a900460ff166002811115613c5257613c52614554565b6002811115613c6357613c63614554565b815260028201546001600160a01b0381166020830152600160a01b900460ff1615156040820152600382018054606090920191613c9f906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613ccb906149e2565b8015613d185780601f10613ced57610100808354040283529160200191613d18565b820191906000526020600020905b815481529060010190602001808311613cfb57829003601f168201915b505050918352505060048201546020808301919091526040805160c08101825260058501546001600160a01b039081166080808401918252600688015460a0850152908352600787015465ffffffffffff80821685880152660100000000000082048116858701526c01000000000000000000000000909104831660608086019190915285880194909452845191820185526008880180549384168352600160a01b84048216968301969096527a010000000000000000000000000000000000000000000000000000909204909116928101929092526009850180549482019492939291840191613e08906149e2565b80601f0160208091040260200160405190810160405280929190818152602001828054613e34906149e2565b8015613e815780601f10613e5657610100808354040283529160200191613e81565b820191906000526020600020905b815481529060010190602001808311613e6457829003601f168201915b505050919092525050509052509050600381606001516004811115613ea857613ea8614554565b14613edf576040517ff525e32000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613ef0848484608001516134da565b60008581526002602090815260408083206001600160a01b03881684529091528120819055909150819003613f51576040517f2313b4b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101208201515151613f6d906001600160a01b031684836140a2565b826001600160a01b0316847f9da6493a92039daf47d1f2d7a782299c5994c6323eb1e972f69c432089ec52bf83604051611f2891815260200190565b60008181526003602052604080822060010180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740400000000000000000000000000000000000000001790555182917f8950be7004a37e2fd94d3fb6f4c5f4375077f766cc1f518f8651515b9ebe235491a250565b60006140366001600160a01b038416836142a6565b9050805160001415801561405b5750808060200190518101906140599190614b43565b155b1561409d576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610781565b505050565b6040516001600160a01b0383811660248301526044820183905261409d91859182169063a9059cbb90606401612f66565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561410e5750600091506003905082614198565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015614162573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661418e57506000925060019150829050614198565b9250600091508190505b9450945094915050565b60008260038111156141b6576141b6614554565b036141bf575050565b60018260038111156141d3576141d3614554565b0361420a576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561421e5761421e614554565b03614258576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b600382600381111561426c5761426c614554565b03610b78576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610781565b6060613aa68383600084600080856001600160a01b031684866040516142cc9190615080565b60006040518083038185875af1925050503d8060008114614309576040519150601f19603f3d011682016040523d82523d6000602084013e61430e565b606091505b509150915061431e868383614328565b9695505050505050565b60608261433d576143388261439d565b613aa6565b815115801561435457506001600160a01b0384163b155b15614396576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610781565b5080613aa6565b8051156143ad5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516101608101825260008082526020820181905291810182905290606082019081526020016000815260006020820181905260408201819052606080830152608082015260a0016144606040805160c08101825260006080820181815260a08301829052825260208201819052918101829052606081019190915290565b815260408051608081018252600080825260208281018290529282015260608082015291015290565b60006020828403121561449b57600080fd5b813567ffffffffffffffff8111156144b257600080fd5b820160808185031215613aa657600080fd5b80356001600160a01b03811681146144db57600080fd5b919050565b600080604083850312156144f357600080fd5b82359150614503602084016144c4565b90509250929050565b60038110610b5957600080fd5b80356144db8161450c565b6000806040838503121561453757600080fd5b8235915060208301356145498161450c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811061459357614593614554565b9052565b848152608081016145ab6020830186614583565b60408201939093526060015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff8111828210171561460f5761460f6145bd565b60405290565b6040516080810167ffffffffffffffff8111828210171561460f5761460f6145bd565b600067ffffffffffffffff80841115614653576146536145bd565b604051601f8501601f19908116603f0116810190828211818310171561467b5761467b6145bd565b8160405280935085815286868601111561469457600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126146bf57600080fd5b613aa683833560208501614638565b803560ff811681146144db57600080fd5b600080604083850312156146f257600080fd5b82359150602083013567ffffffffffffffff8082111561471157600080fd5b9084019060e0828703121561472557600080fd5b61472d6145ec565b82358281111561473c57600080fd5b614748888286016146ae565b8252506020830135602082015261476160408401614519565b60408201526060830135606082015261477c608084016146ce565b608082015260a083013560a082015260c083013560c08201528093505050509250929050565b6000602082840312156147b457600080fd5b813567ffffffffffffffff8111156147cb57600080fd5b82016101808185031215613aa657600080fd5b6000602082840312156147f057600080fd5b5035919050565b6005811061459357614593614554565b60005b8381101561482257818101518382015260200161480a565b50506000910152565b60008151808452614843816020860160208601614807565b601f01601f19169290920160200192915050565b6001600160a01b0381511682526000602082015165ffffffffffff808216602086015280604085015116604086015250506060820151608060608501526148a1608085018261482b565b949350505050565b602081526148c86020820183516bffffffffffffffffffffffff169052565b600060208301516148e5604084018267ffffffffffffffff169052565b5060408301516001600160a01b038116606084015250606083015161490d60808401826147f7565b50608083015161492060a0840182614583565b5060a08301516001600160a01b03811660c08401525060c083015180151560e08401525060e08301516101e0610100818186015261496261020086018461482b565b9086015161012086810191909152860151805180516001600160a01b03908116610140808a01919091526020928301516101608a01529183015165ffffffffffff9081166101808a01526040840151166101a08901526060830151166101c088015291935090860151858403601f190183870152905061431e8382614857565b600181811c908216806149f657607f821691505b602082108103614a2f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215614a4757600080fd5b8135613aa68161450c565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6001600160a01b0383168152604060208201528135604082015260006020830135614aa78161450c565b614ab46060840182614583565b506040830135608083015260608301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614af457600080fd5b830160208101903567ffffffffffffffff811115614b1157600080fd5b803603821315614b2057600080fd5b608060a085015261431e60c085018284614a52565b8015158114610b5957600080fd5b600060208284031215614b5557600080fd5b8151613aa681614b35565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611f7a57611f7a614b60565b60408101614bb08285614583565b8260208301529392505050565b6001600160a01b038316815260408101613aa66020830184614583565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c0e57600080fd5b9190910192915050565b600060208284031215614c2a57600080fd5b613aa6826144c4565b803565ffffffffffff811681146144db57600080fd5b600060208284031215614c5b57600080fd5b613aa682614c33565b600060208284031215614c7657600080fd5b813567ffffffffffffffff81168114613aa657600080fd5b600060208284031215614ca057600080fd5b8135613aa681614b35565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614ce057600080fd5b83018035915067ffffffffffffffff821115614cfb57600080fd5b602001915036819003821315614d1057600080fd5b9250929050565b600081830360a0811215614d2a57600080fd5b614d32614615565b604080831215614d4157600080fd5b8051925080830183811067ffffffffffffffff82111715614d6457614d646145bd565b8152614d6f856144c4565b835260208501356020840152828252614d89818601614c33565b6020830152614d9a60608601614c33565b90820152614daa608085016144c4565b6060820152949350505050565b600060808236031215614dc957600080fd5b614dd1614615565b614dda836144c4565b8152614de860208401614c33565b6020820152614df960408401614c33565b6040820152606083013567ffffffffffffffff811115614e1857600080fd5b830136601f820112614e2957600080fd5b614e3836823560208401614638565b60608301525092915050565b601f82111561409d576000816000526020600020601f850160051c81016020861015614e6d5750805b601f850160051c820191505b81811015614e8c57828155600101614e79565b505050505050565b815167ffffffffffffffff811115614eae57614eae6145bd565b614ec281614ebc84546149e2565b84614e44565b602080601f831160018114614f155760008415614edf5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614e8c565b600085815260208120601f198616915b82811015614f4457888601518255948401946001909101908401614f25565b5085821015614f8057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b838152604060208201526000614faa604083018486614a52565b95945050505050565b8281526040602082015260006148a1604083018461482b565b600060208284031215614fde57600080fd5b8151613aa68161450c565b8082028115828204841417611f7a57611f7a614b60565b600082615036577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115611f7a57611f7a614b60565b858152602081018590526040810184905260a081016150706060830185614583565b8260808301529695505050505050565b60008251614c0e81846020870161480756fea164736f6c6343000817000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| BASE | 100.00% | $0.999699 | 338 | $337.9 |
Loading...
Loading
Loading...
Loading
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.