Overview
POL Balance
0 POL
POL Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
VRFV2Wrapper
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; import "./ConfirmedOwner.sol"; import "./interfaces/TypeAndVersionInterface.sol"; import "./VRFConsumerBaseV2.sol"; import "./interfaces/LinkTokenInterface.sol"; import "./interfaces/AggregatorV3Interface.sol"; import "./interfaces/VRFCoordinatorV2Interface.sol"; import "./interfaces/VRFV2WrapperInterface.sol"; import "./VRFV2WrapperConsumerBase.sol"; /** * @notice A wrapper for VRFCoordinatorV2 that provides an interface better suited to one-off * @notice requests for randomness. */ contract VRFV2Wrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2, VRFV2WrapperInterface { event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); LinkTokenInterface public immutable LINK; AggregatorV3Interface public immutable LINK_ETH_FEED; ExtendedVRFCoordinatorV2Interface public immutable COORDINATOR; uint64 public immutable SUBSCRIPTION_ID; // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) // and some arithmetic operations. uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; // lastRequestId is the request ID of the most recent VRF V2 request made by this wrapper. This // should only be relied on within the same transaction the request was made. uint256 public override lastRequestId; // Configuration fetched from VRFCoordinatorV2 // s_configured tracks whether this contract has been configured. If not configured, randomness // requests cannot be made. bool public s_configured; // s_disabled disables the contract when true. When disabled, new VRF requests cannot be made // but existing ones can still be fulfilled. bool public s_disabled; // s_fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed is // stale. int256 private s_fallbackWeiPerUnitLink; // s_stalenessSeconds is the number of seconds before we consider the feed price to be stale and // fallback to fallbackWeiPerUnitLink. uint32 private s_stalenessSeconds; // s_fulfillmentFlatFeeLinkPPM is the flat fee in millionths of LINK that VRFCoordinatorV2 // charges. uint32 private s_fulfillmentFlatFeeLinkPPM; // Other configuration // s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords // function. The cost for this gas is passed to the user. uint32 private s_wrapperGasOverhead; // s_coordinatorGasOverhead reflects the gas overhead of the coordinator's fulfillRandomWords // function. The cost for this gas is billed to the subscription, and must therefor be included // in the pricing for wrapped requests. This includes the gas costs of proof verification and // payment calculation in the coordinator. uint32 private s_coordinatorGasOverhead; // s_wrapperPremiumPercentage is the premium ratio in percentage. For example, a value of 0 // indicates no premium. A value of 15 indicates a 15 percent premium. uint8 private s_wrapperPremiumPercentage; // s_keyHash is the key hash to use when requesting randomness. Fees are paid based on current gas // fees, so this should be set to the highest gas lane on the network. bytes32 s_keyHash; // s_maxNumWords is the max number of words that can be requested in a single wrapped VRF request. uint8 s_maxNumWords; struct Callback { address callbackAddress; uint32 callbackGasLimit; uint256 requestGasPrice; int256 requestWeiPerUnitLink; uint256 juelsPaid; } mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks; constructor( address _link, address _linkEthFeed, address _coordinator ) ConfirmedOwner(msg.sender) VRFConsumerBaseV2(_coordinator) { LINK = LinkTokenInterface(_link); LINK_ETH_FEED = AggregatorV3Interface(_linkEthFeed); COORDINATOR = ExtendedVRFCoordinatorV2Interface(_coordinator); // Create this wrapper's subscription and add itself as a consumer. uint64 subId = ExtendedVRFCoordinatorV2Interface(_coordinator).createSubscription(); SUBSCRIPTION_ID = subId; ExtendedVRFCoordinatorV2Interface(_coordinator).addConsumer(subId, address(this)); } /** * @notice setConfig configures VRFV2Wrapper. * * @dev Sets wrapper-specific configuration based on the given parameters, and fetches any needed * @dev VRFCoordinatorV2 configuration from the coordinator. * * @param _wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords * function. * * @param _coordinatorGasOverhead reflects the gas overhead of the coordinator's * fulfillRandomWords function. * * @param _wrapperPremiumPercentage is the premium ratio in percentage for wrapper requests. * * @param _keyHash to use for requesting randomness. */ function setConfig( uint32 _wrapperGasOverhead, uint32 _coordinatorGasOverhead, uint8 _wrapperPremiumPercentage, bytes32 _keyHash, uint8 _maxNumWords ) external onlyOwner { s_wrapperGasOverhead = _wrapperGasOverhead; s_coordinatorGasOverhead = _coordinatorGasOverhead; s_wrapperPremiumPercentage = _wrapperPremiumPercentage; s_keyHash = _keyHash; s_maxNumWords = _maxNumWords; s_configured = true; // Get other configuration from coordinator (, , s_stalenessSeconds, ) = COORDINATOR.getConfig(); s_fallbackWeiPerUnitLink = COORDINATOR.getFallbackWeiPerUnitLink(); (s_fulfillmentFlatFeeLinkPPM, , , , , , , , ) = COORDINATOR.getFeeConfig(); } /** * @notice getConfig returns the current VRFV2Wrapper configuration. * * @return fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed * is stale. * * @return stalenessSeconds is the number of seconds before we consider the feed price to be stale * and fallback to fallbackWeiPerUnitLink. * * @return fulfillmentFlatFeeLinkPPM is the flat fee in millionths of LINK that VRFCoordinatorV2 * charges. * * @return wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords * function. The cost for this gas is passed to the user. * * @return coordinatorGasOverhead reflects the gas overhead of the coordinator's * fulfillRandomWords function. * * @return wrapperPremiumPercentage is the premium ratio in percentage. For example, a value of 0 * indicates no premium. A value of 15 indicates a 15 percent premium. * * @return keyHash is the key hash to use when requesting randomness. Fees are paid based on * current gas fees, so this should be set to the highest gas lane on the network. * * @return maxNumWords is the max number of words that can be requested in a single wrapped VRF * request. */ function getConfig() external view returns ( int256 fallbackWeiPerUnitLink, uint32 stalenessSeconds, uint32 fulfillmentFlatFeeLinkPPM, uint32 wrapperGasOverhead, uint32 coordinatorGasOverhead, uint8 wrapperPremiumPercentage, bytes32 keyHash, uint8 maxNumWords ) { return ( s_fallbackWeiPerUnitLink, s_stalenessSeconds, s_fulfillmentFlatFeeLinkPPM, s_wrapperGasOverhead, s_coordinatorGasOverhead, s_wrapperPremiumPercentage, s_keyHash, s_maxNumWords ); } /** * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current * @notice block. * * @dev This function relies on the transaction gas price which is not automatically set during * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. * * @param _callbackGasLimit is the gas limit used to estimate the price. */ function calculateRequestPrice(uint32 _callbackGasLimit) external view override onlyConfiguredNotDisabled returns (uint256) { int256 weiPerUnitLink = getFeedData(); return calculateRequestPriceInternal(_callbackGasLimit, tx.gasprice, weiPerUnitLink); } /** * @notice Estimates the price of a VRF request with a specific gas limit and gas price. * * @dev This is a convenience function that can be called in simulation to better understand * @dev pricing. * * @param _callbackGasLimit is the gas limit used to estimate the price. * @param _requestGasPriceWei is the gas price in wei used for the estimation. */ function estimateRequestPrice(uint32 _callbackGasLimit, uint256 _requestGasPriceWei) external view override onlyConfiguredNotDisabled returns (uint256) { int256 weiPerUnitLink = getFeedData(); return calculateRequestPriceInternal(_callbackGasLimit, _requestGasPriceWei, weiPerUnitLink); } function calculateRequestPriceInternal( uint256 _gas, uint256 _requestGasPrice, int256 _weiPerUnitLink ) internal view returns (uint256) { uint256 baseFee = (1e18 * _requestGasPrice * (_gas + s_wrapperGasOverhead + s_coordinatorGasOverhead)) / uint256(_weiPerUnitLink); uint256 feeWithPremium = (baseFee * (s_wrapperPremiumPercentage + 100)) / 100; uint256 feeWithFlatFee = feeWithPremium + (1e12 * uint256(s_fulfillmentFlatFeeLinkPPM)); return feeWithFlatFee; } /** * @notice onTokenTransfer is called by LinkToken upon payment for a VRF request. * * @dev Reverts if payment is too low. * * @param _sender is the sender of the payment, and the address that will receive a VRF callback * upon fulfillment. * * @param _amount is the amount of LINK paid in Juels. * * @param _data is the abi-encoded VRF request parameters: uint32 callbackGasLimit, * uint16 requestConfirmations, and uint32 numWords. */ function onTokenTransfer( address _sender, uint256 _amount, bytes calldata _data ) external onlyConfiguredNotDisabled { require(msg.sender == address(LINK), "only callable from LINK"); (uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords) = abi.decode( _data, (uint32, uint16, uint32) ); uint32 eip150Overhead = getEIP150Overhead(callbackGasLimit); int256 weiPerUnitLink = getFeedData(); uint256 price = calculateRequestPriceInternal(callbackGasLimit, tx.gasprice, weiPerUnitLink); require(_amount >= price, "fee too low"); require(numWords <= s_maxNumWords, "numWords too high"); uint256 requestId = COORDINATOR.requestRandomWords( s_keyHash, SUBSCRIPTION_ID, requestConfirmations, callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, numWords ); s_callbacks[requestId] = Callback({ callbackAddress: _sender, callbackGasLimit: callbackGasLimit, requestGasPrice: tx.gasprice, requestWeiPerUnitLink: weiPerUnitLink, juelsPaid: _amount }); lastRequestId = requestId; } /** * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw LINK revenue. * * @param _recipient is the address that should receive the LINK funds. * * @param _amount is the amount of LINK in Juels that should be withdrawn. */ function withdraw(address _recipient, uint256 _amount) external onlyOwner { LINK.transfer(_recipient, _amount); } /** * @notice enable this contract so that new requests can be accepted. */ function enable() external onlyOwner { s_disabled = false; } /** * @notice disable this contract so that new requests will be rejected. When disabled, new requests * @notice will revert but existing requests can still be fulfilled. */ function disable() external onlyOwner { s_disabled = true; } function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { Callback memory callback = s_callbacks[_requestId]; delete s_callbacks[_requestId]; require(callback.callbackAddress != address(0), "request not found"); // This should never happen VRFV2WrapperConsumerBase c; bytes memory resp = abi.encodeWithSelector(c.rawFulfillRandomWords.selector, _requestId, _randomWords); bool success = callWithExactGas(callback.callbackGasLimit, callback.callbackAddress, resp); if (!success) { emit WrapperFulfillmentFailed(_requestId, callback.callbackAddress); } } function getFeedData() private view returns (int256) { bool staleFallback = s_stalenessSeconds > 0; uint256 timestamp; int256 weiPerUnitLink; (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); // solhint-disable-next-line not-rely-on-time if (staleFallback && s_stalenessSeconds < block.timestamp - timestamp) { weiPerUnitLink = s_fallbackWeiPerUnitLink; } require(weiPerUnitLink >= 0, "Invalid LINK wei price"); return weiPerUnitLink; } /** * @dev Calculates extra amount of gas required for running an assembly call() post-EIP150. */ function getEIP150Overhead(uint32 gas) private pure returns (uint32) { return gas / 63 + 1; } /** * @dev calls target address with exactly gasAmount gas and data as calldata * or reverts if at least gasAmount gas is not available. */ function callWithExactGas( uint256 gasAmount, address target, bytes memory data ) private returns (bool success) { // solhint-disable-next-line no-inline-assembly assembly { let g := gas() // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). // We want to ensure that we revert if gasAmount > 63//64*gas available // as we do not want to provide them with less, however that check itself costs // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able // to revert if gasAmount > 63//64*gas available. if lt(g, GAS_FOR_CALL_EXACT_CHECK) { revert(0, 0) } g := sub(g, GAS_FOR_CALL_EXACT_CHECK) // if g - g//64 <= gasAmount, revert // (we subtract g//64 because of EIP-150) if iszero(gt(sub(g, div(g, 64)), gasAmount)) { revert(0, 0) } // solidity calls check that a contract actually exists at the destination, so we do the same if iszero(extcodesize(target)) { revert(0, 0) } // call and return whether we succeeded. ignore return data // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) } return success; } function typeAndVersion() external pure virtual override returns (string memory) { return "VRFV2Wrapper 1.0.0"; } modifier onlyConfiguredNotDisabled() { require(s_configured, "wrapper is not configured"); require(!s_disabled, "wrapper is disabled"); _; } } interface ExtendedVRFCoordinatorV2Interface is VRFCoordinatorV2Interface { function getConfig() external view returns ( uint16 minimumRequestConfirmations, uint32 maxGasLimit, uint32 stalenessSeconds, uint32 gasAfterPaymentCalculation ); function getFallbackWeiPerUnitLink() external view returns (int256); function getFeeConfig() external view returns ( uint32 fulfillmentFlatFeeLinkPPMTier1, uint32 fulfillmentFlatFeeLinkPPMTier2, uint32 fulfillmentFlatFeeLinkPPMTier3, uint32 fulfillmentFlatFeeLinkPPMTier4, uint32 fulfillmentFlatFeeLinkPPMTier5, uint24 reqsForTier2, uint24 reqsForTier3, uint24 reqsForTier4, uint24 reqsForTier5 ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ConfirmedOwnerWithProposal.sol"; /** * @title The ConfirmedOwner contract * @notice A contract with helpers for basic contract ownership. */ contract ConfirmedOwner is ConfirmedOwnerWithProposal { constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/OwnableInterface.sol"; /** * @title The ConfirmedOwner contract * @notice A contract with helpers for basic contract ownership. */ contract ConfirmedOwnerWithProposal is OwnableInterface { address private s_owner; address private s_pendingOwner; event OwnershipTransferRequested(address indexed from, address indexed to); event OwnershipTransferred(address indexed from, address indexed to); constructor(address newOwner, address pendingOwner) { require(newOwner != address(0), "Cannot set owner to zero"); s_owner = newOwner; if (pendingOwner != address(0)) { _transferOwnership(pendingOwner); } } /** * @notice Allows an owner to begin transferring ownership to a new address, * pending. */ function transferOwnership(address to) public override onlyOwner { _transferOwnership(to); } /** * @notice Allows an ownership transfer to be completed by the recipient. */ function acceptOwnership() external override { require(msg.sender == s_pendingOwner, "Must be proposed owner"); address oldOwner = s_owner; s_owner = msg.sender; s_pendingOwner = address(0); emit OwnershipTransferred(oldOwner, msg.sender); } /** * @notice Get the current owner */ function owner() public view override returns (address) { return s_owner; } /** * @notice validate, transfer ownership, and emit relevant events */ function _transferOwnership(address to) private { require(to != msg.sender, "Cannot transfer to self"); s_pendingOwner = to; emit OwnershipTransferRequested(s_owner, to); } /** * @notice validate access */ function _validateOwnership() internal view { require(msg.sender == s_owner, "Only callable by owner"); } /** * @notice Reverts if called by anyone other than the contract owner. */ modifier onlyOwner() { _validateOwnership(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface OwnableInterface { function owner() external returns (address); function transferOwnership(address recipient) external; function acceptOwnership() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; abstract contract TypeAndVersionInterface { function typeAndVersion() external pure virtual returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance(address owner, address spender) external view returns (uint256 remaining); function approve(address spender, uint256 value) external returns (bool success); function balanceOf(address owner) external view returns (uint256 balance); function decimals() external view returns (uint8 decimalPlaces); function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); function increaseApproval(address spender, uint256 subtractedValue) external; function name() external view returns (string memory tokenName); function symbol() external view returns (string memory tokenSymbol); function totalSupply() external view returns (uint256 totalTokensIssued); function transfer(address to, uint256 value) external returns (bool success); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool success); function transferFrom( address from, address to, uint256 value ) external returns (bool success); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFV2WrapperInterface { /** * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only * be relied option within the same transaction that the request was made. */ function lastRequestId() external view returns (uint256); /** * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current * @notice block. * * @dev This function relies on the transaction gas price which is not automatically set during * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. * * @param _callbackGasLimit is the gas limit used to estimate the price. */ function calculateRequestPrice(uint32 _callbackGasLimit) external view returns (uint256); /** * @notice Estimates the price of a VRF request with a specific gas limit and gas price. * * @dev This is a convenience function that can be called in simulation to better understand * @dev pricing. * * @param _callbackGasLimit is the gas limit used to estimate the price. * @param _requestGasPriceWei is the gas price in wei used for the estimation. */ function estimateRequestPrice(uint32 _callbackGasLimit, uint256 _requestGasPriceWei) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/LinkTokenInterface.sol"; import "./interfaces/VRFV2WrapperInterface.sol"; /** ******************************************************************************* * @notice Interface for contracts using VRF randomness through the VRF V2 wrapper * ******************************************************************************** * @dev PURPOSE * * @dev Create VRF V2 requests without the need for subscription management. Rather than creating * @dev and funding a VRF V2 subscription, a user can use this wrapper to create one off requests, * @dev paying up front rather than at fulfillment. * * @dev Since the price is determined using the gas price of the request transaction rather than * @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas * @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFV2WrapperConsumerBase. The consumer must be funded * @dev with enough LINK to make the request, otherwise requests will revert. To request randomness, * @dev call the 'requestRandomness' function with the desired VRF parameters. This function handles * @dev paying for the request based on the current pricing. * * @dev Consumers must implement the fullfillRandomWords function, which will be called during * @dev fulfillment with the randomness result. */ abstract contract VRFV2WrapperConsumerBase { LinkTokenInterface internal immutable LINK; VRFV2WrapperInterface internal immutable VRF_V2_WRAPPER; /** * @param _link is the address of LinkToken * @param _vrfV2Wrapper is the address of the VRFV2Wrapper contract */ constructor(address _link, address _vrfV2Wrapper) { LINK = LinkTokenInterface(_link); VRF_V2_WRAPPER = VRFV2WrapperInterface(_vrfV2Wrapper); } /** * @dev Requests randomness from the VRF V2 wrapper. * * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's * fulfillRandomWords function. * @param _requestConfirmations is the number of confirmations to wait before fulfilling the * request. A higher number of confirmations increases security by reducing the likelihood * that a chain re-org changes a published randomness outcome. * @param _numWords is the number of random words to request. * * @return requestId is the VRF V2 request ID of the newly created randomness request. */ function requestRandomness( uint32 _callbackGasLimit, uint16 _requestConfirmations, uint32 _numWords ) internal returns (uint256 requestId) { LINK.transferAndCall( address(VRF_V2_WRAPPER), VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit), abi.encode(_callbackGasLimit, _requestConfirmations, _numWords) ); return VRF_V2_WRAPPER.lastRequestId(); } /** * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must * @notice implement it. * * @param _requestId is the VRF V2 request ID. * @param _randomWords is the randomness result. */ function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual; function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { require(msg.sender == address(VRF_V2_WRAPPER), "only VRF V2 wrapper can fulfill"); fulfillRandomWords(_requestId, _randomWords); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; import "../VRFV2WrapperConsumerBase.sol"; import "../ConfirmedOwner.sol"; contract VRFV2WrapperConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); event WrapperRequestMade(uint256 indexed requestId, uint256 paid); struct RequestStatus { uint256 paid; bool fulfilled; uint256[] randomWords; } mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; constructor(address _link, address _vrfV2Wrapper) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} function makeRequest( uint32 _callbackGasLimit, uint16 _requestConfirmations, uint32 _numWords ) external onlyOwner returns (uint256 requestId) { requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); uint256 paid = VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit); s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false}); emit WrapperRequestMade(requestId, paid); return requestId; } function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { require(s_requests[_requestId].paid > 0, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); } function getRequestStatus(uint256 _requestId) external view returns ( uint256 paid, bool fulfilled, uint256[] memory randomWords ) { require(s_requests[_requestId].paid > 0, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.paid, request.fulfilled, request.randomWords); } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_link","type":"address"},{"internalType":"address","name":"_linkEthFeed","type":"address"},{"internalType":"address","name":"_coordinator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"consumer","type":"address"}],"name":"WrapperFulfillmentFailed","type":"event"},{"inputs":[],"name":"COORDINATOR","outputs":[{"internalType":"contract ExtendedVRFCoordinatorV2Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LINK","outputs":[{"internalType":"contract LinkTokenInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LINK_ETH_FEED","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBSCRIPTION_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"}],"name":"calculateRequestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"},{"internalType":"uint256","name":"_requestGasPriceWei","type":"uint256"}],"name":"estimateRequestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"internalType":"int256","name":"fallbackWeiPerUnitLink","type":"int256"},{"internalType":"uint32","name":"stalenessSeconds","type":"uint32"},{"internalType":"uint32","name":"fulfillmentFlatFeeLinkPPM","type":"uint32"},{"internalType":"uint32","name":"wrapperGasOverhead","type":"uint32"},{"internalType":"uint32","name":"coordinatorGasOverhead","type":"uint32"},{"internalType":"uint8","name":"wrapperPremiumPercentage","type":"uint8"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"uint8","name":"maxNumWords","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"s_callbacks","outputs":[{"internalType":"address","name":"callbackAddress","type":"address"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint256","name":"requestGasPrice","type":"uint256"},{"internalType":"int256","name":"requestWeiPerUnitLink","type":"int256"},{"internalType":"uint256","name":"juelsPaid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_configured","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_disabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_wrapperGasOverhead","type":"uint32"},{"internalType":"uint32","name":"_coordinatorGasOverhead","type":"uint32"},{"internalType":"uint8","name":"_wrapperPremiumPercentage","type":"uint8"},{"internalType":"bytes32","name":"_keyHash","type":"bytes32"},{"internalType":"uint8","name":"_maxNumWords","type":"uint8"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50604051620023b9380380620023b98339810160408190526200003591620002c2565b8033806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c081620001f9565b5050506001600160601b0319606091821b811660805284821b811660a05283821b811660c0529082901b1660e0526040805163288688f960e21b815290516000916001600160a01b0384169163a21a23e49160048082019260209290919082900301818787803b1580156200013457600080fd5b505af115801562000149573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016f91906200030c565b60c081901b6001600160c01b03191661010052604051631cd0704360e21b81526001600160401b03821660048201523060248201529091506001600160a01b03831690637341c10c90604401600060405180830381600087803b158015620001d657600080fd5b505af1158015620001eb573d6000803e3d6000fd5b50505050505050506200033e565b6001600160a01b038116331415620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620002bd57600080fd5b919050565b600080600060608486031215620002d857600080fd5b620002e384620002a5565b9250620002f360208501620002a5565b91506200030360408501620002a5565b90509250925092565b6000602082840312156200031f57600080fd5b81516001600160401b03811681146200033757600080fd5b9392505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160c01c611fe8620003d1600039600081816101810152610bef01526000818161026e01528181610bb001528181610f2f0152818161101001526110ab0152600081816103e7015261155f01526000818161020501528181610a0201526111fd0152600081816104f2015261055a0152611fe86000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c80637fb5d19d116100d8578063ad1783611161008c578063f2fde38b11610066578063f2fde38b146104ab578063f3fef3a3146104be578063fc2a88c3146104d157600080fd5b8063ad178361146103e2578063c15ce4d714610409578063c3f909d41461041c57600080fd5b8063a3907d71116100bd578063a3907d71146103b5578063a4c0ed36146103bd578063a608a1e1146103d057600080fd5b80637fb5d19d146103845780638da5cb5b1461039757600080fd5b80633b2bcbf11161012f57806348baa1c51161011457806348baa1c5146102b157806357a8070a1461035f57806379ba50971461037c57600080fd5b80633b2bcbf1146102695780634306d3541461029057600080fd5b80631b6b6d23116101605780631b6b6d23146102005780631fe543e31461024c5780632f2770db1461026157600080fd5b8063030932bb1461017c578063181f5a77146101c1575b600080fd5b6101a37f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b604080518082018252601281527f56524656325772617070657220312e302e300000000000000000000000000000602082015290516101b89190611d7b565b6102277f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b8565b61025f61025a366004611aaa565b6104da565b005b61025f61059a565b6102277f000000000000000000000000000000000000000000000000000000000000000081565b6102a361029e366004611b99565b6105d0565b6040519081526020016101b8565b61031b6102bf366004611a91565b600860205260009081526040902080546001820154600283015460039093015473ffffffffffffffffffffffffffffffffffffffff8316937401000000000000000000000000000000000000000090930463ffffffff16929085565b6040805173ffffffffffffffffffffffffffffffffffffffff909616865263ffffffff9094166020860152928401919091526060830152608082015260a0016101b8565b60035461036c9060ff1681565b60405190151581526020016101b8565b61025f6106d7565b6102a3610392366004611c01565b6107d4565b60005473ffffffffffffffffffffffffffffffffffffffff16610227565b61025f6108da565b61025f6103cb366004611970565b61090c565b60035461036c90610100900460ff1681565b6102277f000000000000000000000000000000000000000000000000000000000000000081565b61025f610417366004611cd5565b610dea565b6004546005546006546007546040805194855263ffffffff80851660208701526401000000008504811691860191909152680100000000000000008404811660608601526c01000000000000000000000000840416608085015260ff700100000000000000000000000000000000909304831660a085015260c08401919091521660e0820152610100016101b8565b61025f6104b936600461192b565b611195565b61025f6104cc366004611946565b6111a9565b6102a360025481565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461058c576040517f1cf993f400000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b610596828261127e565b5050565b6105a2611489565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b60035460009060ff1661063f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610583565b600354610100900460ff16156106b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610583565b60006106bb61150c565b90506106ce8363ffffffff163a83611680565b9150505b919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610758576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610583565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60035460009060ff16610843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610583565b600354610100900460ff16156108b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610583565b60006108bf61150c565b90506108d28463ffffffff168483611680565b949350505050565b6108e2611489565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055565b60035460ff16610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610583565b600354610100900460ff16156109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610583565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c792063616c6c61626c652066726f6d204c494e4b0000000000000000006044820152606401610583565b60008080610a9984860186611bb6565b9250925092506000610aaa84611769565b90506000610ab661150c565b90506000610acb8663ffffffff163a84611680565b905080891015610b37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f66656520746f6f206c6f770000000000000000000000000000000000000000006044820152606401610583565b60075460ff1663ffffffff85161115610bac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e756d576f72647320746f6f20686967680000000000000000000000000000006044820152606401610583565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635d3b1d306006547f000000000000000000000000000000000000000000000000000000000000000089600560089054906101000a900463ffffffff16898d610c2e9190611e54565b610c389190611e54565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945267ffffffffffffffff909216602484015261ffff16604483015263ffffffff90811660648301528816608482015260a401602060405180830381600087803b158015610cb757600080fd5b505af1158015610ccb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cef9190611a19565b90506040518060a001604052808c73ffffffffffffffffffffffffffffffffffffffff1681526020018863ffffffff1681526020013a81526020018481526020018b8152506008600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff160217905550604082015181600101556060820151816002015560808201518160030155905050806002819055505050505050505050505050565b610df2611489565b6005805460ff808616700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff63ffffffff8981166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff918c166801000000000000000002919091167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff909516949094179390931792909216919091179091556006839055600780549183167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00928316179055600380549091166001179055604080517fc3f909d4000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163c3f909d4916004828101926080929190829003018186803b158015610f7557600080fd5b505afa158015610f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fad9190611a32565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555050604080517f356dac7100000000000000000000000000000000000000000000000000000000815290517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163356dac71916004808301926020929190829003018186803b15801561106b57600080fd5b505afa15801561107f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a39190611a19565b6004819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635fbbc0d26040518163ffffffff1660e01b81526004016101206040518083038186803b15801561111057600080fd5b505afa158015611124573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111489190611c1f565b50506005805463ffffffff909816640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909816979097179096555050505050505050505050565b61119d611489565b6111a681611787565b50565b6111b1611489565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401602060405180830381600087803b15801561124157600080fd5b505af1158015611255573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127991906119f7565b505050565b6000828152600860208181526040808420815160a081018352815473ffffffffffffffffffffffffffffffffffffffff808216835263ffffffff740100000000000000000000000000000000000000008304168387015260018401805495840195909552600284018054606085015260038501805460808601528b8a52979096527fffffffffffffffff00000000000000000000000000000000000000000000000090911690925591859055918490559290915581511661139b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f72657175657374206e6f7420666f756e640000000000000000000000000000006044820152606401610583565b600080631fe543e360e01b85856040516024016113b9929190611dee565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000611433846020015163ffffffff1685600001518461187d565b90508061148157835160405173ffffffffffffffffffffffffffffffffffffffff9091169087907fc551b83c151f2d1c7eeb938ac59008e0409f1c1dc1e2f112449d4d79b458902290600090a35b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461150a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610583565b565b600554604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905160009263ffffffff161515918391829173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163feaf968c9160048082019260a092909190829003018186803b1580156115a657600080fd5b505afa1580156115ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115de9190611d37565b50945090925084915050801561160457506115f98242611f15565b60055463ffffffff16105b1561160e57506004545b6000811215611679576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c6964204c494e4b20776569207072696365000000000000000000006044820152606401610583565b9392505050565b6005546000908190839063ffffffff6c0100000000000000000000000082048116916116ba91680100000000000000009091041688611e3c565b6116c49190611e3c565b6116d686670de0b6b3a7640000611ed8565b6116e09190611ed8565b6116ea9190611ea1565b60055490915060009060649061171790700100000000000000000000000000000000900460ff1682611e7c565b6117249060ff1684611ed8565b61172e9190611ea1565b60055490915060009061175490640100000000900463ffffffff1664e8d4a51000611ed8565b61175e9083611e3c565b979650505050505050565b6000611776603f83611eb5565b611781906001611e54565b92915050565b73ffffffffffffffffffffffffffffffffffffffff8116331415611807576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610583565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005a61138881101561188f57600080fd5b6113888103905084604082048203116118a757600080fd5b50823b6118b357600080fd5b60008083516020850160008789f1949350505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d257600080fd5b805162ffffff811681146106d257600080fd5b803560ff811681146106d257600080fd5b805169ffffffffffffffffffff811681146106d257600080fd5b60006020828403121561193d57600080fd5b611679826118c9565b6000806040838503121561195957600080fd5b611962836118c9565b946020939093013593505050565b6000806000806060858703121561198657600080fd5b61198f856118c9565b935060208501359250604085013567ffffffffffffffff808211156119b357600080fd5b818701915087601f8301126119c757600080fd5b8135818111156119d657600080fd5b8860208285010111156119e857600080fd5b95989497505060200194505050565b600060208284031215611a0957600080fd5b8151801515811461167957600080fd5b600060208284031215611a2b57600080fd5b5051919050565b60008060008060808587031215611a4857600080fd5b8451611a5381611fb9565b6020860151909450611a6481611fc9565b6040860151909350611a7581611fc9565b6060860151909250611a8681611fc9565b939692955090935050565b600060208284031215611aa357600080fd5b5035919050565b60008060408385031215611abd57600080fd5b8235915060208084013567ffffffffffffffff80821115611add57600080fd5b818601915086601f830112611af157600080fd5b813581811115611b0357611b03611f8a565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108582111715611b4657611b46611f8a565b604052828152858101935084860182860187018b1015611b6557600080fd5b600095505b83861015611b88578035855260019590950194938601938601611b6a565b508096505050505050509250929050565b600060208284031215611bab57600080fd5b813561167981611fc9565b600080600060608486031215611bcb57600080fd5b8335611bd681611fc9565b92506020840135611be681611fb9565b91506040840135611bf681611fc9565b809150509250925092565b60008060408385031215611c1457600080fd5b823561196281611fc9565b60008060008060008060008060006101208a8c031215611c3e57600080fd5b8951611c4981611fc9565b60208b0151909950611c5a81611fc9565b60408b0151909850611c6b81611fc9565b60608b0151909750611c7c81611fc9565b60808b0151909650611c8d81611fc9565b9450611c9b60a08b016118ed565b9350611ca960c08b016118ed565b9250611cb760e08b016118ed565b9150611cc66101008b016118ed565b90509295985092959850929598565b600080600080600060a08688031215611ced57600080fd5b8535611cf881611fc9565b94506020860135611d0881611fc9565b9350611d1660408701611900565b925060608601359150611d2b60808701611900565b90509295509295909350565b600080600080600060a08688031215611d4f57600080fd5b611d5886611911565b9450602086015193506040860151925060608601519150611d2b60808701611911565b600060208083528351808285015260005b81811015611da857858101830151858201604001528201611d8c565b81811115611dba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015611e2f57845183529383019391830191600101611e13565b5090979650505050505050565b60008219821115611e4f57611e4f611f2c565b500190565b600063ffffffff808316818516808303821115611e7357611e73611f2c565b01949350505050565b600060ff821660ff84168060ff03821115611e9957611e99611f2c565b019392505050565b600082611eb057611eb0611f5b565b500490565b600063ffffffff80841680611ecc57611ecc611f5b565b92169190910492915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611f1057611f10611f2c565b500290565b600082821015611f2757611f27611f2c565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61ffff811681146111a657600080fd5b63ffffffff811681146111a657600080fdfea164736f6c6343000806000a000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f10000000000000000000000005787befdc0ecd210dfa948264631cd53e68f7802000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101775760003560e01c80637fb5d19d116100d8578063ad1783611161008c578063f2fde38b11610066578063f2fde38b146104ab578063f3fef3a3146104be578063fc2a88c3146104d157600080fd5b8063ad178361146103e2578063c15ce4d714610409578063c3f909d41461041c57600080fd5b8063a3907d71116100bd578063a3907d71146103b5578063a4c0ed36146103bd578063a608a1e1146103d057600080fd5b80637fb5d19d146103845780638da5cb5b1461039757600080fd5b80633b2bcbf11161012f57806348baa1c51161011457806348baa1c5146102b157806357a8070a1461035f57806379ba50971461037c57600080fd5b80633b2bcbf1146102695780634306d3541461029057600080fd5b80631b6b6d23116101605780631b6b6d23146102005780631fe543e31461024c5780632f2770db1461026157600080fd5b8063030932bb1461017c578063181f5a77146101c1575b600080fd5b6101a37f000000000000000000000000000000000000000000000000000000000000012c81565b60405167ffffffffffffffff90911681526020015b60405180910390f35b604080518082018252601281527f56524656325772617070657220312e302e300000000000000000000000000000602082015290516101b89190611d7b565b6102277f000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b8565b61025f61025a366004611aaa565b6104da565b005b61025f61059a565b6102277f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c2485806781565b6102a361029e366004611b99565b6105d0565b6040519081526020016101b8565b61031b6102bf366004611a91565b600860205260009081526040902080546001820154600283015460039093015473ffffffffffffffffffffffffffffffffffffffff8316937401000000000000000000000000000000000000000090930463ffffffff16929085565b6040805173ffffffffffffffffffffffffffffffffffffffff909616865263ffffffff9094166020860152928401919091526060830152608082015260a0016101b8565b60035461036c9060ff1681565b60405190151581526020016101b8565b61025f6106d7565b6102a3610392366004611c01565b6107d4565b60005473ffffffffffffffffffffffffffffffffffffffff16610227565b61025f6108da565b61025f6103cb366004611970565b61090c565b60035461036c90610100900460ff1681565b6102277f0000000000000000000000005787befdc0ecd210dfa948264631cd53e68f780281565b61025f610417366004611cd5565b610dea565b6004546005546006546007546040805194855263ffffffff80851660208701526401000000008504811691860191909152680100000000000000008404811660608601526c01000000000000000000000000840416608085015260ff700100000000000000000000000000000000909304831660a085015260c08401919091521660e0820152610100016101b8565b61025f6104b936600461192b565b611195565b61025f6104cc366004611946565b6111a9565b6102a360025481565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067161461058c576040517f1cf993f400000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c248580671660248201526044015b60405180910390fd5b610596828261127e565b5050565b6105a2611489565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b60035460009060ff1661063f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610583565b600354610100900460ff16156106b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610583565b60006106bb61150c565b90506106ce8363ffffffff163a83611680565b9150505b919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610758576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610583565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60035460009060ff16610843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610583565b600354610100900460ff16156108b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610583565b60006108bf61150c565b90506108d28463ffffffff168483611680565b949350505050565b6108e2611489565b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055565b60035460ff16610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610583565b600354610100900460ff16156109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610583565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f11614610a89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c792063616c6c61626c652066726f6d204c494e4b0000000000000000006044820152606401610583565b60008080610a9984860186611bb6565b9250925092506000610aaa84611769565b90506000610ab661150c565b90506000610acb8663ffffffff163a84611680565b905080891015610b37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f66656520746f6f206c6f770000000000000000000000000000000000000000006044820152606401610583565b60075460ff1663ffffffff85161115610bac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e756d576f72647320746f6f20686967680000000000000000000000000000006044820152606401610583565b60007f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c2485806773ffffffffffffffffffffffffffffffffffffffff16635d3b1d306006547f000000000000000000000000000000000000000000000000000000000000012c89600560089054906101000a900463ffffffff16898d610c2e9190611e54565b610c389190611e54565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945267ffffffffffffffff909216602484015261ffff16604483015263ffffffff90811660648301528816608482015260a401602060405180830381600087803b158015610cb757600080fd5b505af1158015610ccb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cef9190611a19565b90506040518060a001604052808c73ffffffffffffffffffffffffffffffffffffffff1681526020018863ffffffff1681526020013a81526020018481526020018b8152506008600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff160217905550604082015181600101556060820151816002015560808201518160030155905050806002819055505050505050505050505050565b610df2611489565b6005805460ff808616700100000000000000000000000000000000027fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff63ffffffff8981166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff918c166801000000000000000002919091167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff909516949094179390931792909216919091179091556006839055600780549183167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00928316179055600380549091166001179055604080517fc3f909d4000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067169163c3f909d4916004828101926080929190829003018186803b158015610f7557600080fd5b505afa158015610f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fad9190611a32565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555050604080517f356dac7100000000000000000000000000000000000000000000000000000000815290517f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c2485806773ffffffffffffffffffffffffffffffffffffffff169163356dac71916004808301926020929190829003018186803b15801561106b57600080fd5b505afa15801561107f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a39190611a19565b6004819055507f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c2485806773ffffffffffffffffffffffffffffffffffffffff16635fbbc0d26040518163ffffffff1660e01b81526004016101206040518083038186803b15801561111057600080fd5b505afa158015611124573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111489190611c1f565b50506005805463ffffffff909816640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909816979097179096555050505050505050505050565b61119d611489565b6111a681611787565b50565b6111b1611489565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1169063a9059cbb90604401602060405180830381600087803b15801561124157600080fd5b505af1158015611255573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127991906119f7565b505050565b6000828152600860208181526040808420815160a081018352815473ffffffffffffffffffffffffffffffffffffffff808216835263ffffffff740100000000000000000000000000000000000000008304168387015260018401805495840195909552600284018054606085015260038501805460808601528b8a52979096527fffffffffffffffff00000000000000000000000000000000000000000000000090911690925591859055918490559290915581511661139b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f72657175657374206e6f7420666f756e640000000000000000000000000000006044820152606401610583565b600080631fe543e360e01b85856040516024016113b9929190611dee565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000611433846020015163ffffffff1685600001518461187d565b90508061148157835160405173ffffffffffffffffffffffffffffffffffffffff9091169087907fc551b83c151f2d1c7eeb938ac59008e0409f1c1dc1e2f112449d4d79b458902290600090a35b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461150a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610583565b565b600554604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905160009263ffffffff161515918391829173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005787befdc0ecd210dfa948264631cd53e68f7802169163feaf968c9160048082019260a092909190829003018186803b1580156115a657600080fd5b505afa1580156115ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115de9190611d37565b50945090925084915050801561160457506115f98242611f15565b60055463ffffffff16105b1561160e57506004545b6000811215611679576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c6964204c494e4b20776569207072696365000000000000000000006044820152606401610583565b9392505050565b6005546000908190839063ffffffff6c0100000000000000000000000082048116916116ba91680100000000000000009091041688611e3c565b6116c49190611e3c565b6116d686670de0b6b3a7640000611ed8565b6116e09190611ed8565b6116ea9190611ea1565b60055490915060009060649061171790700100000000000000000000000000000000900460ff1682611e7c565b6117249060ff1684611ed8565b61172e9190611ea1565b60055490915060009061175490640100000000900463ffffffff1664e8d4a51000611ed8565b61175e9083611e3c565b979650505050505050565b6000611776603f83611eb5565b611781906001611e54565b92915050565b73ffffffffffffffffffffffffffffffffffffffff8116331415611807576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610583565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005a61138881101561188f57600080fd5b6113888103905084604082048203116118a757600080fd5b50823b6118b357600080fd5b60008083516020850160008789f1949350505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d257600080fd5b805162ffffff811681146106d257600080fd5b803560ff811681146106d257600080fd5b805169ffffffffffffffffffff811681146106d257600080fd5b60006020828403121561193d57600080fd5b611679826118c9565b6000806040838503121561195957600080fd5b611962836118c9565b946020939093013593505050565b6000806000806060858703121561198657600080fd5b61198f856118c9565b935060208501359250604085013567ffffffffffffffff808211156119b357600080fd5b818701915087601f8301126119c757600080fd5b8135818111156119d657600080fd5b8860208285010111156119e857600080fd5b95989497505060200194505050565b600060208284031215611a0957600080fd5b8151801515811461167957600080fd5b600060208284031215611a2b57600080fd5b5051919050565b60008060008060808587031215611a4857600080fd5b8451611a5381611fb9565b6020860151909450611a6481611fc9565b6040860151909350611a7581611fc9565b6060860151909250611a8681611fc9565b939692955090935050565b600060208284031215611aa357600080fd5b5035919050565b60008060408385031215611abd57600080fd5b8235915060208084013567ffffffffffffffff80821115611add57600080fd5b818601915086601f830112611af157600080fd5b813581811115611b0357611b03611f8a565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108582111715611b4657611b46611f8a565b604052828152858101935084860182860187018b1015611b6557600080fd5b600095505b83861015611b88578035855260019590950194938601938601611b6a565b508096505050505050509250929050565b600060208284031215611bab57600080fd5b813561167981611fc9565b600080600060608486031215611bcb57600080fd5b8335611bd681611fc9565b92506020840135611be681611fb9565b91506040840135611bf681611fc9565b809150509250925092565b60008060408385031215611c1457600080fd5b823561196281611fc9565b60008060008060008060008060006101208a8c031215611c3e57600080fd5b8951611c4981611fc9565b60208b0151909950611c5a81611fc9565b60408b0151909850611c6b81611fc9565b60608b0151909750611c7c81611fc9565b60808b0151909650611c8d81611fc9565b9450611c9b60a08b016118ed565b9350611ca960c08b016118ed565b9250611cb760e08b016118ed565b9150611cc66101008b016118ed565b90509295985092959850929598565b600080600080600060a08688031215611ced57600080fd5b8535611cf881611fc9565b94506020860135611d0881611fc9565b9350611d1660408701611900565b925060608601359150611d2b60808701611900565b90509295509295909350565b600080600080600060a08688031215611d4f57600080fd5b611d5886611911565b9450602086015193506040860151925060608601519150611d2b60808701611911565b600060208083528351808285015260005b81811015611da857858101830151858201604001528201611d8c565b81811115611dba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015611e2f57845183529383019391830191600101611e13565b5090979650505050505050565b60008219821115611e4f57611e4f611f2c565b500190565b600063ffffffff808316818516808303821115611e7357611e73611f2c565b01949350505050565b600060ff821660ff84168060ff03821115611e9957611e99611f2c565b019392505050565b600082611eb057611eb0611f5b565b500490565b600063ffffffff80841680611ecc57611ecc611f5b565b92169190910492915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611f1057611f10611f2c565b500290565b600082821015611f2757611f27611f2c565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61ffff811681146111a657600080fd5b63ffffffff811681146111a657600080fdfea164736f6c6343000806000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f10000000000000000000000005787befdc0ecd210dfa948264631cd53e68f7802000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067
-----Decoded View---------------
Arg [0] : _link (address): 0xb0897686c545045aFc77CF20eC7A532E3120E0F1
Arg [1] : _linkEthFeed (address): 0x5787BefDc0ECd210Dfa948264631CD53E68F7802
Arg [2] : _coordinator (address): 0xAE975071Be8F8eE67addBC1A82488F1C24858067
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1
Arg [1] : 0000000000000000000000005787befdc0ecd210dfa948264631cd53e68f7802
Arg [2] : 000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $28.91 | 54.9467 | $1,588.51 |
[ 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.