Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 45,004 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Merge Positions | 65181542 | 27 secs ago | IN | 0 POL | 0.00688773 | ||||
Merge Positions | 65181483 | 2 mins ago | IN | 0 POL | 0.0068714 | ||||
Split Position | 65181175 | 14 mins ago | IN | 0 POL | 0.00670189 | ||||
Split Position | 65180774 | 28 mins ago | IN | 0 POL | 0.00660392 | ||||
Merge Positions | 65180510 | 38 mins ago | IN | 0 POL | 0.00507035 | ||||
Split Position | 65180460 | 40 mins ago | IN | 0 POL | 0.00695716 | ||||
Merge Positions | 65180342 | 44 mins ago | IN | 0 POL | 0.00599481 | ||||
Merge Positions | 65180311 | 45 mins ago | IN | 0 POL | 0.00507059 | ||||
Split Position | 65178851 | 1 hr ago | IN | 0 POL | 0.00664586 | ||||
Merge Positions | 65178121 | 2 hrs ago | IN | 0 POL | 0.00594746 | ||||
Merge Positions | 65177917 | 2 hrs ago | IN | 0 POL | 0.00472897 | ||||
Split Position | 65177783 | 2 hrs ago | IN | 0 POL | 0.00664945 | ||||
Split Position | 65177779 | 2 hrs ago | IN | 0 POL | 0.00634749 | ||||
Split Position | 65177757 | 2 hrs ago | IN | 0 POL | 0.00726334 | ||||
Merge Positions | 65176704 | 2 hrs ago | IN | 0 POL | 0.00682965 | ||||
Merge Positions | 65176182 | 3 hrs ago | IN | 0 POL | 0.00494826 | ||||
Merge Positions | 65174677 | 4 hrs ago | IN | 0 POL | 0.00654588 | ||||
Merge Positions | 65174646 | 4 hrs ago | IN | 0 POL | 0.00540652 | ||||
Split Position | 65174430 | 4 hrs ago | IN | 0 POL | 0.00656226 | ||||
Split Position | 65174298 | 4 hrs ago | IN | 0 POL | 0.00656226 | ||||
Split Position | 65174291 | 4 hrs ago | IN | 0 POL | 0.00729153 | ||||
Merge Positions | 65173898 | 4 hrs ago | IN | 0 POL | 0.00518355 | ||||
Merge Positions | 65173889 | 4 hrs ago | IN | 0 POL | 0.00652082 | ||||
Merge Positions | 65172400 | 5 hrs ago | IN | 0 POL | 0.00545652 | ||||
Merge Positions | 65172015 | 5 hrs ago | IN | 0 POL | 0.00686448 |
Latest 4 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
63686385 | 37 days ago | 1 wei | ||||
63686305 | 37 days ago | 1 wei | ||||
63642257 | 38 days ago | 1 wei | ||||
50505403 | 374 days ago | Contract Creation | 0 POL |
Loading...
Loading
Contract Name:
NegRiskAdapter
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {ERC1155TokenReceiver} from "lib/solmate/src/tokens/ERC1155.sol"; import {ERC20} from "lib/solmate/src/tokens/ERC20.sol"; import {SafeTransferLib} from "lib/solmate/src/utils/SafeTransferLib.sol"; import {WrappedCollateral} from "src/WrappedCollateral.sol"; import {MarketData, MarketStateManager, IMarketStateManagerEE} from "src/modules/MarketDataManager.sol"; import {CTHelpers} from "src/libraries/CTHelpers.sol"; import {Helpers} from "src/libraries/Helpers.sol"; import {NegRiskIdLib} from "src/libraries/NegRiskIdLib.sol"; import {IConditionalTokens} from "src/interfaces/IConditionalTokens.sol"; import {Auth} from "src/modules/Auth.sol"; import {IAuthEE} from "src/modules/interfaces/IAuth.sol"; /// @title INegRiskAdapterEE /// @notice NegRiskAdapter Errors and Events interface INegRiskAdapterEE is IMarketStateManagerEE, IAuthEE { error InvalidIndexSet(); error LengthMismatch(); error UnexpectedCollateralToken(); error NoConvertiblePositions(); error NotApprovedForAll(); event MarketPrepared(bytes32 indexed marketId, address indexed oracle, uint256 feeBips, bytes data); event QuestionPrepared(bytes32 indexed marketId, bytes32 indexed questionId, uint256 index, bytes data); event OutcomeReported(bytes32 indexed marketId, bytes32 indexed questionId, bool outcome); event PositionSplit(address indexed stakeholder, bytes32 indexed conditionId, uint256 amount); event PositionsMerge(address indexed stakeholder, bytes32 indexed conditionId, uint256 amount); event PositionsConverted( address indexed stakeholder, bytes32 indexed marketId, uint256 indexed indexSet, uint256 amount ); event PayoutRedemption(address indexed redeemer, bytes32 indexed conditionId, uint256[] amounts, uint256 payout); } /// @title NegRiskAdapter /// @notice Adapter for the CTF enabling the linking of a set binary markets where only one can resolve true /// @notice The adapter prevents more than one question in the same multi-outcome market from resolving true /// @notice And the adapter allows for the conversion of a set of no positions, to collateral plus the set of /// complementary yes positions /// @author Mike Shrieve ([email protected]) contract NegRiskAdapter is ERC1155TokenReceiver, MarketStateManager, INegRiskAdapterEE, Auth { using SafeTransferLib for ERC20; /*////////////////////////////////////////////////////////////// STATE //////////////////////////////////////////////////////////////*/ IConditionalTokens public immutable ctf; ERC20 public immutable col; WrappedCollateral public immutable wcol; address public immutable vault; address public constant NO_TOKEN_BURN_ADDRESS = address(bytes20(bytes32(keccak256("NO_TOKEN_BURN_ADDRESS")))); uint256 public constant FEE_DENOMINATOR = 10_000; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /// @param _ctf - ConditionalTokens address /// @param _collateral - collateral address constructor(address _ctf, address _collateral, address _vault) { ctf = IConditionalTokens(_ctf); col = ERC20(_collateral); vault = _vault; wcol = new WrappedCollateral(_collateral, col.decimals()); // approve the ctf to transfer wcol on our behalf wcol.approve(_ctf, type(uint256).max); // approve wcol to transfer collateral on our behalf col.approve(address(wcol), type(uint256).max); } /*////////////////////////////////////////////////////////////// IDS //////////////////////////////////////////////////////////////*/ /// @notice Returns the conditionId for a given questionId /// @param _questionId - the questionId /// @return conditionId - the corresponding conditionId function getConditionId(bytes32 _questionId) public view returns (bytes32) { return CTHelpers.getConditionId( address(this), // oracle _questionId, 2 // outcomeCount ); } /// @notice Returns the positionId for a given questionId and outcome /// @param _questionId - the questionId /// @param _outcome - the boolean outcome /// @return positionId - the corresponding positionId function getPositionId(bytes32 _questionId, bool _outcome) public view returns (uint256) { bytes32 collectionId = CTHelpers.getCollectionId( bytes32(0), getConditionId(_questionId), _outcome ? 1 : 2 // 1 (0b01) is yes, 2 (0b10) is no ); uint256 positionId = CTHelpers.getPositionId(address(wcol), collectionId); return positionId; } /*////////////////////////////////////////////////////////////// SPLIT POSITION //////////////////////////////////////////////////////////////*/ /// @notice Splits collateral to a complete set of conditional tokens for a single question /// @notice This function signature is the same as the CTF's splitPosition /// @param _collateralToken - the collateral token, must be the same as the adapter's collateral token /// @param _conditionId - the conditionId for the question /// @param _amount - the amount of collateral to split function splitPosition(address _collateralToken, bytes32, bytes32 _conditionId, uint256[] calldata, uint256 _amount) external { if (_collateralToken != address(col)) revert UnexpectedCollateralToken(); splitPosition(_conditionId, _amount); } /// @notice Splits collateral to a complete set of conditional tokens for a single question /// @param _conditionId - the conditionId for the question /// @param _amount - the amount of collateral to split function splitPosition(bytes32 _conditionId, uint256 _amount) public { col.safeTransferFrom(msg.sender, address(this), _amount); wcol.wrap(address(this), _amount); ctf.splitPosition(address(wcol), bytes32(0), _conditionId, Helpers.partition(), _amount); ctf.safeBatchTransferFrom( address(this), msg.sender, Helpers.positionIds(address(wcol), _conditionId), Helpers.values(2, _amount), "" ); emit PositionSplit(msg.sender, _conditionId, _amount); } /*////////////////////////////////////////////////////////////// MERGE POSITIONS //////////////////////////////////////////////////////////////*/ /// @notice Merges a complete set of conditional tokens for a single question to collateral /// @notice This function signature is the same as the CTF's mergePositions /// @param _collateralToken - the collateral token, must be the same as the adapter's collateral token /// @param _conditionId - the conditionId for the question /// @param _amount - the amount of collateral to merge function mergePositions( address _collateralToken, bytes32, bytes32 _conditionId, uint256[] calldata, uint256 _amount ) external { if (_collateralToken != address(col)) revert UnexpectedCollateralToken(); mergePositions(_conditionId, _amount); } /// @notice Merges a complete set of conditional tokens for a single question to collateral /// @param _conditionId - the conditionId for the question /// @param _amount - the amount of collateral to merge function mergePositions(bytes32 _conditionId, uint256 _amount) public { uint256[] memory positionIds = Helpers.positionIds(address(wcol), _conditionId); // get conditional tokens from sender ctf.safeBatchTransferFrom(msg.sender, address(this), positionIds, Helpers.values(2, _amount), ""); ctf.mergePositions(address(wcol), bytes32(0), _conditionId, Helpers.partition(), _amount); wcol.unwrap(msg.sender, _amount); emit PositionsMerge(msg.sender, _conditionId, _amount); } /*////////////////////////////////////////////////////////////// ERC1155 OPERATIONS //////////////////////////////////////////////////////////////*/ /// @notice Proxies ERC1155 balanceOf to the CTF /// @param _owner - the owner of the tokens /// @param _id - the positionId /// @return balance - the owner's balance function balanceOf(address _owner, uint256 _id) external view returns (uint256) { return ctf.balanceOf(_owner, _id); } /// @notice Proxies ERC1155 balanceOfBatch to the CTF /// @param _owners - the owners of the tokens /// @param _ids - the positionIds /// @return balances - the owners' balances function balanceOfBatch(address[] memory _owners, uint256[] memory _ids) external view returns (uint256[] memory) { return ctf.balanceOfBatch(_owners, _ids); } /// @notice Proxies ERC1155 safeTransferFrom to the CTF /// @notice Can only be called by an admin /// @notice Requires this contract to be approved for all /// @notice Requires the sender to be approved for all /// @param _from - the owner of the tokens /// @param _to - the recipient of the tokens /// @param _id - the positionId /// @param _value - the amount of tokens to transfer /// @param _data - the data to pass to the recipient function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external onlyAdmin { if (!ctf.isApprovedForAll(_from, msg.sender)) { revert NotApprovedForAll(); } return ctf.safeTransferFrom(_from, _to, _id, _value, _data); } /*////////////////////////////////////////////////////////////// REDEEM POSITION //////////////////////////////////////////////////////////////*/ /// @notice Redeem a set of conditional tokens for collateral /// @param _conditionId - conditionId of the conditional tokens to redeem /// @param _amounts - amounts of conditional tokens to redeem /// _amounts should always have length 2, with the first element being the amount of yes tokens to redeem and the /// second element being the amount of no tokens to redeem function redeemPositions(bytes32 _conditionId, uint256[] calldata _amounts) public { uint256[] memory positionIds = Helpers.positionIds(address(wcol), _conditionId); // get conditional tokens from sender ctf.safeBatchTransferFrom(msg.sender, address(this), positionIds, _amounts, ""); ctf.redeemPositions(address(wcol), bytes32(0), _conditionId, Helpers.partition()); uint256 payout = wcol.balanceOf(address(this)); if (payout > 0) { wcol.unwrap(msg.sender, payout); } emit PayoutRedemption(msg.sender, _conditionId, _amounts, payout); } /*////////////////////////////////////////////////////////////// CONVERT POSITIONS //////////////////////////////////////////////////////////////*/ /// @notice Convert a set of no positions to the complementary set of yes positions plus collateral proportional to /// (# of no positions - 1) /// @notice If the market has a fee, the fee is taken from both collateral and the yes positions /// @param _marketId - the marketId /// @param _indexSet - the set of positions to convert, expressed as an index set where the least significant bit is /// the first question (index zero) /// @param _amount - the amount of tokens to convert function convertPositions(bytes32 _marketId, uint256 _indexSet, uint256 _amount) external { MarketData md = getMarketData(_marketId); uint256 questionCount = md.questionCount(); if (md.oracle() == address(0)) revert MarketNotPrepared(); if (questionCount <= 1) revert NoConvertiblePositions(); if (_indexSet == 0) revert InvalidIndexSet(); if ((_indexSet >> questionCount) > 0) revert InvalidIndexSet(); // if _amount is 0, return early if (_amount == 0) { return; } uint256 index = 0; uint256 noPositionCount; // count number of no positions while (index < questionCount) { unchecked { if ((_indexSet & (1 << index)) > 0) { ++noPositionCount; } ++index; } } uint256 yesPositionCount = questionCount - noPositionCount; uint256[] memory noPositionIds = new uint256[](noPositionCount); uint256[] memory yesPositionIds = new uint256[](yesPositionCount); uint256[] memory accumulatedNoPositionIds = new uint256[](yesPositionCount); // mint the amount of wcol required wcol.mint(yesPositionCount * _amount); // populate noPositionIds and yesPositionIds // split yes positions { uint256 noIndex; uint256 yesIndex; index = 0; while (index < questionCount) { bytes32 questionId = NegRiskIdLib.getQuestionId(_marketId, uint8(index)); if ((_indexSet & (1 << index)) > 0) { // NO noPositionIds[noIndex] = getPositionId(questionId, false); unchecked { ++noIndex; } } else { // YES yesPositionIds[yesIndex] = getPositionId(questionId, true); accumulatedNoPositionIds[yesIndex] = getPositionId(questionId, false); // split position to get yes and no tokens // the no tokens will be discarded _splitPosition(getConditionId(questionId), _amount); unchecked { ++yesIndex; } } unchecked { ++index; } } } // transfer the caller's no tokens _and_ accumulated no tokens to the burn address // these must never be redeemed { ctf.safeBatchTransferFrom( msg.sender, NO_TOKEN_BURN_ADDRESS, noPositionIds, Helpers.values(noPositionIds.length, _amount), "" ); ctf.safeBatchTransferFrom( address(this), NO_TOKEN_BURN_ADDRESS, accumulatedNoPositionIds, Helpers.values(yesPositionCount, _amount), "" ); } uint256 feeAmount = (_amount * md.feeBips()) / FEE_DENOMINATOR; uint256 amountOut = _amount - feeAmount; if (noPositionIds.length > 1) { // collateral out is always proportional to the number of no positions minus 1 uint256 multiplier = noPositionIds.length - 1; // transfer collateral fees to vault if (feeAmount > 0) { wcol.release(vault, multiplier * feeAmount); } // transfer collateral to sender wcol.release(msg.sender, multiplier * amountOut); } if (yesPositionIds.length > 0) { if (feeAmount > 0) { // transfer yes token fees to vault ctf.safeBatchTransferFrom( address(this), vault, yesPositionIds, Helpers.values(yesPositionIds.length, feeAmount), "" ); } // transfer yes tokens to sender ctf.safeBatchTransferFrom( address(this), msg.sender, yesPositionIds, Helpers.values(yesPositionIds.length, amountOut), "" ); } emit PositionsConverted(msg.sender, _marketId, _indexSet, _amount); } /*////////////////////////////////////////////////////////////// PREPARE MARKET //////////////////////////////////////////////////////////////*/ /// @notice Prepare a multi-outcome market /// @param _feeBips - the fee for the market, out of 10_000 /// @param _metadata - metadata for the market /// @return marketId - the marketId function prepareMarket(uint256 _feeBips, bytes calldata _metadata) external returns (bytes32) { bytes32 marketId = _prepareMarket(_feeBips, _metadata); emit MarketPrepared(marketId, msg.sender, _feeBips, _metadata); return marketId; } /*////////////////////////////////////////////////////////////// PREPARE QUESTION //////////////////////////////////////////////////////////////*/ /// @notice Prepare a question for a given market /// @param _marketId - the id of the market for which to prepare the question /// @param _metadata - the question metadata /// @return questionId - the id of the resulting question function prepareQuestion(bytes32 _marketId, bytes calldata _metadata) external returns (bytes32) { (bytes32 questionId, uint256 questionIndex) = _prepareQuestion(_marketId); bytes32 conditionId = getConditionId(questionId); // check to see if the condition has already been prepared on the ctf if (ctf.getOutcomeSlotCount(conditionId) == 0) { ctf.prepareCondition(address(this), questionId, 2); } emit QuestionPrepared(_marketId, questionId, questionIndex, _metadata); return questionId; } /*////////////////////////////////////////////////////////////// REPORT OUTCOME //////////////////////////////////////////////////////////////*/ /// @notice Report the outcome of a question /// @param _questionId - the questionId to report /// @param _outcome - the outcome of the question function reportOutcome(bytes32 _questionId, bool _outcome) external { _reportOutcome(_questionId, _outcome); ctf.reportPayouts(_questionId, Helpers.payouts(_outcome)); emit OutcomeReported(NegRiskIdLib.getMarketId(_questionId), _questionId, _outcome); } /*////////////////////////////////////////////////////////////// INTERNAL //////////////////////////////////////////////////////////////*/ /// @dev internal function to avoid stack too deep in convertPositions function _splitPosition(bytes32 _conditionId, uint256 _amount) internal { ctf.splitPosition(address(wcol), bytes32(0), _conditionId, Helpers.partition(), _amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {ERC20} from "lib/solmate/src/tokens/ERC20.sol"; import {SafeTransferLib} from "lib/solmate/src/utils/SafeTransferLib.sol"; /// @title IWrappedCollateralEE /// @notice WrappedCollateral Errors and Events interface IWrappedCollateralEE { error OnlyOwner(); } string constant NAME = "Wrapped Collateral"; string constant SYMBOL = "WCOL"; /// @title WrappedCollateral /// @author Mike Shrieve ([email protected]) /// @notice Wraps an ERC20 token to be used as collateral in the CTF contract WrappedCollateral is IWrappedCollateralEE, ERC20 { using SafeTransferLib for ERC20; /*////////////////////////////////////////////////////////////// STATE //////////////////////////////////////////////////////////////*/ address public immutable owner; address public immutable underlying; /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ modifier onlyOwner() { if (msg.sender != owner) revert OnlyOwner(); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /// @param _underlying The address of the underlying ERC20 token /// @param _decimals The number of decimals of the underlying ERC20 token constructor(address _underlying, uint8 _decimals) ERC20(NAME, SYMBOL, _decimals) { owner = msg.sender; underlying = _underlying; } /*////////////////////////////////////////////////////////////// UNWRAP //////////////////////////////////////////////////////////////*/ /// @notice Unwraps the specified amount of tokens /// @param _to The address to send the unwrapped tokens to /// @param _amount The amount of tokens to unwrap function unwrap(address _to, uint256 _amount) external { _burn(msg.sender, _amount); ERC20(underlying).safeTransfer(_to, _amount); } /*////////////////////////////////////////////////////////////// ADMIN //////////////////////////////////////////////////////////////*/ /// @notice Wraps the specified amount of tokens /// @notice Can only be called by the owner /// @param _to - the address to send the wrapped tokens to /// @param _amount - the amount of tokens to wrap function wrap(address _to, uint256 _amount) external onlyOwner { ERC20(underlying).safeTransferFrom(msg.sender, address(this), _amount); _mint(_to, _amount); } /// @notice Burns the specified amount of tokens /// @notice Can only be called by the owner /// @param _amount - the amount of tokens to burn function burn(uint256 _amount) external onlyOwner { _burn(msg.sender, _amount); } /// @notice Mints the specified amount of tokens /// @notice Can only be called by the owner /// @param _amount - the amount of tokens to mint function mint(uint256 _amount) external onlyOwner { _mint(msg.sender, _amount); } /// @notice Releases the specified amount of the underlying token /// @notice Can only be called by the owner /// @param _to - the address to send the released tokens to /// @param _amount - the amount of tokens to release function release(address _to, uint256 _amount) external onlyOwner { ERC20(underlying).safeTransfer(_to, _amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import {MarketData, MarketDataLib} from "src/types/MarketData.sol"; import {NegRiskIdLib} from "src/libraries/NegRiskIdLib.sol"; interface IMarketStateManagerEE { error IndexOutOfBounds(); error OnlyOracle(); error MarketNotPrepared(); error MarketAlreadyPrepared(); error MarketAlreadyDetermined(); error FeeBipsOutOfBounds(); } /// @title MarketStateManager /// @notice Manages market state on behalf of the NegRiskAdapter /// @author Mike Shrieve([email protected]) abstract contract MarketStateManager is IMarketStateManagerEE { mapping(bytes32 _marketId => MarketData) internal marketData; /*////////////////////////////////////////////////////////////// GETTERS //////////////////////////////////////////////////////////////*/ function getMarketData(bytes32 _marketId) public view returns (MarketData) { return marketData[_marketId]; } function getOracle(bytes32 _marketId) external view returns (address) { return marketData[_marketId].oracle(); } function getQuestionCount(bytes32 _marketId) external view returns (uint256) { return marketData[_marketId].questionCount(); } function getDetermined(bytes32 _marketId) external view returns (bool) { return marketData[_marketId].determined(); } function getResult(bytes32 _marketId) external view returns (uint256) { return marketData[_marketId].result(); } function getFeeBips(bytes32 _marketId) external view returns (uint256) { return marketData[_marketId].feeBips(); } /*////////////////////////////////////////////////////////////// INTERNAL //////////////////////////////////////////////////////////////*/ /// @notice Prepares market data /// @notice The market id depends on the oracle address, feeBips, and market metadata /// @param _feeBips - feeBips out of 10_000 /// @param _metadata - market metadata /// @return marketId - the market id function _prepareMarket(uint256 _feeBips, bytes memory _metadata) internal returns (bytes32 marketId) { address oracle = msg.sender; marketId = NegRiskIdLib.getMarketId(oracle, _feeBips, _metadata); MarketData md = marketData[marketId]; if (md.oracle() != address(0)) revert MarketAlreadyPrepared(); if (_feeBips > 10_000) revert FeeBipsOutOfBounds(); marketData[marketId] = MarketDataLib.initialize(oracle, _feeBips); } /// @notice Prepares a new question for the given market /// @param _marketId - the market for which to prepare a new question /// @return questionId - the resulting question id /// @return index - the resulting question index function _prepareQuestion(bytes32 _marketId) internal returns (bytes32 questionId, uint256 index) { MarketData md = marketData[_marketId]; address oracle = marketData[_marketId].oracle(); if (oracle == address(0)) revert MarketNotPrepared(); if (oracle != msg.sender) revert OnlyOracle(); index = md.questionCount(); questionId = NegRiskIdLib.getQuestionId(_marketId, uint8(index)); marketData[_marketId] = md.incrementQuestionCount(); } /// @notice Reports the outcome of a question /// @notice State is only modified if the outcome is true /// @notice Reverts if the market is not prepared /// @notice Reverts if msg.sender is not the market's oracle /// @notice Reverts if the question index is out of bounds /// @notice Reverts if the outcome is true, and the market has already been determined function _reportOutcome(bytes32 _questionId, bool _outcome) internal { bytes32 marketId = NegRiskIdLib.getMarketId(_questionId); uint256 questionIndex = NegRiskIdLib.getQuestionIndex(_questionId); MarketData data = marketData[marketId]; address oracle = data.oracle(); if (oracle == address(0)) revert MarketNotPrepared(); if (oracle != msg.sender) revert OnlyOracle(); if (questionIndex >= data.questionCount()) revert IndexOutOfBounds(); if (_outcome == true) { if (data.determined()) revert MarketAlreadyDetermined(); marketData[marketId] = data.determine(questionIndex); } } }
// SPDX-License-Identifier: LGPL-3.0-or-later pragma solidity >=0.5.1; // forked from Gnosis Condtional Tokens library CTHelpers { /// @dev Constructs a condition ID from an oracle, a question ID, and the outcome slot count for /// the question. /// @param oracle The account assigned to report the result for the prepared condition. /// @param questionId An identifier for the question to be answered by the oracle. /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. /// Must not exceed 256. function getConditionId(address oracle, bytes32 questionId, uint256 outcomeSlotCount) internal pure returns (bytes32) { return keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount)); } uint256 constant P = 21888242871839275222246405745257275088696311157297823662689037894645226208583; uint256 constant B = 3; function sqrt(uint256 x) private pure returns (uint256 y) { uint256 p = P; // solium-disable-next-line security/no-inline-assembly assembly { // add chain generated via https://crypto.stackexchange.com/q/27179/71252 // and transformed to the following program: // x=1; y=x+x; z=y+y; z=z+z; y=y+z; x=x+y; y=y+x; z=y+y; t=z+z; t=z+t; t=t+t; // t=t+t; z=z+t; x=x+z; z=x+x; z=z+z; y=y+z; z=y+y; z=z+z; z=z+z; z=y+z; x=x+z; // z=x+x; z=z+z; z=z+z; z=x+z; y=y+z; x=x+y; z=x+x; z=z+z; y=y+z; z=y+y; t=z+z; // t=t+t; t=t+t; z=z+t; x=x+z; y=y+x; z=y+y; z=z+z; z=z+z; x=x+z; z=x+x; z=z+z; // z=x+z; z=z+z; z=z+z; z=x+z; y=y+z; z=y+y; t=z+z; t=t+t; t=z+t; t=y+t; t=t+t; // t=t+t; t=t+t; t=t+t; z=z+t; x=x+z; z=x+x; z=x+z; y=y+z; z=y+y; z=y+z; z=z+z; // t=z+z; t=z+t; w=t+t; w=w+w; w=w+w; w=w+w; w=w+w; t=t+w; z=z+t; x=x+z; y=y+x; // z=y+y; x=x+z; y=y+x; x=x+y; y=y+x; x=x+y; z=x+x; z=x+z; z=z+z; y=y+z; z=y+y; // z=z+z; x=x+z; y=y+x; z=y+y; z=y+z; x=x+z; y=y+x; x=x+y; y=y+x; z=y+y; z=z+z; // z=y+z; x=x+z; z=x+x; z=x+z; y=y+z; x=x+y; y=y+x; x=x+y; y=y+x; z=y+y; z=y+z; // z=z+z; x=x+z; y=y+x; z=y+y; z=y+z; z=z+z; x=x+z; z=x+x; t=z+z; t=t+t; t=z+t; // t=x+t; t=t+t; t=t+t; t=t+t; t=t+t; z=z+t; y=y+z; x=x+y; y=y+x; x=x+y; z=x+x; // z=x+z; z=z+z; z=z+z; z=z+z; z=x+z; y=y+z; z=y+y; z=y+z; z=z+z; x=x+z; z=x+x; // z=x+z; y=y+z; x=x+y; z=x+x; z=z+z; y=y+z; x=x+y; z=x+x; y=y+z; x=x+y; y=y+x; // z=y+y; z=y+z; x=x+z; y=y+x; z=y+y; z=y+z; z=z+z; z=z+z; x=x+z; z=x+x; z=z+z; // z=z+z; z=x+z; y=y+z; x=x+y; z=x+x; t=x+z; t=t+t; t=t+t; z=z+t; y=y+z; z=y+y; // x=x+z; y=y+x; x=x+y; y=y+x; x=x+y; y=y+x; z=y+y; t=y+z; z=y+t; z=z+z; z=z+z; // z=t+z; x=x+z; y=y+x; x=x+y; y=y+x; x=x+y; z=x+x; z=x+z; y=y+z; x=x+y; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; x=x+x; // x=x+x; x=x+x; x=x+x; x=x+x; res=y+x // res == (P + 1) // 4 y := mulmod(x, x, p) { let z := mulmod(y, y, p) z := mulmod(z, z, p) y := mulmod(y, z, p) x := mulmod(x, y, p) y := mulmod(y, x, p) z := mulmod(y, y, p) { let t := mulmod(z, z, p) t := mulmod(z, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) z := mulmod(z, t, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(z, z, p) y := mulmod(y, z, p) z := mulmod(y, y, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(y, z, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(x, z, p) y := mulmod(y, z, p) x := mulmod(x, y, p) z := mulmod(x, x, p) z := mulmod(z, z, p) y := mulmod(y, z, p) z := mulmod(y, y, p) t := mulmod(z, z, p) t := mulmod(t, t, p) t := mulmod(t, t, p) z := mulmod(z, t, p) x := mulmod(x, z, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(z, z, p) z := mulmod(z, z, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(z, z, p) z := mulmod(x, z, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(x, z, p) y := mulmod(y, z, p) z := mulmod(y, y, p) t := mulmod(z, z, p) t := mulmod(t, t, p) t := mulmod(z, t, p) t := mulmod(y, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) z := mulmod(z, t, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(x, z, p) y := mulmod(y, z, p) z := mulmod(y, y, p) z := mulmod(y, z, p) z := mulmod(z, z, p) t := mulmod(z, z, p) t := mulmod(z, t, p) { let w := mulmod(t, t, p) w := mulmod(w, w, p) w := mulmod(w, w, p) w := mulmod(w, w, p) w := mulmod(w, w, p) t := mulmod(t, w, p) } z := mulmod(z, t, p) x := mulmod(x, z, p) y := mulmod(y, x, p) z := mulmod(y, y, p) x := mulmod(x, z, p) y := mulmod(y, x, p) x := mulmod(x, y, p) y := mulmod(y, x, p) x := mulmod(x, y, p) z := mulmod(x, x, p) z := mulmod(x, z, p) z := mulmod(z, z, p) y := mulmod(y, z, p) z := mulmod(y, y, p) z := mulmod(z, z, p) x := mulmod(x, z, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(y, z, p) x := mulmod(x, z, p) y := mulmod(y, x, p) x := mulmod(x, y, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(z, z, p) z := mulmod(y, z, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(x, z, p) y := mulmod(y, z, p) x := mulmod(x, y, p) y := mulmod(y, x, p) x := mulmod(x, y, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(y, z, p) z := mulmod(z, z, p) x := mulmod(x, z, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(y, z, p) z := mulmod(z, z, p) x := mulmod(x, z, p) z := mulmod(x, x, p) t := mulmod(z, z, p) t := mulmod(t, t, p) t := mulmod(z, t, p) t := mulmod(x, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) t := mulmod(t, t, p) z := mulmod(z, t, p) y := mulmod(y, z, p) x := mulmod(x, y, p) y := mulmod(y, x, p) x := mulmod(x, y, p) z := mulmod(x, x, p) z := mulmod(x, z, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(x, z, p) y := mulmod(y, z, p) z := mulmod(y, y, p) z := mulmod(y, z, p) z := mulmod(z, z, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(x, z, p) y := mulmod(y, z, p) x := mulmod(x, y, p) z := mulmod(x, x, p) z := mulmod(z, z, p) y := mulmod(y, z, p) x := mulmod(x, y, p) z := mulmod(x, x, p) y := mulmod(y, z, p) x := mulmod(x, y, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(y, z, p) x := mulmod(x, z, p) y := mulmod(y, x, p) z := mulmod(y, y, p) z := mulmod(y, z, p) z := mulmod(z, z, p) z := mulmod(z, z, p) x := mulmod(x, z, p) z := mulmod(x, x, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(x, z, p) y := mulmod(y, z, p) x := mulmod(x, y, p) z := mulmod(x, x, p) t := mulmod(x, z, p) t := mulmod(t, t, p) t := mulmod(t, t, p) z := mulmod(z, t, p) y := mulmod(y, z, p) z := mulmod(y, y, p) x := mulmod(x, z, p) y := mulmod(y, x, p) x := mulmod(x, y, p) y := mulmod(y, x, p) x := mulmod(x, y, p) y := mulmod(y, x, p) z := mulmod(y, y, p) t := mulmod(y, z, p) z := mulmod(y, t, p) z := mulmod(z, z, p) z := mulmod(z, z, p) z := mulmod(t, z, p) } x := mulmod(x, z, p) y := mulmod(y, x, p) x := mulmod(x, y, p) y := mulmod(y, x, p) x := mulmod(x, y, p) z := mulmod(x, x, p) z := mulmod(x, z, p) y := mulmod(y, z, p) } x := mulmod(x, y, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) x := mulmod(x, x, p) y := mulmod(y, x, p) } } /// @dev Constructs an outcome collection ID from a parent collection and an outcome collection. /// @param parentCollectionId Collection ID of the parent outcome collection, or bytes32(0) if /// there's no parent. /// @param conditionId Condition ID of the outcome collection to combine with the parent outcome /// collection. /// @param indexSet Index set of the outcome collection to combine with the parent outcome /// collection. function getCollectionId(bytes32 parentCollectionId, bytes32 conditionId, uint256 indexSet) internal view returns (bytes32) { uint256 x1 = uint256(keccak256(abi.encodePacked(conditionId, indexSet))); bool odd = x1 >> 255 != 0; uint256 y1; uint256 yy; do { x1 = addmod(x1, 1, P); yy = addmod(mulmod(x1, mulmod(x1, x1, P), P), B, P); y1 = sqrt(yy); } while (mulmod(y1, y1, P) != yy); if ((odd && y1 % 2 == 0) || (!odd && y1 % 2 == 1)) y1 = P - y1; uint256 x2 = uint256(parentCollectionId); if (x2 != 0) { odd = x2 >> 254 != 0; x2 = (x2 << 2) >> 2; yy = addmod(mulmod(x2, mulmod(x2, x2, P), P), B, P); uint256 y2 = sqrt(yy); if ((odd && y2 % 2 == 0) || (!odd && y2 % 2 == 1)) y2 = P - y2; require(mulmod(y2, y2, P) == yy, "invalid parent collection ID"); (bool success, bytes memory ret) = address(6).staticcall(abi.encode(x1, y1, x2, y2)); require(success, "ecadd failed"); (x1, y1) = abi.decode(ret, (uint256, uint256)); } if (y1 % 2 == 1) x1 ^= 1 << 254; return bytes32(x1); } /// @dev Constructs a position ID from a collateral token and an outcome collection. These IDs /// are used as the ERC-1155 ID for this contract. /// @param collateralToken Collateral token which backs the position. /// @param collectionId ID of the outcome collection associated with this position. function getPositionId(address collateralToken, bytes32 collectionId) internal pure returns (uint256) { return uint256(keccak256(abi.encodePacked(collateralToken, collectionId))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import {CTHelpers} from "./CTHelpers.sol"; /// @title Helpers /// @notice Helper functions for the NegRiskAdapter /// @author Mike Shrieve ([email protected]) library Helpers { /// @notice Returns the positionIds corresponding to _conditionId /// @param _collateral - the collateral address /// @param _conditionId - the conditionId /// @return positionIds - length 2 array of position ids function positionIds(address _collateral, bytes32 _conditionId) internal view returns (uint256[] memory) { uint256[] memory positionIds_ = new uint256[](2); // YES positionIds_[0] = CTHelpers.getPositionId(_collateral, CTHelpers.getCollectionId(bytes32(0), _conditionId, 1)); // NO positionIds_[1] = CTHelpers.getPositionId(_collateral, CTHelpers.getCollectionId(bytes32(0), _conditionId, 2)); return positionIds_; } /// @notice Returns an array with each element set to the same value /// @param _length - the length of the array /// @param _value - the value of each element /// @return values_ - the array of values function values(uint256 _length, uint256 _value) internal pure returns (uint256[] memory) { uint256[] memory values_ = new uint256[](_length); uint256 i; while (i < _length) { values_[i] = _value; unchecked { ++i; } } return values_; } /// @notice returns the partition for a binary conditional token /// @return partition - the partition [1,2] = [0b01, 0b10] function partition() internal pure returns (uint256[] memory) { uint256[] memory partition_ = new uint256[](2); // YES partition_[0] = 1; // NO partition_[1] = 2; return partition_; } /// @notice returns the payouts for a binary conditional token /// @notice payouts are [1,0] if _outcome is true and [0,1] otherwise /// @param _outcome - the boolean outcome /// @return payouts - the payouts function payouts(bool _outcome) internal pure returns (uint256[] memory) { uint256[] memory payouts_ = new uint256[](2); // YES payouts_[0] = _outcome ? 1 : 0; // NO payouts_[1] = _outcome ? 0 : 1; return payouts_; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @title NegRiskIdLib /// @notice Functions for the NegRiskAdapter Market and QuestionIds /// @notice MarketIds are the keccak256 hash of the oracle, feeBips, and metadata, with the final 8 bits set to 0 /// @notice QuestionIds share the first 31 bytes with their corresponding MarketId, and the final byte consists of the /// questionIndex /// @author Mike Shrieve ([email protected]) library NegRiskIdLib { bytes32 private constant MASK = bytes32(type(uint256).max) << 8; /// @notice Returns the MarketId for a given oracle, feeBips, and metadata /// @param _oracle - the oracle address /// @param _feeBips - the feeBips, out of 10_000 /// @param _metadata - the market metadata /// @return marketId - the marketId function getMarketId(address _oracle, uint256 _feeBips, bytes memory _metadata) internal pure returns (bytes32) { return keccak256(abi.encode(_oracle, _feeBips, _metadata)) & MASK; } /// @notice Returns the MarketId for a given QuestionId /// @param _questionId - the questionId /// @return marketId - the marketId function getMarketId(bytes32 _questionId) internal pure returns (bytes32) { return _questionId & MASK; } /// @notice Returns the QuestionId for a given MarketId and questionIndex /// @param _marketId - the marketId /// @param _questionIndex - the questionIndex /// @return questionId - the questionId function getQuestionId(bytes32 _marketId, uint8 _questionIndex) internal pure returns (bytes32) { unchecked { return bytes32(uint256(_marketId) + _questionIndex); } } /// @notice Returns the questionIndex for a given QuestionId /// @param _questionId - the questionId /// @return questionIndex - the questionIndex function getQuestionIndex(bytes32 _questionId) internal pure returns (uint8) { return uint8(uint256(_questionId)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @notice references to IERC20 are replaced by address /// @notice Interface for Gnosis Conditional Tokens interface IERC1155 { event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); function balanceOf(address owner, uint256 id) external view returns (uint256); function balanceOfBatch(address[] memory owners, uint256[] memory ids) external view returns (uint256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address owner, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external; } interface IConditionalTokensEE { event ConditionPreparation( bytes32 indexed conditionId, address indexed oracle, bytes32 indexed questionId, uint256 outcomeSlotCount ); event ConditionResolution( bytes32 indexed conditionId, address indexed oracle, bytes32 indexed questionId, uint256 outcomeSlotCount, uint256[] payoutNumerators ); /// @dev Emitted when a position is successfully split. event PositionSplit( address indexed stakeholder, address collateralToken, bytes32 indexed parentCollectionId, bytes32 indexed conditionId, uint256[] partition, uint256 amount ); /// @dev Emitted when positions are successfully merged. event PositionsMerge( address indexed stakeholder, address collateralToken, bytes32 indexed parentCollectionId, bytes32 indexed conditionId, uint256[] partition, uint256 amount ); event PayoutRedemption( address indexed redeemer, address indexed collateralToken, bytes32 indexed parentCollectionId, bytes32 conditionId, uint256[] indexSets, uint256 payout ); } interface IConditionalTokens is IConditionalTokensEE, IERC1155 { function payoutNumerators(bytes32 conditionId, uint256 index) external view returns (uint256); function payoutDenominator(bytes32 conditionId) external view returns (uint256); /// @dev This function prepares a condition by initializing a payout vector associated with the /// condition. /// @param oracle The account assigned to report the result for the prepared condition. /// @param questionId An identifier for the question to be answered by the oracle. /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. /// Must not exceed 256. function prepareCondition(address oracle, bytes32 questionId, uint256 outcomeSlotCount) external; /// @dev Called by the oracle for reporting results of conditions. Will set the payout vector /// for the condition with the ID ``keccak256(abi.encodePacked(oracle, questionId, /// outcomeSlotCount))``, where oracle is the message sender, questionId is one of the /// parameters of this function, and outcomeSlotCount is the length of the payouts parameter, /// which contains the payoutNumerators for each outcome slot of the condition. /// @param questionId The question ID the oracle is answering for /// @param payouts The oracle's answer function reportPayouts(bytes32 questionId, uint256[] calldata payouts) external; /// @dev This function splits a position. If splitting from the collateral, this contract will /// attempt to transfer `amount` collateral from the message sender to itself. Otherwise, this /// contract will burn `amount` stake held by the message sender in the position being split /// worth of EIP 1155 tokens. Regardless, if successful, `amount` stake will be minted in the /// split target positions. If any of the transfers, mints, or burns fail, the transaction will /// revert. The transaction will also revert if the given partition is trivial, invalid, or /// refers to more slots than the condition is prepared with. /// @param collateralToken The address of the positions' backing collateral token. /// @param parentCollectionId The ID of the outcome collections common to the position being /// split and the split target positions. May be null, in which only the collateral is shared. /// @param conditionId The ID of the condition to split on. /// @param partition An array of disjoint index sets representing a nontrivial partition of the /// outcome slots of the given condition. E.g. A|B and C but not A|B and B|C (is not disjoint). /// Each element's a number which, together with the condition, represents the outcome /// collection. E.g. 0b110 is A|B, 0b010 is B, etc. /// @param amount The amount of collateral or stake to split. function splitPosition( address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint256[] calldata partition, uint256 amount ) external; function mergePositions( address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint256[] calldata partition, uint256 amount ) external; function redeemPositions( address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint256[] calldata indexSets ) external; /// @dev Gets the outcome slot count of a condition. /// @param conditionId ID of the condition. /// @return Number of outcome slots associated with a condition, or zero if condition has not /// been prepared yet. function getOutcomeSlotCount(bytes32 conditionId) external view returns (uint256); /// @dev Constructs a condition ID from an oracle, a question ID, and the outcome slot count for /// the question. /// @param oracle The account assigned to report the result for the prepared condition. /// @param questionId An identifier for the question to be answered by the oracle. /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. /// Must not exceed 256. function getConditionId(address oracle, bytes32 questionId, uint256 outcomeSlotCount) external pure returns (bytes32); /// @dev Constructs an outcome collection ID from a parent collection and an outcome collection. /// @param parentCollectionId Collection ID of the parent outcome collection, or bytes32(0) if /// there's no parent. /// @param conditionId Condition ID of the outcome collection to combine with the parent outcome /// collection. /// @param indexSet Index set of the outcome collection to combine with the parent outcome /// collection. function getCollectionId(bytes32 parentCollectionId, bytes32 conditionId, uint256 indexSet) external view returns (bytes32); /// @dev Constructs a position ID from a collateral token and an outcome collection. These IDs /// are used as the ERC-1155 ID for this contract. /// @param collateralToken Collateral token which backs the position. /// @param collectionId ID of the outcome collection associated with this position. function getPositionId(address collateralToken, bytes32 collectionId) external pure returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import {IAuth} from "./interfaces/IAuth.sol"; /// @title Auth /// @author Jon Amenechi ([email protected]) /// @notice Provides access control modifiers abstract contract Auth is IAuth { /// @notice Auth mapping(address => uint256) public admins; modifier onlyAdmin() { if (admins[msg.sender] != 1) revert NotAdmin(); _; } constructor() { admins[msg.sender] = 1; } /// @notice Adds an Admin /// @param admin - The address of the admin function addAdmin(address admin) external onlyAdmin { admins[admin] = 1; emit NewAdmin(msg.sender, admin); } /// @notice Removes an admin /// @param admin - The address of the admin to be removed function removeAdmin(address admin) external onlyAdmin { admins[admin] = 0; emit RemovedAdmin(msg.sender, admin); } /// @notice Renounces Admin privileges from the caller function renounceAdmin() external onlyAdmin { admins[msg.sender] = 0; emit RemovedAdmin(msg.sender, msg.sender); } /// @notice Checks if an address is an admin /// @param addr - The address to be checked function isAdmin(address addr) external view returns (bool) { return admins[addr] == 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; interface IAuthEE { error NotAdmin(); /// @notice Emitted when a new admin is added event NewAdmin(address indexed admin, address indexed newAdminAddress); /// @notice Emitted when an admin is removed event RemovedAdmin(address indexed admin, address indexed removedAdmin); } interface IAuth is IAuthEE { function isAdmin(address) external view returns (bool); function addAdmin(address) external; function removeAdmin(address) external; function renounceAdmin() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @notice the MarketData user-defined type, a zero-cost abstraction over bytes32 type MarketData is bytes32; // md[0] = questionCount // md[1] = determined // md[2] = result // md[3:4] = feeBips // md[12:32] = oracle using MarketDataLib for MarketData global; /// @title MarketDataLib /// @notice Library for dealing with the MarketData user-defined bytes32 type /// @author Mike Shrieve ([email protected]) library MarketDataLib { error DeterminedFlagAlreadySet(); /// @notice used to increment the questionCount uint256 constant INCREMENT = uint256(bytes32(bytes1(0x01))); /// @notice extracts the oracle address from MarketData /// @return oracle - the address of the oracle function oracle(MarketData _data) internal pure returns (address) { return address(uint160(uint256(MarketData.unwrap(_data)))); } /// @notice extracts the questionCount from MarketData /// @return questionCount - the number of questions in the market function questionCount(MarketData _data) internal pure returns (uint256) { return uint256(uint8(MarketData.unwrap(_data)[0])); } /// @notice increments the questionCount /// @notice does _not_ check to see if the questionCount is already at the maximum value /// @return marketData - the modified MarketData function incrementQuestionCount(MarketData _data) internal pure returns (MarketData) { bytes32 data = MarketData.unwrap(_data); data = bytes32(uint256(data) + INCREMENT); return MarketData.wrap(data); } /// @notice extracts the determined flag from MarketData /// @return determined - true if the market has been determined, i.e. if one of the questions was resolved true function determined(MarketData _data) internal pure returns (bool) { return MarketData.unwrap(_data)[1] == 0x00 ? false : true; } /// @notice marks the market as determined /// @param _result - the result of the market, i.e., the index of the question that was resolved true /// @return marketData - the modified MarketData function determine(MarketData _data, uint256 _result) internal pure returns (MarketData) { bytes32 data = MarketData.unwrap(_data); if (data[1] != 0x00) revert DeterminedFlagAlreadySet(); data |= bytes32(bytes1(0x01)) >> 8; data |= bytes32(bytes1(uint8(_result))) >> 16; return MarketData.wrap(data); } /// @notice initializes the MarketData type /// @param _oracle - the address of the oracle /// @param _feeBips - the feeBips, out of 10_000 /// @return marketData - the initialized MarketData function initialize(address _oracle, uint256 _feeBips) internal pure returns (MarketData) { bytes32 data; data |= bytes32(bytes2(uint16(_feeBips))) >> 24; data |= bytes32(uint256(uint160(_oracle))); return MarketData.wrap(data); } /// @notice extracts the result from MarketData, i.e., the index of the question that was resolved true /// @notice if the market has not been determined, returns zero /// @return result - the index of the question that was resolved true, or zero function result(MarketData _data) internal pure returns (uint256) { return uint256(uint8(MarketData.unwrap(_data)[2])); } /// @notice extracts the feeBips from MarketData, out of 10_000 /// @return feeBips - the feeBips function feeBips(MarketData _data) internal pure returns (uint256) { return uint256(uint16(bytes2(MarketData.unwrap(_data) << 24))); } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/", "forge-gas-snapshot/=lib/forge-gas-snapshot/src/", "openzeppelin-contracts/=lib/ctf-exchange/lib/openzeppelin-contracts/contracts/", "common/=lib/ctf-exchange/src/common/", "creator/=lib/ctf-exchange/src/creator/", "ctf-exchange/=lib/ctf-exchange/src/", "dev/=lib/ctf-exchange/src/dev/", "exchange-fee-module/=lib/exchange-fee-module/src/", "exchange/=lib/ctf-exchange/src/exchange/", "openzeppelin/=lib/ctf-exchange/lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_ctf","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DeterminedFlagAlreadySet","type":"error"},{"inputs":[],"name":"FeeBipsOutOfBounds","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidIndexSet","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"MarketAlreadyDetermined","type":"error"},{"inputs":[],"name":"MarketAlreadyPrepared","type":"error"},{"inputs":[],"name":"MarketNotPrepared","type":"error"},{"inputs":[],"name":"NoConvertiblePositions","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotApprovedForAll","type":"error"},{"inputs":[],"name":"OnlyOracle","type":"error"},{"inputs":[],"name":"UnexpectedCollateralToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeBips","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"MarketPrepared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdminAddress","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"questionId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"outcome","type":"bool"}],"name":"OutcomeReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"conditionId","type":"bytes32"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"}],"name":"PayoutRedemption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeholder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"conditionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PositionSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeholder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"indexSet","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PositionsConverted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakeholder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"conditionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PositionsMerge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"marketId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"questionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"QuestionPrepared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"address","name":"removedAdmin","type":"address"}],"name":"RemovedAdmin","type":"event"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NO_TOKEN_BURN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"col","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"uint256","name":"_indexSet","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"convertPositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ctf","outputs":[{"internalType":"contract IConditionalTokens","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_questionId","type":"bytes32"}],"name":"getConditionId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getDetermined","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getFeeBips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getMarketData","outputs":[{"internalType":"MarketData","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_questionId","type":"bytes32"},{"internalType":"bool","name":"_outcome","type":"bool"}],"name":"getPositionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getQuestionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"}],"name":"getResult","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralToken","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"_conditionId","type":"bytes32"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mergePositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_conditionId","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mergePositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feeBips","type":"uint256"},{"internalType":"bytes","name":"_metadata","type":"bytes"}],"name":"prepareMarket","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_marketId","type":"bytes32"},{"internalType":"bytes","name":"_metadata","type":"bytes"}],"name":"prepareQuestion","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_conditionId","type":"bytes32"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"redeemPositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_questionId","type":"bytes32"},{"internalType":"bool","name":"_outcome","type":"bool"}],"name":"reportOutcome","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralToken","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"_conditionId","type":"bytes32"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"splitPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_conditionId","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"splitPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wcol","outputs":[{"internalType":"contract WrappedCollateral","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101006040523480156200001257600080fd5b5060405162005ed038038062005ed083398101604081905262000035916200023b565b33600090815260016020818152604092839020919091556001600160a01b0385811660805284811660a081905290841660e052825163313ce56760e01b815292518593919263313ce56792600480820193918290030181865afa158015620000a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000c7919062000285565b604051620000d59062000210565b6001600160a01b03909216825260ff166020820152604001604051809103906000f0801580156200010a573d6000803e3d6000fd5b506001600160a01b0390811660c081905260405163095ea7b360e01b8152918516600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000162573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001889190620002b1565b5060a05160c05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af1158015620001e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002069190620002b1565b50505050620002d5565b61174d806200478383390190565b80516001600160a01b03811681146200023657600080fd5b919050565b6000806000606084860312156200025157600080fd5b6200025c846200021e565b92506200026c602085016200021e565b91506200027c604085016200021e565b90509250925092565b6000602082840312156200029857600080fd5b815160ff81168114620002aa57600080fd5b9392505050565b600060208284031215620002c457600080fd5b81518015158114620002aa57600080fd5b60805160a05160c05160e05161436a62000419600039600081816105ba015281816118e90152611aae0152600081816103e501528181610bc301528181610e8201528181610f3101528181610ff3015281816110cf015281816111cf015281816112810152818161158d015281816118c2015281816119ad01528181611c4301528181611d5501528181611e0201528181611ec00152612c2d01526000818161044d01528181610b0101528181610d7e0152610e250152600081816102750152818161062a015281816107ee015281816108b1015281816109c601528181610ef501528181610fb2015281816110f801528181611193015281816116dc0152818161179a01528181611a7101528181611b2d01528181611ca801528181611d1901528181611f980152818161211c015281816121fa0152612c06015261436a6000f3fe608060405234801561001057600080fd5b506004361061020a5760003560e01c80638a0db6151161012a578063bc197c81116100bd578063dbeccb231161008c578063f23a6e6111610071578063f23a6e6114610569578063f242432a146105a2578063fbfa77cf146105b557600080fd5b8063dbeccb2314610543578063e200affd1461055657600080fd5b8063bc197c81146104a8578063c64748c414610514578063d73792a914610527578063dafaf94a1461053057600080fd5b8063a78695b0116100f9578063a78695b014610448578063add4c7841461046f578063b10c5c1714610482578063b7f75d2c1461049557600080fd5b80638a0db615146104075780638bad0c0a1461041a5780639e7212ad14610422578063a3d7da1d1461043557600080fd5b8063429b62e5116101a2578063752b5ba511610171578063752b5ba51461039f5780637ad7fe36146103b25780637ae2e67b146103cd5780637e3b74c3146103e057600080fd5b8063429b62e5146103395780634e1273f414610359578063704802751461037957806372ce42751461038c57600080fd5b806322a9339f116101de57806322a9339f1461027057806324d7806c146102bc5780632582cb5e1461030657806330f4f4bb1461031957600080fd5b8062fdd58e1461020f57806304329c03146102355780631785f53c146102485780631d69b48d1461025d575b600080fd5b61022261021d3660046137d2565b6105dc565b6040519081526020015b60405180910390f35b6102226102433660046137fc565b61069f565b61025b610256366004613815565b610703565b005b61022261026b366004613879565b61079f565b6102977f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022c565b6102f66102ca366004613815565b73ffffffffffffffffffffffffffffffffffffffff166000908152600160208190526040909120541490565b604051901515815260200161022c565b6102226103143660046137fc565b61096b565b6102226103273660046137fc565b60009081526020819052604090205490565b610222610347366004613815565b60016020526000908152604090205481565b61036c6103673660046139d2565b610986565b60405161022c9190613acd565b61025b610387366004613815565b610a60565b61025b61039a366004613b25565b610aff565b6102226103ad366004613ba6565b610b96565b61029773a5ef39c3d3e10d0b270233af41cac69796b1296681565b6102f66103db3660046137fc565b610c3f565b6102977f000000000000000000000000000000000000000000000000000000000000000081565b610222610415366004613879565b610c57565b61025b610cf7565b61025b610430366004613b25565b610d7c565b61025b610443366004613bd6565b610e0b565b6102977f000000000000000000000000000000000000000000000000000000000000000081565b61022261047d3660046137fc565b6110b0565b61025b610490366004613bd6565b6110c8565b6102226104a33660046137fc565b611330565b6104e36104b6366004613bf8565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161022c565b61025b610522366004613cb3565b611348565b61022261271081565b61029761053e3660046137fc565b611c28565b61025b610551366004613cdf565b611c3c565b61025b610564366004613ba6565b611f8c565b6104e3610577366004613d1e565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b61025b6105b0366004613d1e565b612087565b6102977f000000000000000000000000000000000000000000000000000000000000000081565b6040517efdd58e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390526000917f00000000000000000000000000000000000000000000000000000000000000009091169062fdd58e90604401602060405180830381865afa158015610672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106969190613d96565b90505b92915050565b604080513060601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166020808301919091526034820184905260026054808401919091528351808403909101815260749092019092528051910120600090610699565b336000908152600160208190526040909120541461074d576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600160205260408082208290555133917f787a2e12f4a55b658b8f573c32432ee11a5e8b51677d1e1e937aaf6a0bb5776e91a350565b60008060006107ad86612273565b9150915060006107bc8361069f565b6040517fd42dc0c2000000000000000000000000000000000000000000000000000000008152600481018290529091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063d42dc0c290602401602060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190613d96565b600003610923576040517fd96ee75400000000000000000000000000000000000000000000000000000000815230600482015260248101849052600260448201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063d96ee75490606401600060405180830381600087803b15801561090a57600080fd5b505af115801561091e573d6000803e3d6000fd5b505050505b82877faac410f87d423a922a7b226ac68f0c2eaf5bf6d15e644ac0758c7f96e2c253f784898960405161095893929190613df8565b60405180910390a3509095945050505050565b60008181526020819052604081205460d81c61ffff16610699565b6040517f4e1273f400000000000000000000000000000000000000000000000000000000815260609073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634e1273f4906109fd9086908690600401613e12565b600060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106969190810190613e7f565b3360009081526001602081905260409091205414610aaa576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600160208190526040808320919091555133917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc91a350565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610b84576040517f155a4b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8e8482610e0b565b505050505050565b600080610bbd81610ba68661069f565b85610bb2576002610bb5565b60015b60ff16612358565b604080517f000000000000000000000000000000000000000000000000000000000000000060601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603480830185905283518084039091018152605490920190925280519101209091506000905b95945050505050565b600081815260208190526040812054610699906127ba565b600080610c9a8585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127f992505050565b90503373ffffffffffffffffffffffffffffffffffffffff16817ff059ab16d1ca60e123eab60e3c02b68faf060347c701a5d14885a8e1def7b3a8878787604051610ce793929190613df8565b60405180910390a3949350505050565b3360009081526001602081905260409091205414610d41576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152600160205260408082208290555182917f787a2e12f4a55b658b8f573c32432ee11a5e8b51677d1e1e937aaf6a0bb5776e91a3565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610e01576040517f155a4b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8e84826110c8565b610e4d73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846128f7565b6040517fbf376c7a000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063bf376c7a90604401600060405180830381600087803b158015610edb57600080fd5b505af1158015610eef573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166372ce42757f00000000000000000000000000000000000000000000000000000000000000006000801b85610f5d6129e9565b866040518663ffffffff1660e01b8152600401610f7e959493929190613f10565b600060405180830381600087803b158015610f9857600080fd5b505af1158015610fac573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632eb2c2d630336110187f000000000000000000000000000000000000000000000000000000000000000087612a54565b611023600287612b57565b6040518563ffffffff1660e01b81526004016110429493929190613f5d565b600060405180830381600087803b15801561105c57600080fd5b505af1158015611070573d6000803e3d6000fd5b50506040518381528492503391507fbbed930dbfb7907ae2d60ddf78345610214f26419a0128df39b6cc3d9e5df9b0906020015b60405180910390a35050565b60008181526020819052604081205461069990612bd9565b60006110f47f000000000000000000000000000000000000000000000000000000000000000084612a54565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6333084611140600288612b57565b6040518563ffffffff1660e01b815260040161115f9493929190613f5d565b600060405180830381600087803b15801561117957600080fd5b505af115801561118d573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639e7212ad7f00000000000000000000000000000000000000000000000000000000000000006000801b866111fb6129e9565b876040518663ffffffff1660e01b815260040161121c959493929190613f10565b600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b50506040517f39f47693000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1692506339f476939150604401600060405180830381600087803b1580156112dc57600080fd5b505af11580156112f0573d6000803e3d6000fd5b50506040518481528592503391507fba33ac50d8894676597e6e35dc09cff59854708b642cd069d21eb9c7ca072a049060200160405180910390a3505050565b60008181526020819052604081205461069990612be6565b6000838152602081905260408120549061136182612be6565b905073ffffffffffffffffffffffffffffffffffffffff82166113b0576040517fb664949500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181116113ea576040517f24f2dfe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600003611424576040517f9667d38100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83811c1561145e576040517f9667d38100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260000361146d575050505050565b6000805b82821015611493576001821b861615611488576001015b816001019150611471565b600061149f8285613ff4565b905060008267ffffffffffffffff8111156114bc576114bc6138c5565b6040519080825280602002602001820160405280156114e5578160200160208202803683370190505b50905060008267ffffffffffffffff811115611503576115036138c5565b60405190808252806020026020018201604052801561152c578160200160208202803683370190505b50905060008367ffffffffffffffff81111561154a5761154a6138c5565b604051908082528060200260200182016040528015611573578160200160208202803683370190505b50905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a0712d686115bc8b87614007565b6040518263ffffffff1660e01b81526004016115da91815260200190565b600060405180830381600087803b1580156115f457600080fd5b505af1158015611608573d6000803e3d6000fd5b50505050600080600097505b888810156116d85760ff88168d016001891b8d161561166157611638816000610b96565b86848151811061164a5761164a61401e565b6020026020010181815250508260010192506116cc565b61166c816001610b96565b85838151811061167e5761167e61401e565b602002602001018181525050611695816000610b96565b8483815181106116a7576116a761401e565b6020026020010181815250506116c56116bf8261069f565b8d612bef565b8160010191505b88600101985050611614565b50507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6337fa5ef39c3d3e10d0b270233af41cac69796b12966b80367e2fe6c6f7041543fbf60601c8661174788518f612b57565b6040518563ffffffff1660e01b81526004016117669493929190613f5d565b600060405180830381600087803b15801561178057600080fd5b505af1158015611794573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6307fa5ef39c3d3e10d0b270233af41cac69796b12966b80367e2fe6c6f7041543fbf60601c84611804898f612b57565b6040518563ffffffff1660e01b81526004016118239493929190613f5d565b600060405180830381600087803b15801561183d57600080fd5b505af1158015611851573d6000803e3d6000fd5b506000925061271091505060d88a901c61ffff1661186f908c614007565b611879919061407c565b90506000611887828c613ff4565b9050600185511115611a62576000600186516118a39190613ff4565b905082156119965773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016630357371d7f00000000000000000000000000000000000000000000000000000000000000006119128685614007565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561197d57600080fd5b505af1158015611991573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016630357371d336119dd8585614007565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015611a4857600080fd5b505af1158015611a5c573d6000803e3d6000fd5b50505050505b835115611bc7578115611b2b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6307f000000000000000000000000000000000000000000000000000000000000000087611ad9895188612b57565b6040518563ffffffff1660e01b8152600401611af89493929190613f5d565b600060405180830381600087803b158015611b1257600080fd5b505af1158015611b26573d6000803e3d6000fd5b505050505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6303387611b75895187612b57565b6040518563ffffffff1660e01b8152600401611b949493929190613f5d565b600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b505050505b8b8d3373ffffffffffffffffffffffffffffffffffffffff167fb03d19dddbc72a87e735ff0ea3b57bef133ebe44e1894284916a84044deb367e8e604051611c1191815260200190565b60405180910390a450505050505050505050505050565b600081815260208190526040812054610699565b6000611c687f000000000000000000000000000000000000000000000000000000000000000085612a54565b6040517f2eb2c2d600000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632eb2c2d690611ce590339030908690899089906004016140db565b600060405180830381600087803b158015611cff57600080fd5b505af1158015611d13573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301b7037c7f00000000000000000000000000000000000000000000000000000000000000006000801b87611d816129e9565b6040518563ffffffff1660e01b8152600401611da09493929190614145565b600060405180830381600087803b158015611dba57600080fd5b505af1158015611dce573d6000803e3d6000fd5b50506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600092507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691506370a0823190602401602060405180830381865afa158015611e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e839190613d96565b90508015611f32576040517f39f47693000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906339f4769390604401600060405180830381600087803b158015611f1957600080fd5b505af1158015611f2d573d6000803e3d6000fd5b505050505b843373ffffffffffffffffffffffffffffffffffffffff167f9140a6a270ef945260c03894b3c6b3b2695e9d5101feef0ff24fec960cfd3224868685604051611f7d93929190614180565b60405180910390a35050505050565b611f968282612ca6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c49298ac83611fdc84612e26565b6040518363ffffffff1660e01b8152600401611ff99291906141a4565b600060405180830381600087803b15801561201357600080fd5b505af1158015612027573d6000803e3d6000fd5b5050505081612055837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690565b60405183151581527f9e9fa7fd355160bd4cd3f22d4333519354beff1f5689bde87f2c5e63d8d484b2906020016110a4565b33600090815260016020819052604090912054146120d1576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fe985e9c500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301523360248301527f0000000000000000000000000000000000000000000000000000000000000000169063e985e9c590604401602060405180830381865afa158015612163573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218791906141c5565b6121bd576040517fcd7769ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f242432a90612239908990899089908990899089906004016141e2565b600060405180830381600087803b15801561225357600080fd5b505af1158015612267573d6000803e3d6000fd5b50505050505050505050565b60008181526020819052604081205481908073ffffffffffffffffffffffffffffffffffffffff81166122d2576040517fb664949500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81163314612321576040517f80fee10500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61232a82612be6565b925060ff83168501935061233d82612eb2565b60009586526020869052604090952094909455509092909150565b6000808383604051602001612377929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120905060ff81901c15156000805b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd476001850893507f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760037f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4780878809870908905061243781612ee6565b9150807f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47838409036123ba578280156124785750612476600283614234565b155b806124965750821580156124965750612492600283614234565b6001145b156124c8576124c5827f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47613ff4565b91505b8780156127755760fe81901c151593507f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760037f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47808485098409089150600061255283612ee6565b90508480156125695750612567600282614234565b155b806125875750841580156125875750612583600282614234565b6001145b156125b9576125b6817f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47613ff4565b90505b827f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478283091461264a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f696e76616c696420706172656e7420636f6c6c656374696f6e2049440000000060448201526064015b60405180910390fd5b60408051602081018890529081018590526060810183905260808101829052600090819060069060a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526126ac9161426c565b600060405180830381855afa9150503d80600081146126e7576040519150601f19603f3d011682016040523d82523d6000602084013e6126ec565b606091505b509150915081612758576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6563616464206661696c656400000000000000000000000000000000000000006044820152606401612641565b8080602001905181019061276c9190614288565b90985095505050505b612780600284614234565b6001036127ad577f4000000000000000000000000000000000000000000000000000000000000000851894505b5092979650505050505050565b60008160011a60f81b7fff0000000000000000000000000000000000000000000000000000000000000016156127f1576001610699565b600092915050565b60003361280781858561369d565b6000818152602081905260408120549193508173ffffffffffffffffffffffffffffffffffffffff1614612867576040517fd2b4c0c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127108511156128a3576040517ffc520af500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82167cffff00000000000000000000000000000000000000000000000000000060d887901b161760008481526020819052604090205550909392505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806129e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401612641565b5050505050565b60408051600280825260608083018452926000929190602083019080368337019050509050600181600081518110612a2357612a2361401e565b602002602001018181525050600281600181518110612a4457612a4461401e565b6020908102919091010152919050565b60408051600280825260608083018452926000929190602083019080368337019050509050612b0384612a8a6000866001612358565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b16602082015260348101829052600090605401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209392505050565b81600081518110612b1657612b1661401e565b6020908102919091010152612b3284612a8a6000866002612358565b81600181518110612b4557612b4561401e565b60209081029190910101529392505050565b606060008367ffffffffffffffff811115612b7457612b746138c5565b604051908082528060200260200182016040528015612b9d578160200160208202803683370190505b50905060005b84811015612bd15783828281518110612bbe57612bbe61401e565b6020908102919091010152600101612ba3565b509392505050565b60008160025b1a92915050565b60008181612bdf565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166372ce42757f0000000000000000000000000000000000000000000000000000000000000000600085612c576129e9565b866040518663ffffffff1660e01b8152600401612c78959493929190613f10565b600060405180830381600087803b158015612c9257600080fd5b505af1158015610b8e573d6000803e3d6000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00821660008181526020819052604090205460ff8416908073ffffffffffffffffffffffffffffffffffffffff8116612d2b576040517fb664949500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81163314612d7a576040517f80fee10500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d8382612be6565b8310612dbb576040517f4e23d03500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b841515600103610b8e57612dce826127ba565b15612e05576040517fe3b0238900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e0f82846136f7565b600085815260208190526040902055505050505050565b6040805160028082526060808301845292600092919060208301908036833701905050905082612e57576000612e5a565b60015b60ff1681600081518110612e7057612e7061401e565b60200260200101818152505082612e88576001612e8b565b60005b60ff1681600181518110612ea157612ea161401e565b602090810291909101015292915050565b600081612edf7f0100000000000000000000000000000000000000000000000000000000000000826142ac565b9392505050565b60007f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47808380099150808283098181820990508181840992508183850993508184840992508183840990508181820982818309905082818209905082818209905082818309915082828609945082858609915082828309915082828509935082848509915082828309915082828309915082828509915082828609945082858609915082828309915082828309915082828609915082828509935082848609945082858609915082828309915082828509935082848509915082828309905082818209905082818209905082818309915082828609945082858509935082848509915082828309915082828309915082828609945082858609915082828309915082828609915082828309915082828309915082828609915082828509935082848509915082828309905082818209905082818309905082818509905082818209905082818209905082818209905082818209905082818309915082828609945082858609915082828609915082828509935082848509915082828509915082828309915082828309905082818309905082818209838182099050838182099050838182099050838182099050838183099150508281830991508282860994508285850993508284850991508282860994508285850993508284860994508285850993508284860994508285860991508282860991508282830991508282850993508284850991508282830991508282860994508285850993508284850991508282850991508282860994508285850993508284860994508285850993508284850991508282830991508282850991508282860994508285860991508282860991508282850993508284860994508285850993508284860994508285850993508284850991508282850991508282830991508282860994508285850993508284850991508282850991508282830991508282860994508285860991508282830990508281820990508281830990508281860990508281820990508281820990508281820990508281820990508281830991508282850993508284860994508285850993508284860994508285860991508282860991508282830991508282830991508282830991508282860991508282850993508284850991508282850991508282830991508282860994508285860991508282860991508282850993508284860994508285860991508282830991508282850993508284860994508285860991508282850993508284860994508285850993508284850991508282850991508282860994508285850993508284850991508282850991508282830991508282830991508282860994508285860991508282830991508282830991508282860991508282850993508284860994508285860991508282860990508281820990508281820990508281830991508282850993508284850991508282860994508285850993508284860994508285850993508284860994508285850993508284850991508282850990508281850991508282830991508282830991508282820991505081818509935081848409925081838509935081848409925081838509935081848509905081818509905081818409925050808284099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808383099392505050565b6040516000907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00906136d7908690869086906020016142bf565b604051602081830303815290604052805190602001201690509392505050565b6000828060011a60f81b7fff00000000000000000000000000000000000000000000000000000000000000161561375a576040517fb36eb03600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7dff000000000000000000000000000000000000000000000000000000000060e884901b16177e0100000000000000000000000000000000000000000000000000000000000017905092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137cd57600080fd5b919050565b600080604083850312156137e557600080fd5b6137ee836137a9565b946020939093013593505050565b60006020828403121561380e57600080fd5b5035919050565b60006020828403121561382757600080fd5b610696826137a9565b60008083601f84011261384257600080fd5b50813567ffffffffffffffff81111561385a57600080fd5b60208301915083602082850101111561387257600080fd5b9250929050565b60008060006040848603121561388e57600080fd5b83359250602084013567ffffffffffffffff8111156138ac57600080fd5b6138b886828701613830565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561393b5761393b6138c5565b604052919050565b600067ffffffffffffffff82111561395d5761395d6138c5565b5060051b60200190565b600082601f83011261397857600080fd5b8135602061398d61398883613943565b6138f4565b82815260059290921b840181019181810190868411156139ac57600080fd5b8286015b848110156139c757803583529183019183016139b0565b509695505050505050565b600080604083850312156139e557600080fd5b823567ffffffffffffffff808211156139fd57600080fd5b818501915085601f830112613a1157600080fd5b81356020613a2161398883613943565b82815260059290921b84018101918181019089841115613a4057600080fd5b948201945b83861015613a6557613a56866137a9565b82529482019490820190613a45565b96505086013592505080821115613a7b57600080fd5b50613a8885828601613967565b9150509250929050565b600081518084526020808501945080840160005b83811015613ac257815187529582019590820190600101613aa6565b509495945050505050565b6020815260006106966020830184613a92565b60008083601f840112613af257600080fd5b50813567ffffffffffffffff811115613b0a57600080fd5b6020830191508360208260051b850101111561387257600080fd5b60008060008060008060a08789031215613b3e57600080fd5b613b47876137a9565b95506020870135945060408701359350606087013567ffffffffffffffff811115613b7157600080fd5b613b7d89828a01613ae0565b979a9699509497949695608090950135949350505050565b8015158114613ba357600080fd5b50565b60008060408385031215613bb957600080fd5b823591506020830135613bcb81613b95565b809150509250929050565b60008060408385031215613be957600080fd5b50508035926020909101359150565b60008060008060008060008060a0898b031215613c1457600080fd5b613c1d896137a9565b9750613c2b60208a016137a9565b9650604089013567ffffffffffffffff80821115613c4857600080fd5b613c548c838d01613ae0565b909850965060608b0135915080821115613c6d57600080fd5b613c798c838d01613ae0565b909650945060808b0135915080821115613c9257600080fd5b50613c9f8b828c01613830565b999c989b5096995094979396929594505050565b600080600060608486031215613cc857600080fd5b505081359360208301359350604090920135919050565b600080600060408486031215613cf457600080fd5b83359250602084013567ffffffffffffffff811115613d1257600080fd5b6138b886828701613ae0565b60008060008060008060a08789031215613d3757600080fd5b613d40876137a9565b9550613d4e602088016137a9565b94506040870135935060608701359250608087013567ffffffffffffffff811115613d7857600080fd5b613d8489828a01613830565b979a9699509497509295939492505050565b600060208284031215613da857600080fd5b5051919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201526000610c36604083018486613daf565b604080825283519082018190526000906020906060840190828701845b82811015613e6157815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101613e2f565b50505083810382850152613e758186613a92565b9695505050505050565b60006020808385031215613e9257600080fd5b825167ffffffffffffffff811115613ea957600080fd5b8301601f81018513613eba57600080fd5b8051613ec861398882613943565b81815260059190911b82018301908381019087831115613ee757600080fd5b928401925b82841015613f0557835182529284019290840190613eec565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015283604082015260a060608201526000613f4b60a0830185613a92565b90508260808301529695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060a06040830152613f9660a0830185613a92565b8281036060840152613fa88185613a92565b838103608090940193909352505060008152602001949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561069957610699613fc5565b808202811582820484141761069957610699613fc5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261408b5761408b61404d565b500490565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156140c257600080fd5b8260051b80836020870137939093016020019392505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a0604083015261411460a0830186613a92565b8281036060840152614127818587614090565b83810360809094019390935250506000815260200195945050505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000613e756080830184613a92565b604081526000614194604083018587614090565b9050826020830152949350505050565b8281526040602082015260006141bd6040830184613a92565b949350505050565b6000602082840312156141d757600080fd5b8151612edf81613b95565b600073ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525085604083015284606083015260a0608083015261422860a083018486613daf565b98975050505050505050565b6000826142435761424361404d565b500690565b60005b8381101561426357818101518382015260200161424b565b50506000910152565b6000825161427e818460208701614248565b9190910192915050565b6000806040838503121561429b57600080fd5b505080516020909101519092909150565b8082018082111561069957610699613fc5565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260008251806060840152614300816080850160208701614248565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160800194935050505056fea2646970667358221220cb002f701e1383f3770988bb92900d67a44a83a2d126941d16180c38af3bdf6664736f6c634300081300336101206040523480156200001257600080fd5b506040516200174d3803806200174d83398101604081905262000035916200016e565b6040518060400160405280601281526020017115dc985c1c19590810dbdb1b185d195c985b60721b8152506040518060400160405280600481526020016315d0d3d360e21b8152508282600090816200008f919062000262565b5060016200009e838262000262565b5060ff81166080524660a052620000b4620000d2565b60c05250503360e05250506001600160a01b031661010052620003ac565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516200010691906200032e565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600080604083850312156200018257600080fd5b82516001600160a01b03811681146200019a57600080fd5b602084015190925060ff81168114620001b257600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620001e857607f821691505b6020821081036200020957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200025d57600081815260208120601f850160051c81016020861015620002385750805b601f850160051c820191505b81811015620002595782815560010162000244565b5050505b505050565b81516001600160401b038111156200027e576200027e620001bd565b62000296816200028f8454620001d3565b846200020f565b602080601f831160018114620002ce5760008415620002b55750858301515b600019600386901b1c1916600185901b17855562000259565b600085815260208120601f198616915b82811015620002ff57888601518255948401946001909101908401620002de565b50858210156200031e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200033e81620001d3565b600182811680156200035957600181146200036f57620003a0565b60ff1984168752821515830287019450620003a0565b8760005260208060002060005b85811015620003975781548a8201529084019082016200037c565b50505082870194505b50929695505050505050565b60805160a05160c05160e051610100516113326200041b60003960008181610242015281816103f801526108e40152600081816102ce01528181610387015281816106ec015281816107750152610873015260006106a801526000610673015260006101db01526113326000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80636f307dc3116100cd578063a0712d6811610081578063bf376c7a11610066578063bf376c7a1461031e578063d505accf14610331578063dd62ed3e1461034457600080fd5b8063a0712d68146102f8578063a9059cbb1461030b57600080fd5b80637ecebe00116100b25780637ecebe00146102a95780638da5cb5b146102c957806395d89b41146102f057600080fd5b80636f307dc31461023d57806370a082311461028957600080fd5b806323b872dd116101245780633644e515116101095780633644e5151461020f57806339f476931461021757806342966c681461022a57600080fd5b806323b872dd146101c3578063313ce567146101d657600080fd5b80630357371d1461015657806306fdde031461016b578063095ea7b31461018957806318160ddd146101ac575b600080fd5b610169610164366004610fcb565b61036f565b005b610173610423565b6040516101809190610ff5565b60405180910390f35b61019c610197366004610fcb565b6104b1565b6040519015158152602001610180565b6101b560025481565b604051908152602001610180565b61019c6101d1366004611061565b61052b565b6101fd7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610180565b6101b561066f565b610169610225366004610fcb565b6106ca565b61016961023836600461109d565b6106d4565b6102647f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610180565b6101b56102973660046110b6565b60036020526000908152604090205481565b6101b56102b73660046110b6565b60056020526000908152604090205481565b6102647f000000000000000000000000000000000000000000000000000000000000000081565b610173610750565b61016961030636600461109d565b61075d565b61019c610319366004610fcb565b6107d6565b61016961032c366004610fcb565b61085b565b61016961033f3660046110d8565b610916565b6101b561035236600461114b565b600460209081526000928352604080842090915290825290205481565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103de576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61041f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383610c3a565b5050565b600080546104309061117e565b80601f016020809104026020016040519081016040528092919081815260200182805461045c9061117e565b80156104a95780601f1061047e576101008083540402835291602001916104a9565b820191906000526020600020905b81548152906001019060200180831161048c57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906105199086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105bf5761058d8382611200565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040812080548592906105f4908490611200565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061065c9087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146106a5576106a0610d0f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6103de3382610da9565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610743576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61074d3382610da9565b50565b600180546104309061117e565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146107cc576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61074d3382610e3f565b336000908152600360205260408120805483919083906107f7908490611200565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906105199086815260200190565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146108ca576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61090c73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084610eb0565b61041f8282610e3f565b42841015610985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064015b60405180910390fd5b6000600161099161066f565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610ae3573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610b5e57508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610bc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e4552000000000000000000000000000000000000604482015260640161097c565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610d09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161097c565b50505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051610d419190611213565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290610dde908490611200565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b8060026000828254610e5191906112e9565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610e33565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610f9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161097c565b5050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610fc657600080fd5b919050565b60008060408385031215610fde57600080fd5b610fe783610fa2565b946020939093013593505050565b600060208083528351808285015260005b8181101561102257858101830151858201604001528201611006565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008060006060848603121561107657600080fd5b61107f84610fa2565b925061108d60208501610fa2565b9150604084013590509250925092565b6000602082840312156110af57600080fd5b5035919050565b6000602082840312156110c857600080fd5b6110d182610fa2565b9392505050565b600080600080600080600060e0888a0312156110f357600080fd5b6110fc88610fa2565b965061110a60208901610fa2565b95506040880135945060608801359350608088013560ff8116811461112e57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561115e57600080fd5b61116783610fa2565b915061117560208401610fa2565b90509250929050565b600181811c9082168061119257607f821691505b6020821081036111cb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610525576105256111d1565b600080835481600182811c91508083168061122f57607f831692505b60208084108203611267577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b81801561127b57600181146112ae576112db565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00861689528415158502890196506112db565b60008a81526020902060005b868110156112d35781548b8201529085019083016112ba565b505084890196505b509498975050505050505050565b80820180821115610525576105256111d156fea2646970667358221220ad3d29a4463d14a148a3849050be8e5252fd8bc37be24d48ae47ffef67fa5b4664736f6c634300081300330000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea04760450000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000007f67327e88c258932d7d8f72950be0d46975e11d
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061020a5760003560e01c80638a0db6151161012a578063bc197c81116100bd578063dbeccb231161008c578063f23a6e6111610071578063f23a6e6114610569578063f242432a146105a2578063fbfa77cf146105b557600080fd5b8063dbeccb2314610543578063e200affd1461055657600080fd5b8063bc197c81146104a8578063c64748c414610514578063d73792a914610527578063dafaf94a1461053057600080fd5b8063a78695b0116100f9578063a78695b014610448578063add4c7841461046f578063b10c5c1714610482578063b7f75d2c1461049557600080fd5b80638a0db615146104075780638bad0c0a1461041a5780639e7212ad14610422578063a3d7da1d1461043557600080fd5b8063429b62e5116101a2578063752b5ba511610171578063752b5ba51461039f5780637ad7fe36146103b25780637ae2e67b146103cd5780637e3b74c3146103e057600080fd5b8063429b62e5146103395780634e1273f414610359578063704802751461037957806372ce42751461038c57600080fd5b806322a9339f116101de57806322a9339f1461027057806324d7806c146102bc5780632582cb5e1461030657806330f4f4bb1461031957600080fd5b8062fdd58e1461020f57806304329c03146102355780631785f53c146102485780631d69b48d1461025d575b600080fd5b61022261021d3660046137d2565b6105dc565b6040519081526020015b60405180910390f35b6102226102433660046137fc565b61069f565b61025b610256366004613815565b610703565b005b61022261026b366004613879565b61079f565b6102977f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604581565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022c565b6102f66102ca366004613815565b73ffffffffffffffffffffffffffffffffffffffff166000908152600160208190526040909120541490565b604051901515815260200161022c565b6102226103143660046137fc565b61096b565b6102226103273660046137fc565b60009081526020819052604090205490565b610222610347366004613815565b60016020526000908152604090205481565b61036c6103673660046139d2565b610986565b60405161022c9190613acd565b61025b610387366004613815565b610a60565b61025b61039a366004613b25565b610aff565b6102226103ad366004613ba6565b610b96565b61029773a5ef39c3d3e10d0b270233af41cac69796b1296681565b6102f66103db3660046137fc565b610c3f565b6102977f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e281565b610222610415366004613879565b610c57565b61025b610cf7565b61025b610430366004613b25565b610d7c565b61025b610443366004613bd6565b610e0b565b6102977f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417481565b61022261047d3660046137fc565b6110b0565b61025b610490366004613bd6565b6110c8565b6102226104a33660046137fc565b611330565b6104e36104b6366004613bf8565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161022c565b61025b610522366004613cb3565b611348565b61022261271081565b61029761053e3660046137fc565b611c28565b61025b610551366004613cdf565b611c3c565b61025b610564366004613ba6565b611f8c565b6104e3610577366004613d1e565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b61025b6105b0366004613d1e565b612087565b6102977f0000000000000000000000007f67327e88c258932d7d8f72950be0d46975e11d81565b6040517efdd58e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390526000917f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea04760459091169062fdd58e90604401602060405180830381865afa158015610672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106969190613d96565b90505b92915050565b604080513060601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166020808301919091526034820184905260026054808401919091528351808403909101815260749092019092528051910120600090610699565b336000908152600160208190526040909120541461074d576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600160205260408082208290555133917f787a2e12f4a55b658b8f573c32432ee11a5e8b51677d1e1e937aaf6a0bb5776e91a350565b60008060006107ad86612273565b9150915060006107bc8361069f565b6040517fd42dc0c2000000000000000000000000000000000000000000000000000000008152600481018290529091507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff169063d42dc0c290602401602060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190613d96565b600003610923576040517fd96ee75400000000000000000000000000000000000000000000000000000000815230600482015260248101849052600260448201527f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff169063d96ee75490606401600060405180830381600087803b15801561090a57600080fd5b505af115801561091e573d6000803e3d6000fd5b505050505b82877faac410f87d423a922a7b226ac68f0c2eaf5bf6d15e644ac0758c7f96e2c253f784898960405161095893929190613df8565b60405180910390a3509095945050505050565b60008181526020819052604081205460d81c61ffff16610699565b6040517f4e1273f400000000000000000000000000000000000000000000000000000000815260609073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea04760451690634e1273f4906109fd9086908690600401613e12565b600060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106969190810190613e7f565b3360009081526001602081905260409091205414610aaa576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152600160208190526040808320919091555133917ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc91a350565b7f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610b84576040517f155a4b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8e8482610e0b565b505050505050565b600080610bbd81610ba68661069f565b85610bb2576002610bb5565b60015b60ff16612358565b604080517f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603480830185905283518084039091018152605490920190925280519101209091506000905b95945050505050565b600081815260208190526040812054610699906127ba565b600080610c9a8585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127f992505050565b90503373ffffffffffffffffffffffffffffffffffffffff16817ff059ab16d1ca60e123eab60e3c02b68faf060347c701a5d14885a8e1def7b3a8878787604051610ce793929190613df8565b60405180910390a3949350505050565b3360009081526001602081905260409091205414610d41576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152600160205260408082208290555182917f787a2e12f4a55b658b8f573c32432ee11a5e8b51677d1e1e937aaf6a0bb5776e91a3565b7f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610e01576040517f155a4b5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8e84826110c8565b610e4d73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174163330846128f7565b6040517fbf376c7a000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e273ffffffffffffffffffffffffffffffffffffffff169063bf376c7a90604401600060405180830381600087803b158015610edb57600080fd5b505af1158015610eef573d6000803e3d6000fd5b505050507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff166372ce42757f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e26000801b85610f5d6129e9565b866040518663ffffffff1660e01b8152600401610f7e959493929190613f10565b600060405180830381600087803b158015610f9857600080fd5b505af1158015610fac573d6000803e3d6000fd5b505050507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d630336110187f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e287612a54565b611023600287612b57565b6040518563ffffffff1660e01b81526004016110429493929190613f5d565b600060405180830381600087803b15801561105c57600080fd5b505af1158015611070573d6000803e3d6000fd5b50506040518381528492503391507fbbed930dbfb7907ae2d60ddf78345610214f26419a0128df39b6cc3d9e5df9b0906020015b60405180910390a35050565b60008181526020819052604081205461069990612bd9565b60006110f47f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e284612a54565b90507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6333084611140600288612b57565b6040518563ffffffff1660e01b815260040161115f9493929190613f5d565b600060405180830381600087803b15801561117957600080fd5b505af115801561118d573d6000803e3d6000fd5b505050507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16639e7212ad7f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e26000801b866111fb6129e9565b876040518663ffffffff1660e01b815260040161121c959493929190613f10565b600060405180830381600087803b15801561123657600080fd5b505af115801561124a573d6000803e3d6000fd5b50506040517f39f47693000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e273ffffffffffffffffffffffffffffffffffffffff1692506339f476939150604401600060405180830381600087803b1580156112dc57600080fd5b505af11580156112f0573d6000803e3d6000fd5b50506040518481528592503391507fba33ac50d8894676597e6e35dc09cff59854708b642cd069d21eb9c7ca072a049060200160405180910390a3505050565b60008181526020819052604081205461069990612be6565b6000838152602081905260408120549061136182612be6565b905073ffffffffffffffffffffffffffffffffffffffff82166113b0576040517fb664949500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600181116113ea576040517f24f2dfe700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600003611424576040517f9667d38100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83811c1561145e576040517f9667d38100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260000361146d575050505050565b6000805b82821015611493576001821b861615611488576001015b816001019150611471565b600061149f8285613ff4565b905060008267ffffffffffffffff8111156114bc576114bc6138c5565b6040519080825280602002602001820160405280156114e5578160200160208202803683370190505b50905060008267ffffffffffffffff811115611503576115036138c5565b60405190808252806020026020018201604052801561152c578160200160208202803683370190505b50905060008367ffffffffffffffff81111561154a5761154a6138c5565b604051908082528060200260200182016040528015611573578160200160208202803683370190505b50905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e21663a0712d686115bc8b87614007565b6040518263ffffffff1660e01b81526004016115da91815260200190565b600060405180830381600087803b1580156115f457600080fd5b505af1158015611608573d6000803e3d6000fd5b50505050600080600097505b888810156116d85760ff88168d016001891b8d161561166157611638816000610b96565b86848151811061164a5761164a61401e565b6020026020010181815250508260010192506116cc565b61166c816001610b96565b85838151811061167e5761167e61401e565b602002602001018181525050611695816000610b96565b8483815181106116a7576116a761401e565b6020026020010181815250506116c56116bf8261069f565b8d612bef565b8160010191505b88600101985050611614565b50507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6337fa5ef39c3d3e10d0b270233af41cac69796b12966b80367e2fe6c6f7041543fbf60601c8661174788518f612b57565b6040518563ffffffff1660e01b81526004016117669493929190613f5d565b600060405180830381600087803b15801561178057600080fd5b505af1158015611794573d6000803e3d6000fd5b505050507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6307fa5ef39c3d3e10d0b270233af41cac69796b12966b80367e2fe6c6f7041543fbf60601c84611804898f612b57565b6040518563ffffffff1660e01b81526004016118239493929190613f5d565b600060405180830381600087803b15801561183d57600080fd5b505af1158015611851573d6000803e3d6000fd5b506000925061271091505060d88a901c61ffff1661186f908c614007565b611879919061407c565b90506000611887828c613ff4565b9050600185511115611a62576000600186516118a39190613ff4565b905082156119965773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e216630357371d7f0000000000000000000000007f67327e88c258932d7d8f72950be0d46975e11d6119128685614007565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561197d57600080fd5b505af1158015611991573d6000803e3d6000fd5b505050505b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e216630357371d336119dd8585614007565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015611a4857600080fd5b505af1158015611a5c573d6000803e3d6000fd5b50505050505b835115611bc7578115611b2b577f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6307f0000000000000000000000007f67327e88c258932d7d8f72950be0d46975e11d87611ad9895188612b57565b6040518563ffffffff1660e01b8152600401611af89493929190613f5d565b600060405180830381600087803b158015611b1257600080fd5b505af1158015611b26573d6000803e3d6000fd5b505050505b7f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d6303387611b75895187612b57565b6040518563ffffffff1660e01b8152600401611b949493929190613f5d565b600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b505050505b8b8d3373ffffffffffffffffffffffffffffffffffffffff167fb03d19dddbc72a87e735ff0ea3b57bef133ebe44e1894284916a84044deb367e8e604051611c1191815260200190565b60405180910390a450505050505050505050505050565b600081815260208190526040812054610699565b6000611c687f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e285612a54565b6040517f2eb2c2d600000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea04760451690632eb2c2d690611ce590339030908690899089906004016140db565b600060405180830381600087803b158015611cff57600080fd5b505af1158015611d13573d6000803e3d6000fd5b505050507f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff166301b7037c7f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e26000801b87611d816129e9565b6040518563ffffffff1660e01b8152600401611da09493929190614145565b600060405180830381600087803b158015611dba57600080fd5b505af1158015611dce573d6000803e3d6000fd5b50506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600092507f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e273ffffffffffffffffffffffffffffffffffffffff1691506370a0823190602401602060405180830381865afa158015611e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e839190613d96565b90508015611f32576040517f39f47693000000000000000000000000000000000000000000000000000000008152336004820152602481018290527f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e273ffffffffffffffffffffffffffffffffffffffff16906339f4769390604401600060405180830381600087803b158015611f1957600080fd5b505af1158015611f2d573d6000803e3d6000fd5b505050505b843373ffffffffffffffffffffffffffffffffffffffff167f9140a6a270ef945260c03894b3c6b3b2695e9d5101feef0ff24fec960cfd3224868685604051611f7d93929190614180565b60405180910390a35050505050565b611f968282612ca6565b7f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea047604573ffffffffffffffffffffffffffffffffffffffff1663c49298ac83611fdc84612e26565b6040518363ffffffff1660e01b8152600401611ff99291906141a4565b600060405180830381600087803b15801561201357600080fd5b505af1158015612027573d6000803e3d6000fd5b5050505081612055837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690565b60405183151581527f9e9fa7fd355160bd4cd3f22d4333519354beff1f5689bde87f2c5e63d8d484b2906020016110a4565b33600090815260016020819052604090912054146120d1576040517f7bfa4b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fe985e9c500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301523360248301527f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea0476045169063e985e9c590604401602060405180830381865afa158015612163573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218791906141c5565b6121bd576040517fcd7769ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea0476045169063f242432a90612239908990899089908990899089906004016141e2565b600060405180830381600087803b15801561225357600080fd5b505af1158015612267573d6000803e3d6000fd5b50505050505050505050565b60008181526020819052604081205481908073ffffffffffffffffffffffffffffffffffffffff81166122d2576040517fb664949500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81163314612321576040517f80fee10500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61232a82612be6565b925060ff83168501935061233d82612eb2565b60009586526020869052604090952094909455509092909150565b6000808383604051602001612377929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120905060ff81901c15156000805b7f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd476001850893507f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760037f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4780878809870908905061243781612ee6565b9150807f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47838409036123ba578280156124785750612476600283614234565b155b806124965750821580156124965750612492600283614234565b6001145b156124c8576124c5827f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47613ff4565b91505b8780156127755760fe81901c151593507f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4760037f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47808485098409089150600061255283612ee6565b90508480156125695750612567600282614234565b155b806125875750841580156125875750612583600282614234565b6001145b156125b9576125b6817f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47613ff4565b90505b827f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd478283091461264a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f696e76616c696420706172656e7420636f6c6c656374696f6e2049440000000060448201526064015b60405180910390fd5b60408051602081018890529081018590526060810183905260808101829052600090819060069060a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526126ac9161426c565b600060405180830381855afa9150503d80600081146126e7576040519150601f19603f3d011682016040523d82523d6000602084013e6126ec565b606091505b509150915081612758576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6563616464206661696c656400000000000000000000000000000000000000006044820152606401612641565b8080602001905181019061276c9190614288565b90985095505050505b612780600284614234565b6001036127ad577f4000000000000000000000000000000000000000000000000000000000000000851894505b5092979650505050505050565b60008160011a60f81b7fff0000000000000000000000000000000000000000000000000000000000000016156127f1576001610699565b600092915050565b60003361280781858561369d565b6000818152602081905260408120549193508173ffffffffffffffffffffffffffffffffffffffff1614612867576040517fd2b4c0c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127108511156128a3576040517ffc520af500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82167cffff00000000000000000000000000000000000000000000000000000060d887901b161760008481526020819052604090205550909392505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806129e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401612641565b5050505050565b60408051600280825260608083018452926000929190602083019080368337019050509050600181600081518110612a2357612a2361401e565b602002602001018181525050600281600181518110612a4457612a4461401e565b6020908102919091010152919050565b60408051600280825260608083018452926000929190602083019080368337019050509050612b0384612a8a6000866001612358565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b16602082015260348101829052600090605401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209392505050565b81600081518110612b1657612b1661401e565b6020908102919091010152612b3284612a8a6000866002612358565b81600181518110612b4557612b4561401e565b60209081029190910101529392505050565b606060008367ffffffffffffffff811115612b7457612b746138c5565b604051908082528060200260200182016040528015612b9d578160200160208202803683370190505b50905060005b84811015612bd15783828281518110612bbe57612bbe61401e565b6020908102919091010152600101612ba3565b509392505050565b60008160025b1a92915050565b60008181612bdf565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea0476045166372ce42757f0000000000000000000000003a3bd7bb9528e159577f7c2e685cc81a765002e2600085612c576129e9565b866040518663ffffffff1660e01b8152600401612c78959493929190613f10565b600060405180830381600087803b158015612c9257600080fd5b505af1158015610b8e573d6000803e3d6000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00821660008181526020819052604090205460ff8416908073ffffffffffffffffffffffffffffffffffffffff8116612d2b576040517fb664949500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81163314612d7a576040517f80fee10500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612d8382612be6565b8310612dbb576040517f4e23d03500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b841515600103610b8e57612dce826127ba565b15612e05576040517fe3b0238900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e0f82846136f7565b600085815260208190526040902055505050505050565b6040805160028082526060808301845292600092919060208301908036833701905050905082612e57576000612e5a565b60015b60ff1681600081518110612e7057612e7061401e565b60200260200101818152505082612e88576001612e8b565b60005b60ff1681600181518110612ea157612ea161401e565b602090810291909101015292915050565b600081612edf7f0100000000000000000000000000000000000000000000000000000000000000826142ac565b9392505050565b60007f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47808380099150808283098181820990508181840992508183850993508184840992508183840990508181820982818309905082818209905082818209905082818309915082828609945082858609915082828309915082828509935082848509915082828309915082828309915082828509915082828609945082858609915082828309915082828309915082828609915082828509935082848609945082858609915082828309915082828509935082848509915082828309905082818209905082818209905082818309915082828609945082858509935082848509915082828309915082828309915082828609945082858609915082828309915082828609915082828309915082828309915082828609915082828509935082848509915082828309905082818209905082818309905082818509905082818209905082818209905082818209905082818209905082818309915082828609945082858609915082828609915082828509935082848509915082828509915082828309915082828309905082818309905082818209838182099050838182099050838182099050838182099050838183099150508281830991508282860994508285850993508284850991508282860994508285850993508284860994508285850993508284860994508285860991508282860991508282830991508282850993508284850991508282830991508282860994508285850993508284850991508282850991508282860994508285850993508284860994508285850993508284850991508282830991508282850991508282860994508285860991508282860991508282850993508284860994508285850993508284860994508285850993508284850991508282850991508282830991508282860994508285850993508284850991508282850991508282830991508282860994508285860991508282830990508281820990508281830990508281860990508281820990508281820990508281820990508281820990508281830991508282850993508284860994508285850993508284860994508285860991508282860991508282830991508282830991508282830991508282860991508282850993508284850991508282850991508282830991508282860994508285860991508282860991508282850993508284860994508285860991508282830991508282850993508284860994508285860991508282850993508284860994508285850993508284850991508282850991508282860994508285850993508284850991508282850991508282830991508282830991508282860994508285860991508282830991508282830991508282860991508282850993508284860994508285860991508282860990508281820990508281820990508281830991508282850993508284850991508282860994508285850993508284860994508285850993508284860994508285850993508284850991508282850990508281850991508282830991508282830991508282820991505081818509935081848409925081838509935081848409925081838509935081848509905081818509905081818409925050808284099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808384099250808383099392505050565b6040516000907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00906136d7908690869086906020016142bf565b604051602081830303815290604052805190602001201690509392505050565b6000828060011a60f81b7fff00000000000000000000000000000000000000000000000000000000000000161561375a576040517fb36eb03600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7dff000000000000000000000000000000000000000000000000000000000060e884901b16177e0100000000000000000000000000000000000000000000000000000000000017905092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137cd57600080fd5b919050565b600080604083850312156137e557600080fd5b6137ee836137a9565b946020939093013593505050565b60006020828403121561380e57600080fd5b5035919050565b60006020828403121561382757600080fd5b610696826137a9565b60008083601f84011261384257600080fd5b50813567ffffffffffffffff81111561385a57600080fd5b60208301915083602082850101111561387257600080fd5b9250929050565b60008060006040848603121561388e57600080fd5b83359250602084013567ffffffffffffffff8111156138ac57600080fd5b6138b886828701613830565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561393b5761393b6138c5565b604052919050565b600067ffffffffffffffff82111561395d5761395d6138c5565b5060051b60200190565b600082601f83011261397857600080fd5b8135602061398d61398883613943565b6138f4565b82815260059290921b840181019181810190868411156139ac57600080fd5b8286015b848110156139c757803583529183019183016139b0565b509695505050505050565b600080604083850312156139e557600080fd5b823567ffffffffffffffff808211156139fd57600080fd5b818501915085601f830112613a1157600080fd5b81356020613a2161398883613943565b82815260059290921b84018101918181019089841115613a4057600080fd5b948201945b83861015613a6557613a56866137a9565b82529482019490820190613a45565b96505086013592505080821115613a7b57600080fd5b50613a8885828601613967565b9150509250929050565b600081518084526020808501945080840160005b83811015613ac257815187529582019590820190600101613aa6565b509495945050505050565b6020815260006106966020830184613a92565b60008083601f840112613af257600080fd5b50813567ffffffffffffffff811115613b0a57600080fd5b6020830191508360208260051b850101111561387257600080fd5b60008060008060008060a08789031215613b3e57600080fd5b613b47876137a9565b95506020870135945060408701359350606087013567ffffffffffffffff811115613b7157600080fd5b613b7d89828a01613ae0565b979a9699509497949695608090950135949350505050565b8015158114613ba357600080fd5b50565b60008060408385031215613bb957600080fd5b823591506020830135613bcb81613b95565b809150509250929050565b60008060408385031215613be957600080fd5b50508035926020909101359150565b60008060008060008060008060a0898b031215613c1457600080fd5b613c1d896137a9565b9750613c2b60208a016137a9565b9650604089013567ffffffffffffffff80821115613c4857600080fd5b613c548c838d01613ae0565b909850965060608b0135915080821115613c6d57600080fd5b613c798c838d01613ae0565b909650945060808b0135915080821115613c9257600080fd5b50613c9f8b828c01613830565b999c989b5096995094979396929594505050565b600080600060608486031215613cc857600080fd5b505081359360208301359350604090920135919050565b600080600060408486031215613cf457600080fd5b83359250602084013567ffffffffffffffff811115613d1257600080fd5b6138b886828701613ae0565b60008060008060008060a08789031215613d3757600080fd5b613d40876137a9565b9550613d4e602088016137a9565b94506040870135935060608701359250608087013567ffffffffffffffff811115613d7857600080fd5b613d8489828a01613830565b979a9699509497509295939492505050565b600060208284031215613da857600080fd5b5051919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201526000610c36604083018486613daf565b604080825283519082018190526000906020906060840190828701845b82811015613e6157815173ffffffffffffffffffffffffffffffffffffffff1684529284019290840190600101613e2f565b50505083810382850152613e758186613a92565b9695505050505050565b60006020808385031215613e9257600080fd5b825167ffffffffffffffff811115613ea957600080fd5b8301601f81018513613eba57600080fd5b8051613ec861398882613943565b81815260059190911b82018301908381019087831115613ee757600080fd5b928401925b82841015613f0557835182529284019290840190613eec565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015283604082015260a060608201526000613f4b60a0830185613a92565b90508260808301529695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060a06040830152613f9660a0830185613a92565b8281036060840152613fa88185613a92565b838103608090940193909352505060008152602001949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561069957610699613fc5565b808202811582820484141761069957610699613fc5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261408b5761408b61404d565b500490565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156140c257600080fd5b8260051b80836020870137939093016020019392505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a0604083015261411460a0830186613a92565b8281036060840152614127818587614090565b83810360809094019390935250506000815260200195945050505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000613e756080830184613a92565b604081526000614194604083018587614090565b9050826020830152949350505050565b8281526040602082015260006141bd6040830184613a92565b949350505050565b6000602082840312156141d757600080fd5b8151612edf81613b95565b600073ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525085604083015284606083015260a0608083015261422860a083018486613daf565b98975050505050505050565b6000826142435761424361404d565b500690565b60005b8381101561426357818101518382015260200161424b565b50506000910152565b6000825161427e818460208701614248565b9190910192915050565b6000806040838503121561429b57600080fd5b505080516020909101519092909150565b8082018082111561069957610699613fc5565b73ffffffffffffffffffffffffffffffffffffffff841681528260208201526060604082015260008251806060840152614300816080850160208701614248565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160800194935050505056fea2646970667358221220cb002f701e1383f3770988bb92900d67a44a83a2d126941d16180c38af3bdf6664736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea04760450000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000007f67327e88c258932d7d8f72950be0d46975e11d
-----Decoded View---------------
Arg [0] : _ctf (address): 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045
Arg [1] : _collateral (address): 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
Arg [2] : _vault (address): 0x7f67327E88c258932D7d8f72950bE0d46975E11D
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000004d97dcd97ec945f40cf65f87097ace5ea0476045
Arg [1] : 0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174
Arg [2] : 0000000000000000000000007f67327e88c258932d7d8f72950be0d46975e11d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ 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.