Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TicketMastercopy
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 100 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Inheritance
import "./Ticket.sol";
contract TicketMastercopy is Ticket {
constructor() {
// Freeze mastercopy on deployment so it can never be initialized with real arguments
initialized = true;
}
}// 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) (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) (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) (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: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
// internal
import "../../interfaces/ISportsAMMV2Manager.sol";
import "../../interfaces/ISportsAMMV2.sol";
contract Ticket {
using SafeERC20 for IERC20;
uint private constant ONE = 1e18;
enum Phase {
Trading,
Maturity,
Expiry
}
struct MarketData {
bytes32 gameId;
uint16 sportId;
uint16 typeId;
uint maturity;
uint8 status;
int24 line;
uint24 playerId;
uint8 position;
uint odd;
ISportsAMMV2.CombinedPosition[] combinedPositions;
}
struct TicketInit {
MarketData[] _markets;
uint _buyInAmount;
uint _fees;
uint _totalQuote;
address _sportsAMM;
address _ticketOwner;
IERC20 _collateral;
uint _expiry;
bool _isLive;
uint8 _systemBetDenominator;
bool _isSGP;
}
ISportsAMMV2 public sportsAMM;
address public ticketOwner;
IERC20 public collateral;
uint public buyInAmount;
uint public fees;
uint public totalQuote;
uint public numOfMarkets;
uint public expiry;
uint public createdAt;
bool public resolved;
bool public paused;
bool public initialized;
bool public cancelled;
bool public isLive;
mapping(uint => MarketData) public markets;
uint public finalPayout;
bool public isSystem;
uint8 public systemBetDenominator;
bool public isSGP;
bool public isMarkedAsLost;
uint public expectedFinalPayout;
/* ========== CONSTRUCTOR and INITIALIZERS========== */
/// @notice initialize the ticket contract
/// @param params all parameters for Init
function initialize(TicketInit calldata params) external {
require(!initialized, "Ticket already initialized");
initialized = true;
sportsAMM = ISportsAMMV2(params._sportsAMM);
numOfMarkets = params._markets.length;
for (uint i = 0; i < numOfMarkets; i++) {
markets[i] = params._markets[i];
}
buyInAmount = params._buyInAmount;
fees = params._fees;
totalQuote = params._totalQuote;
ticketOwner = params._ticketOwner;
collateral = params._collateral;
expiry = params._expiry;
isLive = params._isLive;
createdAt = block.timestamp;
systemBetDenominator = params._systemBetDenominator;
isSystem = systemBetDenominator > 0;
isSGP = params._isSGP;
}
/**
* @notice Sets the expected final payout amount for this ticket.
* @dev
* - Can only be called by the SportsAMM contract.
* - This value represents the total amount of collateral (including fees)
* that was initially funded to the ticket upon creation.
* - Used later in `exercise()` to prevent manipulation or overfunding attacks,
* ensuring payout calculations rely only on the original committed collateral
* and not on the current token balance of the contract.
* - Once set, this value should remain constant throughout the ticket lifecycle.
*
* @param amount The total expected collateral amount that should be held by this ticket.
* Must include both user buy-in and fees.
*
* Emits a {ExpectedFinalPayoutSet} event.
*/
function setExpectedFinalPayout(uint amount) external onlyAMM {
expectedFinalPayout = amount;
emit ExpectedFinalPayoutSet(amount);
}
/* ========== EXTERNAL READ FUNCTIONS ========== */
/// @notice checks if the user lost the ticket
/// @return isTicketLost true/false
function isTicketLost() public view returns (bool) {
if (isMarkedAsLost) {
return true;
} else {
uint lostMarketsCount = 0;
for (uint i = 0; i < numOfMarkets; i++) {
(bool isMarketResolved, bool isWinningMarketPosition) = sportsAMM
.resultManager()
.isMarketResolvedAndPositionWinning(
markets[i].gameId,
markets[i].typeId,
markets[i].playerId,
markets[i].line,
markets[i].position,
markets[i].combinedPositions
);
if (isMarketResolved && !isWinningMarketPosition) {
if (!isSystem) {
return true;
} else {
lostMarketsCount++;
if (lostMarketsCount > (numOfMarkets - systemBetDenominator)) {
return true;
}
}
}
}
return false;
}
}
/// @notice checks are all markets of the ticket resolved
/// @return areAllMarketsResolved true/false
function areAllMarketsResolved() public view returns (bool) {
for (uint i = 0; i < numOfMarkets; i++) {
if (
!sportsAMM.resultManager().isMarketResolved(
markets[i].gameId,
markets[i].typeId,
markets[i].playerId,
markets[i].line,
markets[i].combinedPositions
)
) {
return false;
}
}
return true;
}
/// @notice checks if the user won the ticket
/// @return hasUserWon true/false
function isUserTheWinner() external view returns (bool hasUserWon) {
hasUserWon = _isUserTheWinner();
}
/// @notice checks if the ticket ready to be exercised
/// @return isExercisable true/false
function isTicketExercisable() public view returns (bool isExercisable) {
isExercisable = !resolved && (areAllMarketsResolved() || isTicketLost());
}
/// @notice gets current phase of the ticket
/// @return phase ticket phase
function phase() public view returns (Phase) {
return
isTicketExercisable() || resolved ? ((expiry < block.timestamp) ? Phase.Expiry : Phase.Maturity) : Phase.Trading;
}
/// @notice gets combined positions of the game
/// @return combinedPositions game combined positions
function getCombinedPositions(
uint _marketIndex
) public view returns (ISportsAMMV2.CombinedPosition[] memory combinedPositions) {
return markets[_marketIndex].combinedPositions;
}
/// @notice return the payout for this ticket
/// @return systemBetPayout the payout for this ticket
function getSystemBetPayout() external view returns (uint systemBetPayout) {
systemBetPayout = _getSystemBetPayout();
}
/* ========== EXTERNAL WRITE FUNCTIONS ========== */
/// @notice exercise ticket
function exercise(address _exerciseCollateral) external onlyAMM notPaused returns (uint) {
bool isExercisable = isTicketExercisable();
require(isExercisable, "Ticket not exercisable yet");
require(expectedFinalPayout > 0, "Expected final payout not set");
uint payoutWithFees = expectedFinalPayout;
uint payout = payoutWithFees - fees;
bool isCancelled = false;
if (_isUserTheWinner()) {
finalPayout = payout;
isCancelled = true;
for (uint i = 0; i < numOfMarkets; i++) {
bool isCancelledMarketPosition = sportsAMM.resultManager().isCancelledMarketPosition(
markets[i].gameId,
markets[i].typeId,
markets[i].playerId,
markets[i].line,
markets[i].position,
markets[i].combinedPositions
);
if (isCancelledMarketPosition) {
if (isSGP) {
isCancelled = true;
break;
}
finalPayout = (finalPayout * markets[i].odd) / ONE;
} else {
isCancelled = false;
}
}
finalPayout = isCancelled ? buyInAmount : (isSystem ? _getSystemBetPayout() : finalPayout);
collateral.safeTransfer(
_exerciseCollateral == address(0) || _exerciseCollateral == address(collateral)
? address(ticketOwner)
: address(sportsAMM),
finalPayout
);
}
// if user is lost or if the user payout was less than anticipated due to cancelled games, send the remainder to AMM
uint balance = collateral.balanceOf(address(this));
if (balance != 0) {
collateral.safeTransfer(address(sportsAMM), balance);
}
_resolve(!isTicketLost(), isCancelled);
return finalPayout;
}
/// @notice expire ticket
function expire(address _beneficiary) external onlyAMM {
require(phase() == Phase.Expiry, "Ticket not in expiry phase");
require(!resolved, "Can't expire resolved ticket");
emit Expired(_beneficiary);
_selfDestruct(_beneficiary);
}
/// @notice cancel the ticket
function cancel() external onlyAMM notPaused returns (uint) {
finalPayout = buyInAmount;
collateral.safeTransfer(address(ticketOwner), finalPayout);
uint balance = collateral.balanceOf(address(this));
if (balance != 0) {
collateral.safeTransfer(address(sportsAMM), balance);
}
_resolve(true, true);
return finalPayout;
}
/// @notice mark the ticket as lost
function markAsLost() external onlyAMM notPaused returns (uint) {
uint balance = collateral.balanceOf(address(this));
if (balance != 0) {
collateral.safeTransfer(address(sportsAMM), balance);
}
_resolve(false, false);
isMarkedAsLost = true;
return 0;
}
/// @notice withdraw collateral from the ticket
function withdrawCollateral(address recipient) external onlyAMM {
collateral.safeTransfer(recipient, collateral.balanceOf(address(this)));
}
/* ========== INTERNAL FUNCTIONS ========== */
function _resolve(bool _hasUserWon, bool _cancelled) internal {
resolved = true;
cancelled = _cancelled;
emit Resolved(_hasUserWon, _cancelled);
}
function _selfDestruct(address beneficiary) internal {
uint balance = collateral.balanceOf(address(this));
if (balance != 0) {
collateral.safeTransfer(beneficiary, balance);
}
}
function _isUserTheWinner() internal view returns (bool hasUserWon) {
if (areAllMarketsResolved()) {
hasUserWon = !isTicketLost();
}
}
/* ========== SETTERS ========== */
function setPaused(bool _paused) external {
require(msg.sender == address(sportsAMM.manager()), "Invalid sender");
if (paused == _paused) return;
paused = _paused;
emit PauseUpdated(_paused);
}
/* ========== SYSTEM BET UTILS ========== */
function _getSystemBetPayout() internal view returns (uint systemBetPayout) {
if (isSystem) {
uint8[][] memory systemCombinations = sportsAMM.riskManager().generateCombinations(
uint8(numOfMarkets),
systemBetDenominator
);
uint totalCombinations = systemCombinations.length;
uint buyinPerCombination = ((buyInAmount * ONE) / totalCombinations) / ONE;
bool[] memory winningMarkets = new bool[](numOfMarkets);
bool[] memory cancelledMarkets = new bool[](numOfMarkets);
for (uint i = 0; i < numOfMarkets; i++) {
if (
!sportsAMM.resultManager().isMarketResolved(
markets[i].gameId,
markets[i].typeId,
markets[i].playerId,
markets[i].line,
markets[i].combinedPositions
)
) {
return 0;
}
winningMarkets[i] = sportsAMM.resultManager().isWinningMarketPosition(
markets[i].gameId,
markets[i].typeId,
markets[i].playerId,
markets[i].line,
markets[i].position,
markets[i].combinedPositions
);
cancelledMarkets[i] = sportsAMM.resultManager().isCancelledMarketPosition(
markets[i].gameId,
markets[i].typeId,
markets[i].playerId,
markets[i].line,
markets[i].position,
markets[i].combinedPositions
);
}
// Loop through each stored combination
for (uint i = 0; i < totalCombinations; i++) {
uint8[] memory currentCombination = systemCombinations[i];
uint combinationQuote = ONE;
for (uint j = 0; j < currentCombination.length; j++) {
uint8 marketIndex = currentCombination[j];
if (winningMarkets[marketIndex]) {
if (!cancelledMarkets[marketIndex]) {
combinationQuote = (combinationQuote * markets[marketIndex].odd) / ONE;
}
} else {
combinationQuote = 0;
break;
}
}
if (combinationQuote > 0) {
uint combinationPayout = (buyinPerCombination * ONE) / combinationQuote;
systemBetPayout += combinationPayout;
}
}
uint maxPayout = (buyInAmount * ONE) / totalQuote;
if (systemBetPayout > maxPayout) {
systemBetPayout = maxPayout;
}
}
}
/* ========== MODIFIERS ========== */
modifier onlyAMM() {
require(msg.sender == address(sportsAMM), "Only the AMM may perform these methods");
_;
}
modifier notPaused() {
require(!paused, "Market paused");
_;
}
/* ========== EVENTS ========== */
event Resolved(bool isUserTheWinner, bool cancelled);
event Expired(address beneficiary);
event PauseUpdated(bool paused);
event ExpectedFinalPayoutSet(uint amount);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IProxyBetting.sol";
interface IFreeBetsHolder is IProxyBetting {
function confirmLiveTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount, address _collateral) external;
function confirmSGPTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount, address _collateral) external;
function balancePerUserAndCollateral(address user, address collateral) external view returns (uint);
function freeBetExpiration(address user, address collateral) external view returns (uint);
function freeBetExpirationUpgrade() external view returns (uint);
function freeBetExpirationPeriod() external view returns (uint);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IProxyBetting {
function getActiveTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfActiveTicketsPerUser(address _user) external view returns (uint);
function getResolvedTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfResolvedTicketsPerUser(address _user) external view returns (uint);
function confirmTicketResolved(address _resolvedTicket) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/ISportsAMMV2Manager.sol";
import "../interfaces/ISportsAMMV2ResultManager.sol";
import "../interfaces/ISportsAMMV2RiskManager.sol";
import "../interfaces/ISportsAMMV2Manager.sol";
import "../interfaces/IFreeBetsHolder.sol";
import "../interfaces/IStakingThalesBettingProxy.sol";
interface ISportsAMMV2 {
enum TicketAction {
Exercise,
Cancel,
MarkLost
}
struct CombinedPosition {
uint16 typeId;
uint8 position;
int24 line;
}
struct TradeData {
bytes32 gameId;
uint16 sportId;
uint16 typeId;
uint maturity;
uint8 status;
int24 line;
uint24 playerId;
uint[] odds;
bytes32[] merkleProof;
uint8 position;
CombinedPosition[][] combinedPositions;
}
function defaultCollateral() external view returns (IERC20);
function manager() external view returns (ISportsAMMV2Manager);
function resultManager() external view returns (ISportsAMMV2ResultManager);
function safeBoxFee() external view returns (uint);
function handleTicketResolving(address _ticket, ISportsAMMV2.TicketAction action) external;
function riskManager() external view returns (ISportsAMMV2RiskManager);
function freeBetsHolder() external view returns (IFreeBetsHolder);
function stakingThalesBettingProxy() external view returns (IStakingThalesBettingProxy);
function tradeLive(
TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _expectedQuote,
address _recipient,
address _referrer,
address _collateral
) external returns (address _createdTicket);
function trade(
TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _expectedQuote,
uint _additionalSlippage,
address _referrer,
address _collateral,
bool _isEth
) external returns (address _createdTicket);
function tradeSystemBet(
TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _expectedQuote,
uint _additionalSlippage,
address _referrer,
address _collateral,
bool _isEth,
uint8 _systemBetDenominator
) external returns (address _createdTicket);
function tradeSGP(
ISportsAMMV2.TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _approvedQuote,
address _recipient,
address _referrer,
address _collateral
) external returns (address _createdTicket);
function rootPerGame(bytes32 game) external view returns (bytes32);
function getRootsPerGames(bytes32[] calldata _games) external view returns (bytes32[] memory _roots);
function paused() external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./ISportsAMMV2.sol";
interface ISportsAMMV2Manager {
enum Role {
ROOT_SETTING,
RISK_MANAGING,
MARKET_RESOLVING,
TICKET_PAUSER
}
function isWhitelistedAddress(address _address, Role role) external view returns (bool);
function decimals() external view returns (uint);
function feeToken() external view returns (address);
function isActiveTicket(address _ticket) external view returns (bool);
function getActiveTickets(uint _index, uint _pageSize) external view returns (address[] memory);
function numOfActiveTickets() external view returns (uint);
function getActiveTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfActiveTicketsPerUser(address _user) external view returns (uint);
function getResolvedTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfResolvedTicketsPerUser(address _user) external view returns (uint);
function getTicketsPerGame(uint _index, uint _pageSize, bytes32 _gameId) external view returns (address[] memory);
function numOfTicketsPerGame(bytes32 _gameId) external view returns (uint);
function isKnownTicket(address _ticket) external view returns (bool);
function sportsAMM() external view returns (address);
function getTicketsPerMarket(
uint _index,
uint _pageSize,
bytes32 _gameId,
uint _typeId,
uint _playerId
) external view returns (address[] memory);
function numOfTicketsPerMarket(bytes32 _gameId, uint _typeId, uint _playerId) external view returns (uint);
function addNewKnownTicket(ISportsAMMV2.TradeData[] memory _tradeData, address ticket, address user) external;
function resolveKnownTicket(address ticket, address ticketOwner) external;
function expireKnownTicket(address ticket, address ticketOwner) external;
function isSystemTicket(address _ticket) external view returns (bool);
function isSGPTicket(address _ticket) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ISportsAMMV2.sol";
interface ISportsAMMV2ResultManager {
enum MarketPositionStatus {
Open,
Cancelled,
Winning,
Losing
}
function isMarketResolved(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
ISportsAMMV2.CombinedPosition[] memory combinedPositions
) external view returns (bool isResolved);
function getMarketPositionStatus(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (MarketPositionStatus status);
function isWinningMarketPosition(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (bool isWinning);
function isCancelledMarketPosition(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (bool isCancelled);
function getResultsPerMarket(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId
) external view returns (int24[] memory results);
function resultTypePerMarketType(uint _typeId) external view returns (uint8 marketType);
function isMarketResolvedAndPositionWinning(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (bool isResolved, bool isWinning);
function setResultsPerMarkets(
bytes32[] memory _gameIds,
uint16[] memory _typeIds,
uint24[] memory _playerIds,
int24[][] memory _results
) external;
function isGameCancelled(bytes32 _gameId) external view returns (bool);
function cancelGames(bytes32[] memory _gameIds) external;
function cancelMarkets(
bytes32[] memory _gameIds,
uint16[] memory _typeIds,
uint24[] memory _playerIds,
int24[] memory _lines
) external;
function cancelMarket(bytes32 _gameId, uint16 _typeId, uint24 _playerId, int24 _line) external;
function cancelGame(bytes32 _gameId) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./ISportsAMMV2.sol";
interface ISportsAMMV2RiskManager {
struct TypeCap {
uint typeId;
uint cap;
}
struct CapData {
uint capPerSport;
uint capPerChild;
TypeCap[] capPerType;
}
struct DynamicLiquidityData {
uint cutoffTimePerSport;
uint cutoffDividerPerSport;
}
struct RiskData {
uint sportId;
CapData capData;
uint riskMultiplierPerSport;
DynamicLiquidityData dynamicLiquidityData;
}
enum RiskStatus {
NoRisk,
OutOfLiquidity,
InvalidCombination
}
function minBuyInAmount() external view returns (uint);
function maxTicketSize() external view returns (uint);
function maxSupportedAmount() external view returns (uint);
function maxSupportedOdds() external view returns (uint);
function maxAllowedSystemCombinations() external view returns (uint);
function expiryDuration() external view returns (uint);
function liveTradingPerSportAndTypeEnabled(uint _sportId, uint _typeId) external view returns (bool _enabled);
function calculateCapToBeUsed(
bytes32 _gameId,
uint16 _sportId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _maturity,
bool _isLive
) external view returns (uint cap);
function calculateTotalRiskOnGame(
bytes32 _gameId,
uint16 _sportId,
uint _maturity
) external view returns (uint totalRisk);
function checkRisks(
ISportsAMMV2.TradeData[] memory _tradeData,
uint _buyInAmount,
bool _isLive,
uint8 _systemBetDenominator
) external view returns (ISportsAMMV2RiskManager.RiskStatus riskStatus, bool[] memory isMarketOutOfLiquidity);
function checkLimits(
uint _buyInAmount,
uint _totalQuote,
uint _payout,
uint _expectedPayout,
uint _additionalSlippage,
uint _ticketSize
) external view;
function spentOnGame(bytes32 _gameId) external view returns (uint);
function riskPerMarketTypeAndPosition(
bytes32 _gameId,
uint _typeId,
uint _playerId,
uint _position
) external view returns (int);
function checkAndUpdateRisks(
ISportsAMMV2.TradeData[] memory _tradeData,
uint _buyInAmount,
uint _payout,
bool _isLive,
uint8 _systemBetDenominator,
bool _isSGP
) external;
function verifyMerkleTree(ISportsAMMV2.TradeData memory _marketTradeData, bytes32 _rootPerGame) external pure;
function batchVerifyMerkleTree(
ISportsAMMV2.TradeData[] memory _marketTradeData,
bytes32[] memory _rootPerGame
) external pure;
function isSportIdFuture(uint16 _sportsId) external view returns (bool);
function sgpOnSportIdEnabled(uint16 _sportsId) external view returns (bool);
function getMaxSystemBetPayout(
ISportsAMMV2.TradeData[] memory _tradeData,
uint8 _systemBetDenominator,
uint _buyInAmount,
uint _addedPayoutPercentage
) external view returns (uint systemBetPayout, uint systemBetQuote);
function generateCombinations(uint8 n, uint8 k) external pure returns (uint8[][] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IProxyBetting.sol";
interface IStakingThalesBettingProxy is IProxyBetting {
function preConfirmLiveTrade(bytes32 requestId, uint _buyInAmount) external;
function confirmLiveTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount) external;
function preConfirmSGPTrade(bytes32 requestId, uint _buyInAmount) external;
function confirmSGPTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount) external;
}{
"optimizer": {
"enabled": true,
"runs": 100
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExpectedFinalPayoutSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"}],"name":"Expired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PauseUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isUserTheWinner","type":"bool"},{"indexed":false,"internalType":"bool","name":"cancelled","type":"bool"}],"name":"Resolved","type":"event"},{"inputs":[],"name":"areAllMarketsResolved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyInAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createdAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_exerciseCollateral","type":"address"}],"name":"exercise","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expectedFinalPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"}],"name":"expire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finalPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketIndex","type":"uint256"}],"name":"getCombinedPositions","outputs":[{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[]","name":"combinedPositions","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSystemBetPayout","outputs":[{"internalType":"uint256","name":"systemBetPayout","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"uint256","name":"odd","type":"uint256"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[]","name":"combinedPositions","type":"tuple[]"}],"internalType":"struct Ticket.MarketData[]","name":"_markets","type":"tuple[]"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_fees","type":"uint256"},{"internalType":"uint256","name":"_totalQuote","type":"uint256"},{"internalType":"address","name":"_sportsAMM","type":"address"},{"internalType":"address","name":"_ticketOwner","type":"address"},{"internalType":"contract IERC20","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"},{"internalType":"bool","name":"_isLive","type":"bool"},{"internalType":"uint8","name":"_systemBetDenominator","type":"uint8"},{"internalType":"bool","name":"_isSGP","type":"bool"}],"internalType":"struct Ticket.TicketInit","name":"params","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMarkedAsLost","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSGP","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSystem","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTicketExercisable","outputs":[{"internalType":"bool","name":"isExercisable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTicketLost","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isUserTheWinner","outputs":[{"internalType":"bool","name":"hasUserWon","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"markAsLost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"markets","outputs":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"uint256","name":"odd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numOfMarkets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"phase","outputs":[{"internalType":"enum Ticket.Phase","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resolved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setExpectedFinalPayout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sportsAMM","outputs":[{"internalType":"contract ISportsAMMV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"systemBetDenominator","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticketOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506009805462ff0000191662010000179055612889806100316000396000f3fe608060405234801561001057600080fd5b50600436106101db5760003560e01c8063928d300e11610105578063c8db233e1161009d578063c8db233e1461046b578063c99252881461047e578063cf09e0d014610491578063d165dac21461049a578063d8dfeb45146104a3578063e184c9be146104b6578063e74d3c47146104bf578063ea8a1af0146104c7578063eef8889b146104cf57600080fd5b8063928d300e1461030c5780639a82a09a1461031f5780639af1d35a14610333578063b0c56f051461033c578063b1283e7714610344578063b1c9fe6e1461040f578063b5ac8d9814610424578063b8f7a66514610437578063c358c6961461044b57600080fd5b80633356a35a116101785780633356a35a146102a15780633f6fa655146102a9578063400e69ef146102b65780634652e330146102bf5780635c975abb146102cc57806362e5c819146102de5780636a265aa9146102e75780637e2480d2146102ef57806384b124ab1461030357600080fd5b8062641e8b146101e0578063085d03ee1461020957806309d28f7914610221578063158ef93e1461023757806316c38b3c1461024a5780631b15982a1461025f5780631c98697914610272578063242a8a6b14610285578063242c6c2d1461028e575b600080fd5b6001546101f3906001600160a01b031681565b6040516102009190611f6c565b60405180910390f35b6102116104f3565b6040519015158152602001610200565b6102296106c4565b604051908152602001610200565b6009546102119062010000900460ff1681565b61025d610258366004611f8e565b6106d3565b005b61022961026d366004611fc0565b61080f565b600c546102119062010000900460ff1681565b610229600b5481565b61025d61029c366004611fdd565b610c2d565b610211610c8c565b6009546102119060ff1681565b61022960055481565b600c546102119060ff1681565b60095461021190610100900460ff1681565b61022960065481565b610229610c96565b600c54610211906301000000900460ff1681565b610229600d5481565b61025d61031a366004611fc0565b610da5565b600954610211906301000000900460ff1681565b61022960045481565b610211610e5c565b6103b7610352366004611fdd565b600a602052600090815260409020805460018201546002808401546003850154600490950154939461ffff80851695620100009095041693919260ff80831693610100840490920b9262ffffff600160201b82041692600160381b9091049091169089565b60408051998a5261ffff98891660208b01529690971695880195909552606087019390935260ff918216608087015260020b60a086015262ffffff90911660c08501521660e083015261010082015261012001610200565b610417610fb6565b604051610200919061200c565b61025d610432366004612034565b610fec565b60095461021190600160201b900460ff1681565b61045e610459366004611fdd565b611222565b604051610200919061206f565b61025d610479366004611fc0565b6112b6565b6000546101f3906001600160a01b031681565b61022960085481565b61022960035481565b6002546101f3906001600160a01b031681565b61022960075481565b6102116113db565b610229611402565b600c546104e190610100900460ff1681565b60405160ff9091168152602001610200565b600c546000906301000000900460ff161561050e5750600190565b6000805b6006548110156106b8576000805460408051638ff9d5cf60e01b8152905183926001600160a01b031691638ff9d5cf9160048083019260209291908290030181865afa158015610566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058a91906120d2565b6000848152600a6020526040908190208054600182015460038301549351631334a14160e31b81526001600160a01b0395909516946399a50a0894610602946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b6040805180830381865afa15801561061e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106429190612199565b91509150818015610651575080155b156106a357600c5460ff1661066b57600194505050505090565b83610675816121e9565b600c546006549196506106919250610100900460ff1690612202565b8411156106a357600194505050505090565b505080806106b0906121e9565b915050610512565b50600091505090565b90565b60006106ce611527565b905090565b60008054906101000a90046001600160a01b03166001600160a01b031663481c6a756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610724573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074891906120d2565b6001600160a01b0316336001600160a01b03161461079e5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b60448201526064015b60405180910390fd5b801515600960019054906101000a900460ff161515036107bb5750565b600980548215156101000261ff00199091161790556040517f77860e247ab9186dbe64e5bd0e0b93273cc4273e01818420e788f500078886f59061080490831515815260200190565b60405180910390a150565b600080546001600160a01b0316331461083a5760405162461bcd60e51b815260040161079590612215565b600954610100900460ff16156108625760405162461bcd60e51b81526004016107959061225b565b600061086c6113db565b9050806108bb5760405162461bcd60e51b815260206004820152601a60248201527f5469636b6574206e6f74206578657263697361626c65207965740000000000006044820152606401610795565b6000600d541161090d5760405162461bcd60e51b815260206004820152601d60248201527f45787065637465642066696e616c207061796f7574206e6f74207365740000006044820152606401610795565b600d546004546000906109209083612202565b9050600061092c611c70565b15610b765750600b819055600160005b600654811015610aec5760008060009054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561099a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109be91906120d2565b6000838152600a60205260409081902080546001820154600383015493516371752fa560e01b81526001600160a01b0395909516946371752fa594610a36946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b602060405180830381865afa158015610a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a779190612282565b90508015610ad457600c5462010000900460ff1615610a9a576001925050610aec565b6000828152600a6020526040902060040154600b54670de0b6b3a764000091610ac29161229f565b610acc91906122b6565b600b55610ad9565b600092505b5080610ae4816121e9565b91505061093c565b5080610b1157600c5460ff16610b0457600b54610b15565b610b0c611527565b610b15565b6003545b600b55610b766001600160a01b0387161580610b3e57506002546001600160a01b038881169116145b610b53576000546001600160a01b0316610b60565b6001546001600160a01b03165b600b546002546001600160a01b03169190611c8d565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190610ba7903090600401611f6c565b602060405180830381865afa158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be891906122d8565b90508015610c0d57600054600254610c0d916001600160a01b03918216911683611c8d565b610c1f610c186104f3565b1583611ce4565b5050600b5495945050505050565b6000546001600160a01b03163314610c575760405162461bcd60e51b815260040161079590612215565b600d8190556040518181527f660dbcbc304d174b408928860802fceee5965601ce687ed10cc25b2db9b552a290602001610804565b60006106ce611c70565b600080546001600160a01b03163314610cc15760405162461bcd60e51b815260040161079590612215565b600954610100900460ff1615610ce95760405162461bcd60e51b81526004016107959061225b565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190610d1a903090600401611f6c565b602060405180830381865afa158015610d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5b91906122d8565b90508015610d8057600054600254610d80916001600160a01b03918216911683611c8d565b610d8b600080611ce4565b5050600c805463ff00000019166301000000179055600090565b6000546001600160a01b03163314610dcf5760405162461bcd60e51b815260040161079590612215565b6002546040516370a0823160e01b8152610e599183916001600160a01b03909116906370a0823190610e05903090600401611f6c565b602060405180830381865afa158015610e22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4691906122d8565b6002546001600160a01b03169190611c8d565b50565b6000805b600654811015610fae5760008054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf91906120d2565b6000828152600a602052604090819020805460018201546003830154935163397f782360e01b81526001600160a01b03959095169463397f782394610f4f946201000090930461ffff1692600160201b820462ffffff169261010090920460020b916005909101906004016122f1565b602060405180830381865afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f909190612282565b610f9c57600091505090565b80610fa6816121e9565b915050610e60565b506001905090565b6000610fc06113db565b80610fcd575060095460ff165b610fd75750600090565b4260075410610fe65750600190565b50600290565b60095462010000900460ff16156110455760405162461bcd60e51b815260206004820152601a60248201527f5469636b657420616c726561647920696e697469616c697a65640000000000006044820152606401610795565b6009805462ff000019166201000017905561106660a0820160808301611fc0565b600080546001600160a01b0319166001600160a01b03929092169190911790556110908180612333565b6006555060005b6006548110156110fa576110ab8280612333565b828181106110bb576110bb612383565b90506020028101906110cd9190612399565b6000828152600a602052604090206110e58282612566565b508190506110f2816121e9565b915050611097565b5060208101356003556040810135600455606081013560055561112360c0820160a08301611fc0565b600180546001600160a01b0319166001600160a01b039290921691909117905561115360e0820160c08301611fc0565b600280546001600160a01b0319166001600160a01b039290921691909117905560e081013560075561118d61012082016101008301611f8e565b60098054911515600160201b0264ff0000000019909216919091179055426008556111c06101408201610120830161268a565b600c805460ff1960ff93841661010090810291821661ffff1984161761ff00199093169190911704909216151591909117905561120561016082016101408301611f8e565b600c8054911515620100000262ff00001990921691909117905550565b6060600a6000838152602001908152602001600020600501805480602002602001604051908101604052809291908181526020016000905b828210156112ab576000848152602090819020604080516060810182529185015461ffff8116835260ff62010000820416838501526301000000900460020b9082015282526001909201910161125a565b505050509050919050565b6000546001600160a01b031633146112e05760405162461bcd60e51b815260040161079590612215565b60026112ea610fb6565b60028111156112fb576112fb611ff6565b146113485760405162461bcd60e51b815260206004820152601a60248201527f5469636b6574206e6f7420696e206578706972792070686173650000000000006044820152606401610795565b60095460ff161561139b5760405162461bcd60e51b815260206004820152601c60248201527f43616e277420657870697265207265736f6c766564207469636b6574000000006044820152606401610795565b7fd5669ebe8b90ed693033f1915dcea031e7a16a6f146a8326c02eec10eed77edd816040516113ca9190611f6c565b60405180910390a1610e5981611d4b565b60095460009060ff161580156106ce57506113f4610e5c565b806106ce57506106ce6104f3565b600080546001600160a01b0316331461142d5760405162461bcd60e51b815260040161079590612215565b600954610100900460ff16156114555760405162461bcd60e51b81526004016107959061225b565b600354600b81905560015460025461147d926001600160a01b03918216929190911690611c8d565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906114ae903090600401611f6c565b602060405180830381865afa1580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef91906122d8565b9050801561151457600054600254611514916001600160a01b03918216911683611c8d565b61151f600180611ce4565b5050600b5490565b600c5460009060ff16156106c15760008060009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa158015611589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ad91906120d2565b600654600c546040516305007e4d60e21b815260ff928316600482015261010090910490911660248201526001600160a01b039190911690631401f93490604401600060405180830381865afa15801561160b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261163391908101906126fa565b90506000815190506000670de0b6b3a764000082670de0b6b3a764000060035461165d919061229f565b61166791906122b6565b61167191906122b6565b905060006006546001600160401b0381111561168f5761168f61245a565b6040519080825280602002602001820160405280156116b8578160200160208202803683370190505b50905060006006546001600160401b038111156116d7576116d761245a565b604051908082528060200260200182016040528015611700578160200160208202803683370190505b50905060005b600654811015611aeb5760008054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611761573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178591906120d2565b6000828152600a602052604090819020805460018201546003830154935163397f782360e01b81526001600160a01b03959095169463397f7823946117f5946201000090930461ffff1692600160201b820462ffffff169261010090920460020b916005909101906004016122f1565b602060405180830381865afa158015611812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118369190612282565b611847576000965050505050505090565b60008054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611898573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bc91906120d2565b6000828152600a60205260409081902080546001820154600383015493516376d0508160e01b81526001600160a01b0395909516946376d0508194611934946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b602060405180830381865afa158015611951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119759190612282565b83828151811061198757611987612383565b91151560209283029190910182015260005460408051638ff9d5cf60e01b815290516001600160a01b0390921692638ff9d5cf926004808401938290030181865afa1580156119da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fe91906120d2565b6000828152600a60205260409081902080546001820154600383015493516371752fa560e01b81526001600160a01b0395909516946371752fa594611a76946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b602060405180830381865afa158015611a93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab79190612282565b828281518110611ac957611ac9612383565b9115156020928302919091019091015280611ae3816121e9565b915050611706565b5060005b84811015611c33576000868281518110611b0b57611b0b612383565b602002602001015190506000670de0b6b3a7640000905060005b8251811015611be8576000838281518110611b4257611b42612383565b60200260200101519050868160ff1681518110611b6157611b61612383565b602002602001015115611bcb57858160ff1681518110611b8357611b83612383565b6020026020010151611bc65760ff81166000908152600a6020526040902060040154670de0b6b3a764000090611bb9908561229f565b611bc391906122b6565b92505b611bd5565b6000925050611be8565b5080611be0816121e9565b915050611b25565b508015611c1e57600081611c04670de0b6b3a76400008961229f565b611c0e91906122b6565b9050611c1a818b612811565b9950505b50508080611c2b906121e9565b915050611aef565b506000600554670de0b6b3a7640000600354611c4f919061229f565b611c5991906122b6565b905080871115611c67578096505b50505050505090565b6000611c7a610e5c565b156106c157611c876104f3565b15905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611cdf908490611de0565b505050565b6009805482151563010000000263ff0000ff199091161760011790556040517f402533440ea6dbf4c9e96f4c7a180525f93b7972a76e0a007c14c379f81bef5a90611d3f908490849091151582521515602082015260400190565b60405180910390a15050565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d7c903090600401611f6c565b602060405180830381865afa158015611d99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbd91906122d8565b90508015611ddc57600254611ddc906001600160a01b03168383611c8d565b5050565b6000611df56001600160a01b03841683611e3a565b90508051600014158015611e1a575080806020019051810190611e189190612282565b155b15611cdf5782604051635274afe760e01b81526004016107959190611f6c565b6060611e4883836000611e51565b90505b92915050565b606081471015611e76573060405163cd78605960e01b81526004016107959190611f6c565b600080856001600160a01b03168486604051611e929190612824565b60006040518083038185875af1925050503d8060008114611ecf576040519150601f19603f3d011682016040523d82523d6000602084013e611ed4565b606091505b5091509150611ee4868383611ef0565b925050505b9392505050565b606082611f0557611f0082611f43565b611ee9565b8151158015611f1c57506001600160a01b0384163b155b15611f3c5783604051639996b31560e01b81526004016107959190611f6c565b5080611ee9565b805115611f535780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0391909116815260200190565b8015158114610e5957600080fd5b600060208284031215611fa057600080fd5b8135611ee981611f80565b6001600160a01b0381168114610e5957600080fd5b600060208284031215611fd257600080fd5b8135611ee981611fab565b600060208284031215611fef57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b602081016003831061202e57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121561204657600080fd5b81356001600160401b0381111561205c57600080fd5b82016101608185031215611ee957600080fd5b602080825282518282018190526000919060409081850190868401855b828110156120c5578151805161ffff1685528681015160ff168786015285015160020b858501526060909301929085019060010161208c565b5091979650505050505050565b6000602082840312156120e457600080fd5b8151611ee981611fab565b6000815480845260208085019450836000528060002060005b8381101561214257815461ffff81168852601081901c60ff168489015260181c60020b604088015260609096019560019182019101612108565b509495945050505050565b86815261ffff8616602082015262ffffff851660408201528360020b606082015260ff8316608082015260c060a0820152600061218d60c08301846120ef565b98975050505050505050565b600080604083850312156121ac57600080fd5b82516121b781611f80565b60208401519092506121c881611f80565b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b6000600182016121fb576121fb6121d3565b5060010190565b81810381811115611e4b57611e4b6121d3565b60208082526026908201527f4f6e6c792074686520414d4d206d617920706572666f726d207468657365206d6040820152656574686f647360d01b606082015260800190565b6020808252600d908201526c13585c9ad95d081c185d5cd959609a1b604082015260600190565b60006020828403121561229457600080fd5b8151611ee981611f80565b8082028115828204841417611e4b57611e4b6121d3565b6000826122d357634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156122ea57600080fd5b5051919050565b85815261ffff8516602082015262ffffff841660408201528260020b606082015260a06080820152600061232860a08301846120ef565b979650505050505050565b6000808335601e1984360301811261234a57600080fd5b8301803591506001600160401b0382111561236457600080fd5b6020019150600581901b360382131561237c57600080fd5b9250929050565b634e487b7160e01b600052603260045260246000fd5b6000823561013e198336030181126123b057600080fd5b9190910192915050565b6000813561ffff81168114611e4b57600080fd5b60ff81168114610e5957600080fd5b60008135611e4b816123ce565b600081358060020b8114611e4b57600080fd5b6000813562ffffff81168114611e4b57600080fd5b6000808335601e1984360301811261242957600080fd5b8301803591506001600160401b0382111561244357600080fd5b602001915060608102360382131561237c57600080fd5b634e487b7160e01b600052604160045260246000fd5b61248f61247c836123ba565b825461ffff191661ffff91909116178255565b602082013561249d816123ce565b815462ff00008260101b1691508162ff00001982161783556124c1604085016123ea565b60181b65ffffff000000168265ffffffff00001983161717835550505050565b600160401b8311156124f5576124f561245a565b80548382558084101561252c576000828152602081208581019083015b8082101561252857828255600182019150612512565b5050505b5060008181526020812083915b8581101561255e5761254b8383612470565b6060929092019160019182019101612539565b505050505050565b813581556001810161257d61247c602085016123ba565b6125a661258c604085016123ba565b825463ffff0000191660109190911b63ffff000016178255565b5060608201356002820155600381016125d56125c4608085016123dd565b825460ff191660ff91909116178255565b6126006125e460a085016123ea565b825460089190911b63ffffff001663ffffff0019909116178255565b61262f61260f60c085016123fd565b825466ffffff00000000191660209190911b66ffffff0000000016178255565b61265c61263e60e085016123dd565b82805460ff60381b191660389290921b60ff60381b16919091179055565b506101008201356004820155612676610120830183612412565b6126848183600586016124e1565b50505050565b60006020828403121561269c57600080fd5b8135611ee9816123ce565b604051601f8201601f191681016001600160401b03811182821017156126cf576126cf61245a565b604052919050565b60006001600160401b038211156126f0576126f061245a565b5060051b60200190565b6000602080838503121561270d57600080fd5b82516001600160401b038082111561272457600080fd5b818501915085601f83011261273857600080fd5b815161274b612746826126d7565b6126a7565b818152600591821b840185019185820191908984111561276a57600080fd5b8686015b84811015612802578051868111156127865760008081fd5b8701603f81018c136127985760008081fd5b8881015160406127aa612746836126d7565b82815291851b83018101918b8101908f8411156127c75760008081fd5b938201935b838510156127f157845192506127e1836123ce565b828252938c0193908c01906127cc565b88525050509388019350870161276e565b50909998505050505050505050565b80820180821115611e4b57611e4b6121d3565b6000825160005b81811015612845576020818601810151858301520161282b565b50600092019182525091905056fea2646970667358221220b7ed4ed71d5d5e6fbb0fb8df8b787a7e552a8fce4c49dbc23fdaa4092f58074064736f6c63430008140033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101db5760003560e01c8063928d300e11610105578063c8db233e1161009d578063c8db233e1461046b578063c99252881461047e578063cf09e0d014610491578063d165dac21461049a578063d8dfeb45146104a3578063e184c9be146104b6578063e74d3c47146104bf578063ea8a1af0146104c7578063eef8889b146104cf57600080fd5b8063928d300e1461030c5780639a82a09a1461031f5780639af1d35a14610333578063b0c56f051461033c578063b1283e7714610344578063b1c9fe6e1461040f578063b5ac8d9814610424578063b8f7a66514610437578063c358c6961461044b57600080fd5b80633356a35a116101785780633356a35a146102a15780633f6fa655146102a9578063400e69ef146102b65780634652e330146102bf5780635c975abb146102cc57806362e5c819146102de5780636a265aa9146102e75780637e2480d2146102ef57806384b124ab1461030357600080fd5b8062641e8b146101e0578063085d03ee1461020957806309d28f7914610221578063158ef93e1461023757806316c38b3c1461024a5780631b15982a1461025f5780631c98697914610272578063242a8a6b14610285578063242c6c2d1461028e575b600080fd5b6001546101f3906001600160a01b031681565b6040516102009190611f6c565b60405180910390f35b6102116104f3565b6040519015158152602001610200565b6102296106c4565b604051908152602001610200565b6009546102119062010000900460ff1681565b61025d610258366004611f8e565b6106d3565b005b61022961026d366004611fc0565b61080f565b600c546102119062010000900460ff1681565b610229600b5481565b61025d61029c366004611fdd565b610c2d565b610211610c8c565b6009546102119060ff1681565b61022960055481565b600c546102119060ff1681565b60095461021190610100900460ff1681565b61022960065481565b610229610c96565b600c54610211906301000000900460ff1681565b610229600d5481565b61025d61031a366004611fc0565b610da5565b600954610211906301000000900460ff1681565b61022960045481565b610211610e5c565b6103b7610352366004611fdd565b600a602052600090815260409020805460018201546002808401546003850154600490950154939461ffff80851695620100009095041693919260ff80831693610100840490920b9262ffffff600160201b82041692600160381b9091049091169089565b60408051998a5261ffff98891660208b01529690971695880195909552606087019390935260ff918216608087015260020b60a086015262ffffff90911660c08501521660e083015261010082015261012001610200565b610417610fb6565b604051610200919061200c565b61025d610432366004612034565b610fec565b60095461021190600160201b900460ff1681565b61045e610459366004611fdd565b611222565b604051610200919061206f565b61025d610479366004611fc0565b6112b6565b6000546101f3906001600160a01b031681565b61022960085481565b61022960035481565b6002546101f3906001600160a01b031681565b61022960075481565b6102116113db565b610229611402565b600c546104e190610100900460ff1681565b60405160ff9091168152602001610200565b600c546000906301000000900460ff161561050e5750600190565b6000805b6006548110156106b8576000805460408051638ff9d5cf60e01b8152905183926001600160a01b031691638ff9d5cf9160048083019260209291908290030181865afa158015610566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058a91906120d2565b6000848152600a6020526040908190208054600182015460038301549351631334a14160e31b81526001600160a01b0395909516946399a50a0894610602946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b6040805180830381865afa15801561061e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106429190612199565b91509150818015610651575080155b156106a357600c5460ff1661066b57600194505050505090565b83610675816121e9565b600c546006549196506106919250610100900460ff1690612202565b8411156106a357600194505050505090565b505080806106b0906121e9565b915050610512565b50600091505090565b90565b60006106ce611527565b905090565b60008054906101000a90046001600160a01b03166001600160a01b031663481c6a756040518163ffffffff1660e01b8152600401602060405180830381865afa158015610724573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074891906120d2565b6001600160a01b0316336001600160a01b03161461079e5760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b60448201526064015b60405180910390fd5b801515600960019054906101000a900460ff161515036107bb5750565b600980548215156101000261ff00199091161790556040517f77860e247ab9186dbe64e5bd0e0b93273cc4273e01818420e788f500078886f59061080490831515815260200190565b60405180910390a150565b600080546001600160a01b0316331461083a5760405162461bcd60e51b815260040161079590612215565b600954610100900460ff16156108625760405162461bcd60e51b81526004016107959061225b565b600061086c6113db565b9050806108bb5760405162461bcd60e51b815260206004820152601a60248201527f5469636b6574206e6f74206578657263697361626c65207965740000000000006044820152606401610795565b6000600d541161090d5760405162461bcd60e51b815260206004820152601d60248201527f45787065637465642066696e616c207061796f7574206e6f74207365740000006044820152606401610795565b600d546004546000906109209083612202565b9050600061092c611c70565b15610b765750600b819055600160005b600654811015610aec5760008060009054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561099a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109be91906120d2565b6000838152600a60205260409081902080546001820154600383015493516371752fa560e01b81526001600160a01b0395909516946371752fa594610a36946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b602060405180830381865afa158015610a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a779190612282565b90508015610ad457600c5462010000900460ff1615610a9a576001925050610aec565b6000828152600a6020526040902060040154600b54670de0b6b3a764000091610ac29161229f565b610acc91906122b6565b600b55610ad9565b600092505b5080610ae4816121e9565b91505061093c565b5080610b1157600c5460ff16610b0457600b54610b15565b610b0c611527565b610b15565b6003545b600b55610b766001600160a01b0387161580610b3e57506002546001600160a01b038881169116145b610b53576000546001600160a01b0316610b60565b6001546001600160a01b03165b600b546002546001600160a01b03169190611c8d565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190610ba7903090600401611f6c565b602060405180830381865afa158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be891906122d8565b90508015610c0d57600054600254610c0d916001600160a01b03918216911683611c8d565b610c1f610c186104f3565b1583611ce4565b5050600b5495945050505050565b6000546001600160a01b03163314610c575760405162461bcd60e51b815260040161079590612215565b600d8190556040518181527f660dbcbc304d174b408928860802fceee5965601ce687ed10cc25b2db9b552a290602001610804565b60006106ce611c70565b600080546001600160a01b03163314610cc15760405162461bcd60e51b815260040161079590612215565b600954610100900460ff1615610ce95760405162461bcd60e51b81526004016107959061225b565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190610d1a903090600401611f6c565b602060405180830381865afa158015610d37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5b91906122d8565b90508015610d8057600054600254610d80916001600160a01b03918216911683611c8d565b610d8b600080611ce4565b5050600c805463ff00000019166301000000179055600090565b6000546001600160a01b03163314610dcf5760405162461bcd60e51b815260040161079590612215565b6002546040516370a0823160e01b8152610e599183916001600160a01b03909116906370a0823190610e05903090600401611f6c565b602060405180830381865afa158015610e22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4691906122d8565b6002546001600160a01b03169190611c8d565b50565b6000805b600654811015610fae5760008054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf91906120d2565b6000828152600a602052604090819020805460018201546003830154935163397f782360e01b81526001600160a01b03959095169463397f782394610f4f946201000090930461ffff1692600160201b820462ffffff169261010090920460020b916005909101906004016122f1565b602060405180830381865afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f909190612282565b610f9c57600091505090565b80610fa6816121e9565b915050610e60565b506001905090565b6000610fc06113db565b80610fcd575060095460ff165b610fd75750600090565b4260075410610fe65750600190565b50600290565b60095462010000900460ff16156110455760405162461bcd60e51b815260206004820152601a60248201527f5469636b657420616c726561647920696e697469616c697a65640000000000006044820152606401610795565b6009805462ff000019166201000017905561106660a0820160808301611fc0565b600080546001600160a01b0319166001600160a01b03929092169190911790556110908180612333565b6006555060005b6006548110156110fa576110ab8280612333565b828181106110bb576110bb612383565b90506020028101906110cd9190612399565b6000828152600a602052604090206110e58282612566565b508190506110f2816121e9565b915050611097565b5060208101356003556040810135600455606081013560055561112360c0820160a08301611fc0565b600180546001600160a01b0319166001600160a01b039290921691909117905561115360e0820160c08301611fc0565b600280546001600160a01b0319166001600160a01b039290921691909117905560e081013560075561118d61012082016101008301611f8e565b60098054911515600160201b0264ff0000000019909216919091179055426008556111c06101408201610120830161268a565b600c805460ff1960ff93841661010090810291821661ffff1984161761ff00199093169190911704909216151591909117905561120561016082016101408301611f8e565b600c8054911515620100000262ff00001990921691909117905550565b6060600a6000838152602001908152602001600020600501805480602002602001604051908101604052809291908181526020016000905b828210156112ab576000848152602090819020604080516060810182529185015461ffff8116835260ff62010000820416838501526301000000900460020b9082015282526001909201910161125a565b505050509050919050565b6000546001600160a01b031633146112e05760405162461bcd60e51b815260040161079590612215565b60026112ea610fb6565b60028111156112fb576112fb611ff6565b146113485760405162461bcd60e51b815260206004820152601a60248201527f5469636b6574206e6f7420696e206578706972792070686173650000000000006044820152606401610795565b60095460ff161561139b5760405162461bcd60e51b815260206004820152601c60248201527f43616e277420657870697265207265736f6c766564207469636b6574000000006044820152606401610795565b7fd5669ebe8b90ed693033f1915dcea031e7a16a6f146a8326c02eec10eed77edd816040516113ca9190611f6c565b60405180910390a1610e5981611d4b565b60095460009060ff161580156106ce57506113f4610e5c565b806106ce57506106ce6104f3565b600080546001600160a01b0316331461142d5760405162461bcd60e51b815260040161079590612215565b600954610100900460ff16156114555760405162461bcd60e51b81526004016107959061225b565b600354600b81905560015460025461147d926001600160a01b03918216929190911690611c8d565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a08231906114ae903090600401611f6c565b602060405180830381865afa1580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef91906122d8565b9050801561151457600054600254611514916001600160a01b03918216911683611c8d565b61151f600180611ce4565b5050600b5490565b600c5460009060ff16156106c15760008060009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa158015611589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ad91906120d2565b600654600c546040516305007e4d60e21b815260ff928316600482015261010090910490911660248201526001600160a01b039190911690631401f93490604401600060405180830381865afa15801561160b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261163391908101906126fa565b90506000815190506000670de0b6b3a764000082670de0b6b3a764000060035461165d919061229f565b61166791906122b6565b61167191906122b6565b905060006006546001600160401b0381111561168f5761168f61245a565b6040519080825280602002602001820160405280156116b8578160200160208202803683370190505b50905060006006546001600160401b038111156116d7576116d761245a565b604051908082528060200260200182016040528015611700578160200160208202803683370190505b50905060005b600654811015611aeb5760008054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611761573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061178591906120d2565b6000828152600a602052604090819020805460018201546003830154935163397f782360e01b81526001600160a01b03959095169463397f7823946117f5946201000090930461ffff1692600160201b820462ffffff169261010090920460020b916005909101906004016122f1565b602060405180830381865afa158015611812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118369190612282565b611847576000965050505050505090565b60008054906101000a90046001600160a01b03166001600160a01b0316638ff9d5cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611898573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bc91906120d2565b6000828152600a60205260409081902080546001820154600383015493516376d0508160e01b81526001600160a01b0395909516946376d0508194611934946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b602060405180830381865afa158015611951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119759190612282565b83828151811061198757611987612383565b91151560209283029190910182015260005460408051638ff9d5cf60e01b815290516001600160a01b0390921692638ff9d5cf926004808401938290030181865afa1580156119da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fe91906120d2565b6000828152600a60205260409081902080546001820154600383015493516371752fa560e01b81526001600160a01b0395909516946371752fa594611a76946201000090930461ffff1692600160201b820462ffffff1692610100830460020b92600160381b900460ff16916005019060040161214d565b602060405180830381865afa158015611a93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab79190612282565b828281518110611ac957611ac9612383565b9115156020928302919091019091015280611ae3816121e9565b915050611706565b5060005b84811015611c33576000868281518110611b0b57611b0b612383565b602002602001015190506000670de0b6b3a7640000905060005b8251811015611be8576000838281518110611b4257611b42612383565b60200260200101519050868160ff1681518110611b6157611b61612383565b602002602001015115611bcb57858160ff1681518110611b8357611b83612383565b6020026020010151611bc65760ff81166000908152600a6020526040902060040154670de0b6b3a764000090611bb9908561229f565b611bc391906122b6565b92505b611bd5565b6000925050611be8565b5080611be0816121e9565b915050611b25565b508015611c1e57600081611c04670de0b6b3a76400008961229f565b611c0e91906122b6565b9050611c1a818b612811565b9950505b50508080611c2b906121e9565b915050611aef565b506000600554670de0b6b3a7640000600354611c4f919061229f565b611c5991906122b6565b905080871115611c67578096505b50505050505090565b6000611c7a610e5c565b156106c157611c876104f3565b15905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611cdf908490611de0565b505050565b6009805482151563010000000263ff0000ff199091161760011790556040517f402533440ea6dbf4c9e96f4c7a180525f93b7972a76e0a007c14c379f81bef5a90611d3f908490849091151582521515602082015260400190565b60405180910390a15050565b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d7c903090600401611f6c565b602060405180830381865afa158015611d99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbd91906122d8565b90508015611ddc57600254611ddc906001600160a01b03168383611c8d565b5050565b6000611df56001600160a01b03841683611e3a565b90508051600014158015611e1a575080806020019051810190611e189190612282565b155b15611cdf5782604051635274afe760e01b81526004016107959190611f6c565b6060611e4883836000611e51565b90505b92915050565b606081471015611e76573060405163cd78605960e01b81526004016107959190611f6c565b600080856001600160a01b03168486604051611e929190612824565b60006040518083038185875af1925050503d8060008114611ecf576040519150601f19603f3d011682016040523d82523d6000602084013e611ed4565b606091505b5091509150611ee4868383611ef0565b925050505b9392505050565b606082611f0557611f0082611f43565b611ee9565b8151158015611f1c57506001600160a01b0384163b155b15611f3c5783604051639996b31560e01b81526004016107959190611f6c565b5080611ee9565b805115611f535780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0391909116815260200190565b8015158114610e5957600080fd5b600060208284031215611fa057600080fd5b8135611ee981611f80565b6001600160a01b0381168114610e5957600080fd5b600060208284031215611fd257600080fd5b8135611ee981611fab565b600060208284031215611fef57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b602081016003831061202e57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121561204657600080fd5b81356001600160401b0381111561205c57600080fd5b82016101608185031215611ee957600080fd5b602080825282518282018190526000919060409081850190868401855b828110156120c5578151805161ffff1685528681015160ff168786015285015160020b858501526060909301929085019060010161208c565b5091979650505050505050565b6000602082840312156120e457600080fd5b8151611ee981611fab565b6000815480845260208085019450836000528060002060005b8381101561214257815461ffff81168852601081901c60ff168489015260181c60020b604088015260609096019560019182019101612108565b509495945050505050565b86815261ffff8616602082015262ffffff851660408201528360020b606082015260ff8316608082015260c060a0820152600061218d60c08301846120ef565b98975050505050505050565b600080604083850312156121ac57600080fd5b82516121b781611f80565b60208401519092506121c881611f80565b809150509250929050565b634e487b7160e01b600052601160045260246000fd5b6000600182016121fb576121fb6121d3565b5060010190565b81810381811115611e4b57611e4b6121d3565b60208082526026908201527f4f6e6c792074686520414d4d206d617920706572666f726d207468657365206d6040820152656574686f647360d01b606082015260800190565b6020808252600d908201526c13585c9ad95d081c185d5cd959609a1b604082015260600190565b60006020828403121561229457600080fd5b8151611ee981611f80565b8082028115828204841417611e4b57611e4b6121d3565b6000826122d357634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156122ea57600080fd5b5051919050565b85815261ffff8516602082015262ffffff841660408201528260020b606082015260a06080820152600061232860a08301846120ef565b979650505050505050565b6000808335601e1984360301811261234a57600080fd5b8301803591506001600160401b0382111561236457600080fd5b6020019150600581901b360382131561237c57600080fd5b9250929050565b634e487b7160e01b600052603260045260246000fd5b6000823561013e198336030181126123b057600080fd5b9190910192915050565b6000813561ffff81168114611e4b57600080fd5b60ff81168114610e5957600080fd5b60008135611e4b816123ce565b600081358060020b8114611e4b57600080fd5b6000813562ffffff81168114611e4b57600080fd5b6000808335601e1984360301811261242957600080fd5b8301803591506001600160401b0382111561244357600080fd5b602001915060608102360382131561237c57600080fd5b634e487b7160e01b600052604160045260246000fd5b61248f61247c836123ba565b825461ffff191661ffff91909116178255565b602082013561249d816123ce565b815462ff00008260101b1691508162ff00001982161783556124c1604085016123ea565b60181b65ffffff000000168265ffffffff00001983161717835550505050565b600160401b8311156124f5576124f561245a565b80548382558084101561252c576000828152602081208581019083015b8082101561252857828255600182019150612512565b5050505b5060008181526020812083915b8581101561255e5761254b8383612470565b6060929092019160019182019101612539565b505050505050565b813581556001810161257d61247c602085016123ba565b6125a661258c604085016123ba565b825463ffff0000191660109190911b63ffff000016178255565b5060608201356002820155600381016125d56125c4608085016123dd565b825460ff191660ff91909116178255565b6126006125e460a085016123ea565b825460089190911b63ffffff001663ffffff0019909116178255565b61262f61260f60c085016123fd565b825466ffffff00000000191660209190911b66ffffff0000000016178255565b61265c61263e60e085016123dd565b82805460ff60381b191660389290921b60ff60381b16919091179055565b506101008201356004820155612676610120830183612412565b6126848183600586016124e1565b50505050565b60006020828403121561269c57600080fd5b8135611ee9816123ce565b604051601f8201601f191681016001600160401b03811182821017156126cf576126cf61245a565b604052919050565b60006001600160401b038211156126f0576126f061245a565b5060051b60200190565b6000602080838503121561270d57600080fd5b82516001600160401b038082111561272457600080fd5b818501915085601f83011261273857600080fd5b815161274b612746826126d7565b6126a7565b818152600591821b840185019185820191908984111561276a57600080fd5b8686015b84811015612802578051868111156127865760008081fd5b8701603f81018c136127985760008081fd5b8881015160406127aa612746836126d7565b82815291851b83018101918b8101908f8411156127c75760008081fd5b938201935b838510156127f157845192506127e1836123ce565b828252938c0193908c01906127cc565b88525050509388019350870161276e565b50909998505050505050505050565b80820180821115611e4b57611e4b6121d3565b6000825160005b81811015612845576020818601810151858301520161282b565b50600092019182525091905056fea2646970667358221220b7ed4ed71d5d5e6fbb0fb8df8b787a7e552a8fce4c49dbc23fdaa4092f58074064736f6c63430008140033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.