More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 274 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Hatch All | 19459666 | 108 days ago | IN | 0 ETH | 0.03395913 | ||||
Withdraw | 19244405 | 138 days ago | IN | 0 ETH | 0.00054955 | ||||
Nest All | 19159892 | 150 days ago | IN | 0 ETH | 0.00161129 | ||||
Hatch All | 19159885 | 150 days ago | IN | 0 ETH | 0.00992232 | ||||
Hatch All | 19136458 | 154 days ago | IN | 0 ETH | 0.00657576 | ||||
Hatch All | 19129503 | 155 days ago | IN | 0 ETH | 0.00912975 | ||||
Hatch All | 19090926 | 160 days ago | IN | 0 ETH | 0.04055142 | ||||
Hatch All | 19086953 | 161 days ago | IN | 0 ETH | 0.00579407 | ||||
Nest All | 19025770 | 169 days ago | IN | 0 ETH | 0.01792776 | ||||
Hatch All | 19025764 | 169 days ago | IN | 0 ETH | 0.01005708 | ||||
Hatch All | 19025759 | 169 days ago | IN | 0 ETH | 0.00523294 | ||||
Hatch All | 19025753 | 169 days ago | IN | 0 ETH | 0.00949583 | ||||
Hatch All | 18972320 | 177 days ago | IN | 0 ETH | 0.00255822 | ||||
Hatch All | 18972304 | 177 days ago | IN | 0 ETH | 0.00441062 | ||||
Nest All | 18964257 | 178 days ago | IN | 0 ETH | 0.00486062 | ||||
Mint | 18964191 | 178 days ago | IN | 0.00409743 ETH | 0.00367844 | ||||
Hatch All | 18960302 | 178 days ago | IN | 0 ETH | 0.00154544 | ||||
Hatch All | 18960232 | 178 days ago | IN | 0 ETH | 0.00304363 | ||||
Nest All | 18951665 | 180 days ago | IN | 0 ETH | 0.00243191 | ||||
Mint | 18951544 | 180 days ago | IN | 0.00403542 ETH | 0.00157887 | ||||
Hatch All | 18951530 | 180 days ago | IN | 0 ETH | 0.00491759 | ||||
Hatch All | 18946204 | 180 days ago | IN | 0 ETH | 0.00429879 | ||||
Hatch All | 18939579 | 181 days ago | IN | 0 ETH | 0.00408712 | ||||
Hatch All | 18937789 | 181 days ago | IN | 0 ETH | 0.00536011 | ||||
Hatch All | 18935740 | 182 days ago | IN | 0 ETH | 0.00780651 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
19244405 | 138 days ago | 0.65886805 ETH | ||||
18964191 | 178 days ago | 0.000683 ETH | ||||
18951544 | 180 days ago | 0.00036691 ETH | ||||
18914912 | 185 days ago | 0.00009055 ETH | ||||
18914895 | 185 days ago | 0.00009086 ETH | ||||
18899169 | 187 days ago | 0.00014771 ETH | ||||
18898329 | 187 days ago | 0.00014791 ETH | ||||
18871146 | 191 days ago | 0.00005874 ETH | ||||
18870859 | 191 days ago | 0.00114647 ETH | ||||
18792622 | 202 days ago | 0.00267443 ETH | ||||
18762449 | 206 days ago | 0.00505346 ETH | ||||
18743794 | 209 days ago | 0.00022246 ETH | ||||
18733946 | 210 days ago | 1.49559564 ETH | ||||
18732309 | 210 days ago | 0.00118292 ETH | ||||
18709734 | 213 days ago | 0.00040338 ETH | ||||
18708358 | 214 days ago | 0.00269996 ETH | ||||
18708340 | 214 days ago | 0.01075157 ETH | ||||
18704919 | 214 days ago | 0.00204903 ETH | ||||
18702642 | 214 days ago | 0.00069119 ETH | ||||
18700993 | 215 days ago | 0.00139259 ETH | ||||
18699762 | 215 days ago | 0.0007003 ETH | ||||
18699716 | 215 days ago | 0.00209451 ETH | ||||
18697913 | 215 days ago | 0.00014117 ETH | ||||
18697770 | 215 days ago | 0.00280702 ETH | ||||
18697766 | 215 days ago | 0.0001404 ETH |
Loading...
Loading
Contract Name:
KomodosRoostNest
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "@openzeppelin/[email protected]/access/Ownable.sol"; import {LinearVRGDA} from "./VRGDAs/LinearVRGDA.sol"; import {ERC721TokenReceiver} from "solmate/src/tokens/ERC721.sol"; import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol"; import {toDaysWadUnsafe} from "solmate/src/utils/SignedWadMath.sol"; import {KomodosRoost} from "./KomodosRoost.sol"; contract KomodosRoostNest is LinearVRGDA, Ownable, ERC721TokenReceiver { KomodosRoost public roost; uint256 private soldQty = 0; uint256 private startTime = 0; uint256 private randNonce; uint256 private constant MAX_ORDER_QTY = 50; uint256 private constant MAX_SALE_ALLOCATION = 1069; uint256 private constant MIN_KOMODO_RANK = 4; uint256 private constant MAX_KOMODO_RANK = 10; uint256 private constant GILA_KOMODO_RANK = 150; mapping(uint256 => NestState) private nestStates; mapping(address => uint256[]) private allNestedEggs; uint256[] private komodoIdsRankWeighted; bool public nestingActive = false; struct NestState { uint256 nestedTill; uint256 nestedFor; address nestedBy; // 0 => unhatched // MIN_KOMODO_RANK <=> MAX_KOMODO_RANK => hatched uint256 rank; } event FundsAssigned(uint256 timestamp); event EggMinted(uint256 indexed eggId, address indexed mintedTo); event EggNested( uint256 indexed eggId, address indexed nestedBy, uint256 nestedFor ); event EggStolen( uint256 indexed eggId, address indexed stolenFrom, address indexed stolenBy, uint256 stolenByKomodo ); event EggHatched( uint256 indexed eggId, address indexed hatchedBy, uint256 rank ); modifier onlyGilaKomodo() { require( msg.sender == roost.ownerOf(0), "Only the Legion of Gila may enter" ); _; } constructor( address _roostAddress, int256 _targetPrice, int256 _priceDecayPercent, int256 _perTimeUnit, uint256 _entropy ) LinearVRGDA(_targetPrice, _priceDecayPercent, _perTimeUnit) { roost = KomodosRoost(_roostAddress); randNonce = uint256( keccak256( abi.encodePacked( blockhash(block.number - 1), block.number, block.coinbase, block.prevrandao, block.timestamp, _entropy ) ) ); _transferOwnership(roost.courtAddress()); } function awaken() external onlyOwner { require(startTime == 0, "ALREADY_AWAKE"); address courtAddress = roost.courtAddress(); nestStates[0] = NestState(0, 0, courtAddress, GILA_KOMODO_RANK); emit EggHatched(0, courtAddress, GILA_KOMODO_RANK); nestStates[1] = NestState(0, 0, courtAddress, MAX_KOMODO_RANK); emit EggHatched(1, courtAddress, MAX_KOMODO_RANK); for (uint256 i = 0; i < GILA_KOMODO_RANK; i++) { komodoIdsRankWeighted.push(0); } for (uint256 i = 0; i < MAX_KOMODO_RANK; i++) { komodoIdsRankWeighted.push(1); } nestingActive = true; startTime = block.timestamp; } function disableNesting() external onlyOwner { nestingActive = false; } function getPrice() public view returns (uint256) { return getVRGDAPrice( toDaysWadUnsafe(block.timestamp - startTime), soldQty ); } function mint( uint256 quantity ) external payable returns (uint256 unitPrice) { require(nestingActive, "NESTING_INACTIVE"); require(block.timestamp >= startTime, "SALE_INACTIVE"); require(soldQty + quantity <= MAX_SALE_ALLOCATION, "SUPPLY_EXHAUSTED"); require(quantity > 0 && quantity <= MAX_ORDER_QTY, "ORDER_QTY_INVALID"); unchecked { unitPrice = getPrice(); uint256 totalPrice = quantity * unitPrice; require(msg.value >= totalPrice, "UNDERPAID"); // Don't allow underpaying. soldQty += quantity; for (uint256 i = 0; i < quantity; i++) { roost.mint(msg.sender); emit EggMinted(roost.nextToMint() - 1, msg.sender); } // Note: We do this at the end to avoid creating a reentrancy vector. // Refund the user any ETH they spent over the current price of the eggs. // Unchecked is safe here because we validate msg.value >= price above. SafeTransferLib.safeTransferETH(msg.sender, msg.value - totalPrice); } } function withdraw() external onlyOwner { payable(owner()).transfer(address(this).balance); emit FundsAssigned(block.timestamp); } function isNestable(uint256 eggId) public view returns (bool) { return (nestStates[eggId].rank == 0) && (nestStates[eggId].nestedTill == 0) && roost.exists(eggId); } function nest(uint256 eggId, uint256 rank) public { require(nestingActive, "NESTING_INACTIVE"); require(roost.ownerOf(eggId) == msg.sender, "NOT_THE_EGG_OWNER"); require(nestStates[eggId].rank == 0, "EGG_ALREADY_HATCHED"); require(nestStates[eggId].nestedTill == 0, "EGG_ALREADY_NESTED"); require( rank >= MIN_KOMODO_RANK && rank <= MAX_KOMODO_RANK, "INVALID_RANK" ); uint256 nestingBlocks = calculateNestingBlocks(rank); // Set the nestedTill field of the egg struct to the block number when the egg will be ready to hatch nestStates[eggId] = NestState( block.number + nestingBlocks, nestingBlocks, msg.sender, 0 ); allNestedEggs[msg.sender].push(eggId); emit EggNested(eggId, msg.sender, nestingBlocks); // Transfer the egg from the caller to the contract // NOTE: Transfer is done at the end to avoid a re-entrancy vector roost.safeTransferFrom(msg.sender, address(this), eggId); } function nestAll(uint256[] calldata eggIds, uint256 rank) public { for (uint256 i = 0; i < eggIds.length; ++i) { nest(eggIds[i], rank); } } function getPendingEggs( address nester ) public view returns (uint256[] memory) { uint256 count = 0; for (uint256 i = 0; i < allNestedEggs[nester].length; i++) { uint256 eggId = allNestedEggs[nester][i]; NestState storage nestState = nestStates[eggId]; if ( nestState.nestedTill != 0 && block.number < nestState.nestedTill ) { ++count; } } uint256 idx = 0; uint256[] memory eggIds = new uint256[](count); for (uint256 i = 0; i < allNestedEggs[nester].length; i++) { uint256 eggId = allNestedEggs[nester][i]; NestState storage nestState = nestStates[eggId]; if ( nestState.nestedTill != 0 && block.number < nestState.nestedTill ) { eggIds[idx++] = eggId; } } return eggIds; } function getHatchableEggs( address nester ) public view returns (uint256[] memory) { uint256 count = 0; for (uint256 i = 0; i < allNestedEggs[nester].length; i++) { uint256 eggId = allNestedEggs[nester][i]; NestState storage nestState = nestStates[eggId]; if ( nestState.nestedTill != 0 && block.number >= nestState.nestedTill ) { ++count; } } uint256 idx = 0; uint256[] memory eggIds = new uint256[](count); for (uint256 i = 0; i < allNestedEggs[nester].length; i++) { uint256 eggId = allNestedEggs[nester][i]; NestState storage nestState = nestStates[eggId]; if ( nestState.nestedTill != 0 && block.number >= nestState.nestedTill ) { eggIds[idx++] = eggId; } } return eggIds; } function hatch(uint256 eggId) public { NestState storage nestState = nestStates[eggId]; require(nestState.rank == 0, "EGG_ALREADY_HATCHED"); require(nestState.nestedTill != 0, "EGG_NOT_YET_NESTED"); require(block.number >= nestState.nestedTill, "NESTING_INCOMPLETE"); require( nestState.nestedBy == msg.sender || msg.sender == owner(), "NOT_THE_NESTER_OR_CONTRACT_OWNER" ); // Generate a random number to determine whether the steal event occurs uint256 randomNumber = uint256( keccak256( abi.encodePacked( blockhash(block.number - 1), randNonce, block.coinbase, block.prevrandao, block.timestamp ) ) ); randNonce += 1; uint256 hatchingRank = hatchingKomodoRank(nestState.nestedFor); // If the steal event occurs, choose a random komodo from the array of all komodo ids // weighted by the rank of each komodo bool stolen = randomNumber % 10000 < hatchingStealProbabilityBps(hatchingRank); address owner; if (stolen) { uint256 ownerId = komodoIdsRankWeighted[ randomNumber % komodoIdsRankWeighted.length ]; owner = roost.ownerOf(ownerId); nestStates[eggId] = NestState(0, 0, address(0), 0); emit EggStolen(eggId, nestState.nestedBy, owner, ownerId); } else { owner = msg.sender; nestState.rank = hatchingRank; nestState.nestedTill = 0; nestState.nestedFor = 0; for (uint256 i = 0; i < nestState.rank; i++) { komodoIdsRankWeighted.push(eggId); } emit EggHatched(eggId, nestState.nestedBy, nestState.rank); roost.emitMetadataUpdate(eggId); } roost.safeTransferFrom(address(this), owner, eggId); } function hatchAll(uint256[] calldata eggIds) public { for (uint256 i = 0; i < eggIds.length; i++) { hatch(eggIds[i]); } } function hatchingStealProbabilityBps( uint256 rank ) public pure returns (uint256) { require( rank >= MIN_KOMODO_RANK && rank <= MAX_KOMODO_RANK, "INVALID_RANK" ); return 2667 - (167 * rank); } function hatchingKomodoRank( uint256 nestedBlocks ) public pure returns (uint256) { return (nestedBlocks + 132000) / 34800; } function calculateNestingBlocks( uint256 rank ) public pure returns (uint256) { require( rank >= MIN_KOMODO_RANK && rank <= MAX_KOMODO_RANK, "INVALID_RANK" ); return (34800 * rank) - 132000; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "@openzeppelin/[email protected]/utils/Strings.sol"; import "@openzeppelin/[email protected]/access/Ownable.sol"; import {ERC721} from "solmate/src/tokens/ERC721.sol"; contract KomodosRoost is ERC721, Ownable { using Strings for uint256; // Tokens 0 - 32 will be preminted to court wallet uint256 public constant HONOR_ALLOCATION = 33; // Tokens 33 - 164 will be marked as available to claim uint256 public constant CLAIM_ALLOCATION = 165; uint256 public nextToClaim = HONOR_ALLOCATION; uint256 public nextToMint = CLAIM_ALLOCATION; address public minter = address(0); address public courtAddress = address(0); uint256 private claimsEnabledBlock; mapping(address => uint256) private claimsRemaining; string public tokenBaseURI; event MinterUpdated(address minter); event ClaimsEnabledBlockUpdated(uint256 claimsEnabledBlock); event TokenBaseURIUpdated(string uri); event EggMinted(uint256 indexed eggId, address indexed mintedTo); event MetadataUpdate(uint256 _tokenId); modifier onlyMinter() { require(msg.sender == minter, "MINTER_ONLY"); _; } constructor( address _courtAddress, string memory _tokenBaseURI, uint256 _claimsEnabledBlock ) ERC721("Komodo's Roost", "KOMODO") { require(_courtAddress != address(0), "INVALID_COURT"); courtAddress = _courtAddress; tokenBaseURI = _tokenBaseURI; claimsEnabledBlock = _claimsEnabledBlock; _transferOwnership(_courtAddress); } function emitMetadataUpdate(uint256 tokenId) public { require(msg.sender == minter || msg.sender == courtAddress, "NOT_ALLOWED"); emit MetadataUpdate(tokenId); } function exists(uint256 id) public view returns (bool) { return _ownerOf[id] != address(0); } function tokenURI(uint256 id) public view override returns (string memory) { require(ownerOf(id) != address(0), "NOT_YET_MINTED"); return bytes(tokenBaseURI).length > 0 ? string(abi.encodePacked(tokenBaseURI, id.toString())) : ""; } function setMinter(address _minter) external onlyOwner { minter = _minter; emit MinterUpdated(_minter); } function setClaimsEnabledBlock(uint256 _newClaimsEnabledBlock) external onlyOwner { claimsEnabledBlock = _newClaimsEnabledBlock; emit ClaimsEnabledBlockUpdated(_newClaimsEnabledBlock); } function setBaseTokenURI(string memory _tokenBaseURI) external onlyOwner { tokenBaseURI = _tokenBaseURI; emit TokenBaseURIUpdated(_tokenBaseURI); } function assignClaims( address[] calldata addresses, uint256[] calldata claimQuantities ) external onlyOwner { require( addresses.length == claimQuantities.length, "MISMATCHING_LENGTHS" ); for (uint256 i = 0; i < addresses.length; i++) { claimsRemaining[addresses[i]] += claimQuantities[i]; } } function removeClaims( address[] calldata addresses, uint256[] calldata claimQuantities ) external onlyOwner { require( addresses.length == claimQuantities.length, "MISMATCHING_LENGTHS" ); for (uint256 i = 0; i < addresses.length; i++) { require( claimsRemaining[addresses[i]] >= claimQuantities[i], "INVALID_CLAIMS_QUANTITY" ); claimsRemaining[addresses[i]] -= claimQuantities[i]; } } function mint(address to) public onlyMinter { _mint(to, nextToMint++); emit EggMinted(nextToMint - 1, to); } function claimHonor() public onlyOwner { for (uint256 i = 0; i < HONOR_ALLOCATION; i++) { _mint(courtAddress, i); emit EggMinted(i, courtAddress); } } function claim(uint256 quantity) public { require((block.number >= claimsEnabledBlock), "CLAIM_WINDOW_INACTIVE"); require(quantity > 0, "CLAIM_QTY_ZERO"); require(quantity <= claimsRemaining[msg.sender], "NO_CLAIMS_REMAINING"); require( nextToClaim + quantity <= CLAIM_ALLOCATION, "ALLOCATION_EXHAUSTED" ); claimsRemaining[msg.sender] -= quantity; for (uint256 i = 0; i < quantity; i++) { _mint(msg.sender, nextToClaim++); emit EggMinted(nextToClaim - 1, msg.sender); } } function claimsAvailable(address claimer) public view returns (uint256) { return nextToClaim + claimsRemaining[claimer] <= CLAIM_ALLOCATION ? claimsRemaining[claimer] : CLAIM_ALLOCATION - nextToClaim; } function claimAll() public { claim(claimsAvailable(msg.sender)); } function transferFrom( address from, address to, uint256 id ) public override { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || msg.sender == minter || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Signed 18 decimal fixed point (wad) arithmetic library. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SignedWadMath.sol) /// @author Modified from Remco Bloemen (https://xn--2-umb.com/22/exp-ln/index.html) /// @dev Will not revert on overflow, only use where overflow is not possible. function toWadUnsafe(uint256 x) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Multiply x by 1e18. r := mul(x, 1000000000000000000) } } /// @dev Takes an integer amount of seconds and converts it to a wad amount of days. /// @dev Will not revert on overflow, only use where overflow is not possible. /// @dev Not meant for negative second amounts, it assumes x is positive. function toDaysWadUnsafe(uint256 x) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Multiply x by 1e18 and then divide it by 86400. r := div(mul(x, 1000000000000000000), 86400) } } /// @dev Takes a wad amount of days and converts it to an integer amount of seconds. /// @dev Will not revert on overflow, only use where overflow is not possible. /// @dev Not meant for negative day amounts, it assumes x is positive. function fromDaysWadUnsafe(int256 x) pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Multiply x by 86400 and then divide it by 1e18. r := div(mul(x, 86400), 1000000000000000000) } } /// @dev Will not revert on overflow, only use where overflow is not possible. function unsafeWadMul(int256 x, int256 y) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Multiply x by y and divide by 1e18. r := sdiv(mul(x, y), 1000000000000000000) } } /// @dev Will return 0 instead of reverting if y is zero and will /// not revert on overflow, only use where overflow is not possible. function unsafeWadDiv(int256 x, int256 y) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Multiply x by 1e18 and divide it by y. r := sdiv(mul(x, 1000000000000000000), y) } } function wadMul(int256 x, int256 y) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Check for the specific edge case where x == -1 and y == type(int256).min // For y == -1 and x == min int256, the second overflow check will catch this. // See: https://secure-contracts.com/learn_evm/arithmetic-checks.html#arithmetic-checks-for-int256-multiplication if and(eq(x, not(0)), eq(y, 0x8000000000000000000000000000000000000000000000000000000000000000)) { revert(0, 0) } // Store x * y in r for now. r := mul(x, y) // Equivalent to require(x == 0 || (x * y) / x == y) if iszero(or(iszero(x), eq(sdiv(r, x), y))) { revert(0, 0) } // Scale the result down by 1e18. r := sdiv(r, 1000000000000000000) } } function wadDiv(int256 x, int256 y) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Store x * 1e18 in r for now. r := mul(x, 1000000000000000000) // Equivalent to require(y != 0 && ((x * 1e18) / 1e18 == x)) if iszero(and(iszero(iszero(y)), eq(sdiv(r, 1000000000000000000), x))) { revert(0, 0) } // Divide r by y. r := sdiv(r, y) } } /// @dev Will not work with negative bases, only use when x is positive. function wadPow(int256 x, int256 y) pure returns (int256) { // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y) return wadExp((wadLn(x) * y) / 1e18); // Using ln(x) means x must be greater than 0. } function wadExp(int256 x) pure returns (int256 r) { unchecked { // When the result is < 0.5 we return zero. This happens when // x <= floor(log(0.5e18) * 1e18) ~ -42e18 if (x <= -42139678854452767551) return 0; // When the result is > (2**255 - 1) / 1e18 we can not represent it as an // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135. if (x >= 135305999368893231589) revert("EXP_OVERFLOW"); // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 // for more intermediate precision and a binary basis. This base conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5**18; // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; x = x - k * 54916777467707473351141471128; // k is in the range [-61, 195]. // Evaluate using a (6, 7)-term rational approximation. // p is made monic, we'll multiply by a scale factor later. int256 y = x + 1346386616545796478920950773328; y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; p = p * x + (4385272521454847904659076985693276 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; q = ((q * x) >> 96) + 50020603652535783019961831881945; q = ((q * x) >> 96) - 533845033583426703283633433725380; q = ((q * x) >> 96) + 3604857256930695427073651918091429; q = ((q * x) >> 96) - 14423608567350463180887372962807573; q = ((q * x) >> 96) + 26449188498355588339934803723976023; /// @solidity memory-safe-assembly assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already 2**96 too large. r := sdiv(p, q) } // r should be in the range (0.09, 0.25) * 2**96. // We now need to multiply r by: // * the scale factor s = ~6.031367120. // * the 2**k factor from the range reduction. // * the 1e18 / 2**96 factor for base conversion. // We do this all at once, with an intermediate result in 2**213 // basis, so the final right shift is always by a positive amount. r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); } } function wadLn(int256 x) pure returns (int256 r) { unchecked { require(x > 0, "UNDEFINED"); // We want to convert x from 10**18 fixed point to 2**96 fixed point. // We do this by multiplying by 2**96 / 10**18. But since // ln(x * C) = ln(x) + ln(C), we can simply do nothing here // and add ln(2**96 / 10**18) at the end. /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) r := or(r, shl(2, lt(0xf, shr(r, x)))) r := or(r, shl(1, lt(0x3, shr(r, x)))) r := or(r, lt(0x1, shr(r, x))) } // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) int256 k = r - 96; x <<= uint256(159 - k); x = int256(uint256(x) >> 159); // Evaluate using a (8, 8)-term rational approximation. // p is made monic, we will multiply by a scale factor later. int256 p = x + 3273285459638523848632254066296; p = ((p * x) >> 96) + 24828157081833163892658089445524; p = ((p * x) >> 96) + 43456485725739037958740375743393; p = ((p * x) >> 96) - 11111509109440967052023855526967; p = ((p * x) >> 96) - 45023709667254063763336534515857; p = ((p * x) >> 96) - 14706773417378608786704636184526; p = p * x - (795164235651350426258249787498 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. // q is monic by convention. int256 q = x + 5573035233440673466300451813936; q = ((q * x) >> 96) + 71694874799317883764090561454958; q = ((q * x) >> 96) + 283447036172924575727196451306956; q = ((q * x) >> 96) + 401686690394027663651624208769553; q = ((q * x) >> 96) + 204048457590392012362485061816622; q = ((q * x) >> 96) + 31853899698501571402653359427138; q = ((q * x) >> 96) + 909429971244387300277376558375; /// @solidity memory-safe-assembly assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already 2**96 too large. r := sdiv(p, q) } // r is in the range (0, 0.125) * 2**96 // Finalization, we need to: // * multiply by the scale factor s = 5.549… // * add ln(2**96 / 10**18) // * add k * ln(2) // * multiply by 10**18 / 2**96 = 5**18 >> 78 // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 r *= 1677202110996718588342820967067443963516166; // add ln(2) * k * 5e18 * 2**192 r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; // add ln(2**96 / 10**18) * 5e18 * 2**192 r += 600920179829731861736702779321621459595472258049074101567377883020018308; // base conversion: mul 2**18 / 2**192 r >>= 174; } } /// @dev Will return 0 instead of reverting if y is zero. function unsafeDiv(int256 x, int256 y) pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. r := sdiv(x, y) } }
// 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: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {unsafeWadDiv} from "solmate/src/utils/SignedWadMath.sol"; import {VRGDA} from "./VRGDA.sol"; /// @title Linear Variable Rate Gradual Dutch Auction /// @author transmissions11 <[email protected]> /// @author FrankieIsLost <[email protected]> /// @notice VRGDA with a linear issuance curve. abstract contract LinearVRGDA is VRGDA { /*////////////////////////////////////////////////////////////// PRICING PARAMETERS //////////////////////////////////////////////////////////////*/ /// @dev The total number of tokens to target selling every full unit of time. /// @dev Represented as an 18 decimal fixed point number. int256 internal immutable perTimeUnit; /// @notice Sets pricing parameters for the VRGDA. /// @param _targetPrice The target price for a token if sold on pace, scaled by 1e18. /// @param _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18. /// @param _perTimeUnit The number of tokens to target selling in 1 full unit of time, scaled by 1e18. constructor( int256 _targetPrice, int256 _priceDecayPercent, int256 _perTimeUnit ) VRGDA(_targetPrice, _priceDecayPercent) { perTimeUnit = _perTimeUnit; } /*////////////////////////////////////////////////////////////// PRICING LOGIC //////////////////////////////////////////////////////////////*/ /// @dev Given a number of tokens sold, return the target time that number of tokens should be sold by. /// @param sold A number of tokens sold, scaled by 1e18, to get the corresponding target sale time for. /// @return The target time the tokens should be sold by, scaled by 1e18, where the time is /// relative, such that 0 means the tokens should be sold immediately when the VRGDA begins. function getTargetSaleTime(int256 sold) public view virtual override returns (int256) { return unsafeWadDiv(sold, perTimeUnit); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// 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: MIT pragma solidity >=0.8.0; import {wadExp, wadLn, wadMul, unsafeWadMul, toWadUnsafe} from "solmate/src/utils/SignedWadMath.sol"; /// @title Variable Rate Gradual Dutch Auction /// @author transmissions11 <[email protected]> /// @author FrankieIsLost <[email protected]> /// @notice Sell tokens roughly according to an issuance schedule. abstract contract VRGDA { /*////////////////////////////////////////////////////////////// VRGDA PARAMETERS //////////////////////////////////////////////////////////////*/ /// @notice Target price for a token, to be scaled according to sales pace. /// @dev Represented as an 18 decimal fixed point number. int256 public immutable targetPrice; /// @dev Precomputed constant that allows us to rewrite a pow() as an exp(). /// @dev Represented as an 18 decimal fixed point number. int256 internal immutable decayConstant; /// @notice Sets target price and per time unit price decay for the VRGDA. /// @param _targetPrice The target price for a token if sold on pace, scaled by 1e18. /// @param _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18. constructor(int256 _targetPrice, int256 _priceDecayPercent) { targetPrice = _targetPrice; decayConstant = wadLn(1e18 - _priceDecayPercent); // The decay constant must be negative for VRGDAs to work. require(decayConstant < 0, "NON_NEGATIVE_DECAY_CONSTANT"); } /*////////////////////////////////////////////////////////////// PRICING LOGIC //////////////////////////////////////////////////////////////*/ /// @notice Calculate the price of a token according to the VRGDA formula. /// @param timeSinceStart Time passed since the VRGDA began, scaled by 1e18. /// @param sold The total number of tokens that have been sold so far. /// @return The price of a token according to VRGDA, scaled by 1e18. function getVRGDAPrice(int256 timeSinceStart, uint256 sold) public view virtual returns (uint256) { unchecked { // prettier-ignore return uint256(wadMul(targetPrice, wadExp(unsafeWadMul(decayConstant, // Theoretically calling toWadUnsafe with sold can silently overflow but under // any reasonable circumstance it will never be large enough. We use sold + 1 as // the VRGDA formula's n param represents the nth token and sold is the n-1th token. timeSinceStart - getTargetSaleTime(toWadUnsafe(sold + 1)) )))); } } /// @dev Given a number of tokens sold, return the target time that number of tokens should be sold by. /// @param sold A number of tokens sold, scaled by 1e18, to get the corresponding target sale time for. /// @return The target time the tokens should be sold by, scaled by 1e18, where the time is /// relative, such that 0 means the tokens should be sold immediately when the VRGDA begins. function getTargetSaleTime(int256 sold) public view virtual returns (int256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_roostAddress","type":"address"},{"internalType":"int256","name":"_targetPrice","type":"int256"},{"internalType":"int256","name":"_priceDecayPercent","type":"int256"},{"internalType":"int256","name":"_perTimeUnit","type":"int256"},{"internalType":"uint256","name":"_entropy","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eggId","type":"uint256"},{"indexed":true,"internalType":"address","name":"hatchedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"}],"name":"EggHatched","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eggId","type":"uint256"},{"indexed":true,"internalType":"address","name":"mintedTo","type":"address"}],"name":"EggMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eggId","type":"uint256"},{"indexed":true,"internalType":"address","name":"nestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"nestedFor","type":"uint256"}],"name":"EggNested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eggId","type":"uint256"},{"indexed":true,"internalType":"address","name":"stolenFrom","type":"address"},{"indexed":true,"internalType":"address","name":"stolenBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"stolenByKomodo","type":"uint256"}],"name":"EggStolen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FundsAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"awaken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"calculateNestingBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"disableNesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nester","type":"address"}],"name":"getHatchableEggs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nester","type":"address"}],"name":"getPendingEggs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"sold","type":"int256"}],"name":"getTargetSaleTime","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"timeSinceStart","type":"int256"},{"internalType":"uint256","name":"sold","type":"uint256"}],"name":"getVRGDAPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"}],"name":"hatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"eggIds","type":"uint256[]"}],"name":"hatchAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nestedBlocks","type":"uint256"}],"name":"hatchingKomodoRank","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"hatchingStealProbabilityBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"}],"name":"isNestable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"unitPrice","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"},{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"nest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"eggIds","type":"uint256[]"},{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"nestAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nestingActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"roost","outputs":[{"internalType":"contract KomodosRoost","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040525f6002555f6003555f60085f6101000a81548160ff02191690831515021790555034801562000031575f80fd5b506040516200405638038062004056833981810160405281019062000057919062000679565b838383828281608081815250506200008a81670de0b6b3a76400006200007e91906200072a565b6200023b60201b60201c565b60a081815250505f60a05112620000d8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000cf90620007cf565b60405180910390fd5b50508060c0818152505050505062000105620000f9620004dc60201b60201c565b620004e360201b60201c565b8460015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600143620001549190620007ef565b4043414442856040516020016200017196959493929190620008da565b604051602081830303815290604052805190602001205f1c6004819055506200023060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b67fc9e66040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001fe573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000224919062000955565b620004e360201b60201c565b5050505050620009f3565b5f80821362000281576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200027890620009d3565b60405180910390fd5b816fffffffffffffffffffffffffffffffff1060071b905081811c67ffffffffffffffff1060061b8117905081811c63ffffffff1060051b8117905081811c61ffff1060041b8117905081811c60ff1060031b8117905081811c600f1060021b8117905081811c60031060011b8117905081811c600110811790505f60608203905080609f0383901b9250609f83901c92505f6c29508e458543d8aa4df2abee78840190506d0139601a2efabe717e604cbb48946060858302901d0190506d02247f7a7b6594320649aa03aba16060858302901d0190506c8c3f38e95a6b1ff2ab1c3b34376060858302901d0390506d02384773bdf1ac5676facced60916060858302901d0390506cb9a025d814b29c212b8b1a07ce6060858302901d039050780a09507084cc699bb0e71ea86a0000000000000000000000008482020390505f6c465772b2bbbb5f824b15207a30850190506d0388eaa27412d5aca026815d636e6060868302901d0190506d0df99ac502031bf953eff472fdcc6060868302901d0190506d13cdffb29d51d99322bdff5f22116060868302901d0190506d0a0f742023def783a307a986912e6060868302901d0190506d01920d8043ca89b5239253284e426060868302901d0190506c0b7a86d7375468fac667a0a5276060868302901d0190508082059350711340daa0d5f769dba1915cef59f0815a550684029350827d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302840193507d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642848401935060ae84901d9350505050919050565b5f33905090565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620005d382620005a8565b9050919050565b620005e581620005c7565b8114620005f0575f80fd5b50565b5f815190506200060381620005da565b92915050565b5f819050919050565b6200061d8162000609565b811462000628575f80fd5b50565b5f815190506200063b8162000612565b92915050565b5f819050919050565b620006558162000641565b811462000660575f80fd5b50565b5f8151905062000673816200064a565b92915050565b5f805f805f60a08688031215620006955762000694620005a4565b5b5f620006a488828901620005f3565b9550506020620006b7888289016200062b565b9450506040620006ca888289016200062b565b9350506060620006dd888289016200062b565b9250506080620006f08882890162000663565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f620007368262000609565b9150620007438362000609565b925082820390508181125f8412168282135f8512151617156200076b576200076a620006fd565b5b92915050565b5f82825260208201905092915050565b7f4e4f4e5f4e454741544956455f44454341595f434f4e5354414e5400000000005f82015250565b5f620007b7601b8362000771565b9150620007c48262000781565b602082019050919050565b5f6020820190508181035f830152620007e881620007a9565b9050919050565b5f620007fb8262000641565b9150620008088362000641565b9250828203905081811115620008235762000822620006fd565b5b92915050565b5f819050919050565b5f819050919050565b620008506200084a8262000829565b62000832565b82525050565b5f819050919050565b620008746200086e8262000641565b62000856565b82525050565b5f6200088682620005a8565b9050919050565b5f8160601b9050919050565b5f620008a5826200088d565b9050919050565b5f620008b88262000899565b9050919050565b620008d4620008ce826200087a565b620008ac565b82525050565b5f620008e782896200083b565b602082019150620008f982886200085f565b6020820191506200090b8287620008bf565b6014820191506200091d82866200085f565b6020820191506200092f82856200085f565b6020820191506200094182846200085f565b602082019150819050979650505050505050565b5f602082840312156200096d576200096c620005a4565b5b5f6200097c84828501620005f3565b91505092915050565b7f554e444546494e454400000000000000000000000000000000000000000000005f82015250565b5f620009bb60098362000771565b9150620009c88262000985565b602082019050919050565b5f6020820190508181035f830152620009ec81620009ad565b9050919050565b60805160a05160c05161363162000a255f395f610a6f01525f61203401525f8181611f22015261200d01526136315ff3fe60806040526004361061014a575f3560e01c806393b49bdd116100b5578063c023b7bc1161006e578063c023b7bc14610472578063c8c18842146104ae578063dc38679c146104d6578063e0b464ae14610500578063f2fde38b14610528578063f466d4ab146105505761014a565b806393b49bdd146103625780639456ad091461039e57806398d5fdca146103b4578063a0712d68146103de578063a780f0bd1461040e578063aa985de01461044a5761014a565b80636d9d33b7116101075780636d9d33b714610258578063715018a614610294578063790fd479146102aa578063883d4cf2146102e65780638da5cb5b146103105780638dfe4b1f1461033a5761014a565b8063076a86941461014e57806309e03294146101785780630dbcecd5146101b4578063150b7a02146101f057806315a4d8601461022c5780633ccfd60b14610242575b5f80fd5b348015610159575f80fd5b5061016261058c565b60405161016f9190612560565b60405180910390f35b348015610183575f80fd5b5061019e600480360381019061019991906125b4565b6105b1565b6040516101ab91906125ee565b60405180910390f35b3480156101bf575f80fd5b506101da60048036038101906101d591906125b4565b610626565b6040516101e791906125ee565b60405180910390f35b3480156101fb575f80fd5b50610216600480360381019061021191906126a3565b61064a565b6040516102239190612761565b60405180910390f35b348015610237575f80fd5b5061024061065e565b005b34801561024d575f80fd5b506102566109dc565b005b348015610263575f80fd5b5061027e600480360381019061027991906127ad565b610a68565b60405161028b91906127e7565b60405180910390f35b34801561029f575f80fd5b506102a8610a9a565b005b3480156102b5575f80fd5b506102d060048036038101906102cb9190612800565b610aad565b6040516102dd91906128e2565b60405180910390f35b3480156102f1575f80fd5b506102fa610d0a565b604051610307919061291c565b60405180910390f35b34801561031b575f80fd5b50610324610d1c565b6040516103319190612944565b60405180910390f35b348015610345575f80fd5b50610360600480360381019061035b91906129b2565b610d43565b005b34801561036d575f80fd5b5061038860048036038101906103839190612800565b610d84565b60405161039591906128e2565b60405180910390f35b3480156103a9575f80fd5b506103b2610fdf565b005b3480156103bf575f80fd5b506103c8611002565b6040516103d591906125ee565b60405180910390f35b6103f860048036038101906103f391906125b4565b611029565b60405161040591906125ee565b60405180910390f35b348015610419575f80fd5b50610434600480360381019061042f91906125b4565b611344565b604051610441919061291c565b60405180910390f35b348015610455575f80fd5b50610470600480360381019061046b91906129fd565b611422565b005b34801561047d575f80fd5b50610498600480360381019061049391906125b4565b611876565b6040516104a591906125ee565b60405180910390f35b3480156104b9575f80fd5b506104d460048036038101906104cf91906125b4565b6118e9565b005b3480156104e1575f80fd5b506104ea611f20565b6040516104f791906127e7565b60405180910390f35b34801561050b575f80fd5b5061052660048036038101906105219190612a3b565b611f44565b005b348015610533575f80fd5b5061054e60048036038101906105499190612800565b611f85565b005b34801561055b575f80fd5b5061057660048036038101906105719190612a98565b612007565b60405161058391906125ee565b60405180910390f35b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f600482101580156105c45750600a8211155b610603576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fa90612b30565b60405180910390fd5b620203a0826187f06106159190612b7b565b61061f9190612bbc565b9050919050565b5f6187f0620203a0836106399190612bef565b6106439190612c4f565b9050919050565b5f63150b7a0260e01b905095945050505050565b610666612080565b5f600354146106aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a190612cc9565b60405180910390fd5b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b67fc9e66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107399190612cfb565b905060405180608001604052805f81526020015f81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001609681525060055f8081526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050508073ffffffffffffffffffffffffffffffffffffffff165f7fdb3da22d51c55d1ef1754d6364dfeab7810001722856b1bae07b2242a33473d9609660405161083191906125ee565b60405180910390a360405180608001604052805f81526020015f81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001600a81525060055f600181526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050508073ffffffffffffffffffffffffffffffffffffffff1660017fdb3da22d51c55d1ef1754d6364dfeab7810001722856b1bae07b2242a33473d9600a60405161093191906125ee565b60405180910390a35f5b60968110156109775760075f908060018154018082558091505060019003905f5260205f20015f9091909190915055808060010191505061093b565b505f5b600a8110156109b75760076001908060018154018082558091505060019003905f5260205f20015f9091909190915055808060010191505061097a565b50600160085f6101000a81548160ff0219169083151502179055504260038190555050565b6109e4612080565b6109ec610d1c565b73ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015610a2e573d5f803e3d5ffd5b507f7635c1d36c3210c9a5d0992d3653cf078347a14f938bb48667296c19ae0e1f0342604051610a5e91906125ee565b60405180910390a1565b5f610a93827f00000000000000000000000000000000000000000000000000000000000000006120fe565b9050919050565b610aa2612080565b610aab5f612114565b565b60605f805b60065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610ba0575f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610b4a57610b49612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610b7f5750805f01544310155b15610b915783610b8e90612d53565b93505b50508080600101915050610ab2565b505f808267ffffffffffffffff811115610bbd57610bbc612d9a565b5b604051908082528060200260200182016040528015610beb5781602001602082028036833780820191505090505b5090505f5b60065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610cfe575f60065f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610c8857610c87612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610cbd5750805f01544310155b15610cef5781848680610ccf90612d53565b975081518110610ce257610ce1612d26565b5b6020026020010181815250505b50508080600101915050610bf0565b50809350505050919050565b60085f9054906101000a900460ff1681565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f5b82829050811015610d7f57610d72838383818110610d6657610d65612d26565b5b905060200201356118e9565b8080600101915050610d45565b505050565b60605f805b60065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610e76575f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610e2157610e20612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610e555750805f015443105b15610e675783610e6490612d53565b93505b50508080600101915050610d89565b505f808267ffffffffffffffff811115610e9357610e92612d9a565b5b604051908082528060200260200182016040528015610ec15781602001602082028036833780820191505090505b5090505f5b60065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610fd3575f60065f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610f5e57610f5d612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610f925750805f015443105b15610fc45781848680610fa490612d53565b975081518110610fb757610fb6612d26565b5b6020026020010181815250505b50508080600101915050610ec6565b50809350505050919050565b610fe7612080565b5f60085f6101000a81548160ff021916908315150217905550565b5f61102461101c600354426110179190612bbc565b6121d5565b600254612007565b905090565b5f60085f9054906101000a900460ff16611078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106f90612e11565b60405180910390fd5b6003544210156110bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b490612e79565b60405180910390fd5b61042d826002546110ce9190612bef565b111561110f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110690612ee1565b60405180910390fd5b5f8211801561111f575060328211155b61115e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115590612f49565b60405180910390fd5b611166611002565b90505f8183029050803410156111b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a890612fb1565b60405180910390fd5b8260025f82825401925050819055505f5b838110156113315760015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636a627842336040518263ffffffff1660e01b81526004016112249190612944565b5f604051808303815f87803b15801561123b575f80fd5b505af115801561124d573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff166001805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636be78f766040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112f79190612fe3565b037f3f30939db62a9977a0d3dd0a8776309093ded9da114c6095d1d189bcb43854dd60405160405180910390a380806001019150506111c2565b5061133e338234036121ed565b50919050565b5f8060055f8481526020019081526020015f206003015414801561137a57505f60055f8481526020019081526020015f205f0154145b801561141b575060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e79836040518263ffffffff1660e01b81526004016113db91906125ee565b602060405180830381865afa1580156113f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061141a9190613038565b5b9050919050565b60085f9054906101000a900460ff16611470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146790612e11565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1660015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b81526004016114e191906125ee565b602060405180830381865afa1580156114fc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115209190612cfb565b73ffffffffffffffffffffffffffffffffffffffff1614611576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156d906130ad565b60405180910390fd5b5f60055f8481526020019081526020015f2060030154146115cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c390613115565b60405180910390fd5b5f60055f8481526020019081526020015f205f015414611621576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116189061317d565b60405180910390fd5b600481101580156116335750600a8111155b611672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166990612b30565b60405180910390fd5b5f61167c826105b1565b9050604051806080016040528082436116959190612bef565b81526020018281526020013373ffffffffffffffffffffffffffffffffffffffff1681526020015f81525060055f8581526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003015590505060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2083908060018154018082558091505060019003905f5260205f20015f90919091909150553373ffffffffffffffffffffffffffffffffffffffff16837fd9f5ab4cc12671e09c1c99df4949527872aa143457644a0ae270eebb8b58cd59836040516117de91906125ee565b60405180910390a360015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3330866040518463ffffffff1660e01b81526004016118449392919061319b565b5f604051808303815f87803b15801561185b575f80fd5b505af115801561186d573d5f803e3d5ffd5b50505050505050565b5f600482101580156118895750600a8211155b6118c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118bf90612b30565b60405180910390fd5b8160a76118d59190612b7b565b610a6b6118e29190612bbc565b9050919050565b5f60055f8381526020019081526020015f2090505f816003015414611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90613115565b60405180910390fd5b5f815f015403611988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197f9061321a565b60405180910390fd5b805f01544310156119ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c590613282565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480611a5d5750611a2e610d1c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611a9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a93906132ea565b60405180910390fd5b5f600143611aaa9190612bbc565b40600454414442604051602001611ac59594939291906133a7565b604051602081830303815290604052805190602001205f1c9050600160045f828254611af19190612bef565b925050819055505f611b068360010154610626565b90505f611b1282611876565b61271084611b209190613405565b1090505f8115611d30575f6007808054905086611b3d9190613405565b81548110611b4e57611b4d612d26565b5b905f5260205f200154905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e826040518263ffffffff1660e01b8152600401611bb391906125ee565b602060405180830381865afa158015611bce573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bf29190612cfb565b915060405180608001604052805f81526020015f81526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525060055f8981526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050508173ffffffffffffffffffffffffffffffffffffffff16866002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16887fdfe44e8c2446ef07b6112cd25fdf9a97c447d5673fd84cafae7bb4e48bc35dab84604051611d2291906125ee565b60405180910390a450611e8d565b3390508285600301819055505f855f01819055505f85600101819055505f5b8560030154811015611d8e57600787908060018154018082558091505060019003905f5260205f20015f90919091909150558080600101915050611d4f565b50846002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16867fdb3da22d51c55d1ef1754d6364dfeab7810001722856b1bae07b2242a33473d98760030154604051611dfd91906125ee565b60405180910390a360015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633190b9ea876040518263ffffffff1660e01b8152600401611e5f91906125ee565b5f604051808303815f87803b158015611e76575f80fd5b505af1158015611e88573d5f803e3d5ffd5b505050505b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3083896040518463ffffffff1660e01b8152600401611eeb9392919061319b565b5f604051808303815f87803b158015611f02575f80fd5b505af1158015611f14573d5f803e3d5ffd5b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f5b83839050811015611f7f57611f74848483818110611f6757611f66612d26565b5b9050602002013583611422565b806001019050611f46565b50505050565b611f8d612080565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ffb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff2906134a5565b60405180910390fd5b61200481612114565b50565b5f6120787f000000000000000000000000000000000000000000000000000000000000000061207361206e7f00000000000000000000000000000000000000000000000000000000000000006120676120626001890161223d565b610a68565b8803612250565b612266565b612485565b905092915050565b6120886124df565b73ffffffffffffffffffffffffffffffffffffffff166120a6610d1c565b73ffffffffffffffffffffffffffffffffffffffff16146120fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f39061350d565b60405180910390fd5b565b5f81670de0b6b3a7640000840205905092915050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f62015180670de0b6b3a76400008302049050919050565b5f805f805f85875af1905080612238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161222f90613575565b60405180910390fd5b505050565b5f670de0b6b3a764000082029050919050565b5f670de0b6b3a764000082840205905092915050565b5f7ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213612296575f9050612480565b680755bf798b4a1bf1e582126122e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122d8906135dd565b60405180910390fd5b6503782dace9d9604e83901b816122fb576122fa612c22565b5b0591505f60606b8000000000000000000000006bb17217f7d1cf79abc9e3b398606086901b8161232e5761232d612c22565b5b0501901d90506bb17217f7d1cf79abc9e3b3988102830392505f6c10fe68e7fd37d0007b713f7650840190506d02d16720577bd19bf614176fe9ea6060858302901d0190505f6d04a4fd9f2a8b96949216d2255a6c8583010390506e0587f503bb6ea29d25fcb7401964506060838302901d01905079d835ebba824c98fb31b83b2ca45c0000000000000000000000008582020190505f6c240c330e9fb2d9cbaf0fd5aafc860390506d0277594991cfc85f6e2461837cd96060878302901d0190506d1a521255e34f6a5061b25ef1c9c46060878302901d0390506db1bbb201f443cf962f1a1d3db4a56060878302901d0190506e02c72388d9f74f51a9331fed693f156060878302901d0390506e05180bb14799ab47a8a8cb2a527d576060878302901d01905080820594508360c30374029d9dc38563c32e5c2f6dc192ee70ef65f9978af38602901c9450505050505b919050565b5f7f800000000000000000000000000000000000000000000000000000000000000082145f19841416156124b7575f80fd5b818302905081838205148315176124cc575f80fd5b670de0b6b3a76400008105905092915050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61252861252361251e846124e6565b612505565b6124e6565b9050919050565b5f6125398261250e565b9050919050565b5f61254a8261252f565b9050919050565b61255a81612540565b82525050565b5f6020820190506125735f830184612551565b92915050565b5f80fd5b5f80fd5b5f819050919050565b61259381612581565b811461259d575f80fd5b50565b5f813590506125ae8161258a565b92915050565b5f602082840312156125c9576125c8612579565b5b5f6125d6848285016125a0565b91505092915050565b6125e881612581565b82525050565b5f6020820190506126015f8301846125df565b92915050565b5f612611826124e6565b9050919050565b61262181612607565b811461262b575f80fd5b50565b5f8135905061263c81612618565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f84011261266357612662612642565b5b8235905067ffffffffffffffff8111156126805761267f612646565b5b60208301915083600182028301111561269c5761269b61264a565b5b9250929050565b5f805f805f608086880312156126bc576126bb612579565b5b5f6126c98882890161262e565b95505060206126da8882890161262e565b94505060406126eb888289016125a0565b935050606086013567ffffffffffffffff81111561270c5761270b61257d565b5b6127188882890161264e565b92509250509295509295909350565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61275b81612727565b82525050565b5f6020820190506127745f830184612752565b92915050565b5f819050919050565b61278c8161277a565b8114612796575f80fd5b50565b5f813590506127a781612783565b92915050565b5f602082840312156127c2576127c1612579565b5b5f6127cf84828501612799565b91505092915050565b6127e18161277a565b82525050565b5f6020820190506127fa5f8301846127d8565b92915050565b5f6020828403121561281557612814612579565b5b5f6128228482850161262e565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61285d81612581565b82525050565b5f61286e8383612854565b60208301905092915050565b5f602082019050919050565b5f6128908261282b565b61289a8185612835565b93506128a583612845565b805f5b838110156128d55781516128bc8882612863565b97506128c78361287a565b9250506001810190506128a8565b5085935050505092915050565b5f6020820190508181035f8301526128fa8184612886565b905092915050565b5f8115159050919050565b61291681612902565b82525050565b5f60208201905061292f5f83018461290d565b92915050565b61293e81612607565b82525050565b5f6020820190506129575f830184612935565b92915050565b5f8083601f84011261297257612971612642565b5b8235905067ffffffffffffffff81111561298f5761298e612646565b5b6020830191508360208202830111156129ab576129aa61264a565b5b9250929050565b5f80602083850312156129c8576129c7612579565b5b5f83013567ffffffffffffffff8111156129e5576129e461257d565b5b6129f18582860161295d565b92509250509250929050565b5f8060408385031215612a1357612a12612579565b5b5f612a20858286016125a0565b9250506020612a31858286016125a0565b9150509250929050565b5f805f60408486031215612a5257612a51612579565b5b5f84013567ffffffffffffffff811115612a6f57612a6e61257d565b5b612a7b8682870161295d565b93509350506020612a8e868287016125a0565b9150509250925092565b5f8060408385031215612aae57612aad612579565b5b5f612abb85828601612799565b9250506020612acc858286016125a0565b9150509250929050565b5f82825260208201905092915050565b7f494e56414c49445f52414e4b00000000000000000000000000000000000000005f82015250565b5f612b1a600c83612ad6565b9150612b2582612ae6565b602082019050919050565b5f6020820190508181035f830152612b4781612b0e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612b8582612581565b9150612b9083612581565b9250828202612b9e81612581565b91508282048414831517612bb557612bb4612b4e565b5b5092915050565b5f612bc682612581565b9150612bd183612581565b9250828203905081811115612be957612be8612b4e565b5b92915050565b5f612bf982612581565b9150612c0483612581565b9250828201905080821115612c1c57612c1b612b4e565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612c5982612581565b9150612c6483612581565b925082612c7457612c73612c22565b5b828204905092915050565b7f414c52454144595f4157414b45000000000000000000000000000000000000005f82015250565b5f612cb3600d83612ad6565b9150612cbe82612c7f565b602082019050919050565b5f6020820190508181035f830152612ce081612ca7565b9050919050565b5f81519050612cf581612618565b92915050565b5f60208284031215612d1057612d0f612579565b5b5f612d1d84828501612ce7565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612d5d82612581565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8f57612d8e612b4e565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e455354494e475f494e414354495645000000000000000000000000000000005f82015250565b5f612dfb601083612ad6565b9150612e0682612dc7565b602082019050919050565b5f6020820190508181035f830152612e2881612def565b9050919050565b7f53414c455f494e414354495645000000000000000000000000000000000000005f82015250565b5f612e63600d83612ad6565b9150612e6e82612e2f565b602082019050919050565b5f6020820190508181035f830152612e9081612e57565b9050919050565b7f535550504c595f455848415553544544000000000000000000000000000000005f82015250565b5f612ecb601083612ad6565b9150612ed682612e97565b602082019050919050565b5f6020820190508181035f830152612ef881612ebf565b9050919050565b7f4f524445525f5154595f494e56414c49440000000000000000000000000000005f82015250565b5f612f33601183612ad6565b9150612f3e82612eff565b602082019050919050565b5f6020820190508181035f830152612f6081612f27565b9050919050565b7f554e4445525041494400000000000000000000000000000000000000000000005f82015250565b5f612f9b600983612ad6565b9150612fa682612f67565b602082019050919050565b5f6020820190508181035f830152612fc881612f8f565b9050919050565b5f81519050612fdd8161258a565b92915050565b5f60208284031215612ff857612ff7612579565b5b5f61300584828501612fcf565b91505092915050565b61301781612902565b8114613021575f80fd5b50565b5f815190506130328161300e565b92915050565b5f6020828403121561304d5761304c612579565b5b5f61305a84828501613024565b91505092915050565b7f4e4f545f5448455f4547475f4f574e45520000000000000000000000000000005f82015250565b5f613097601183612ad6565b91506130a282613063565b602082019050919050565b5f6020820190508181035f8301526130c48161308b565b9050919050565b7f4547475f414c52454144595f48415443484544000000000000000000000000005f82015250565b5f6130ff601383612ad6565b915061310a826130cb565b602082019050919050565b5f6020820190508181035f83015261312c816130f3565b9050919050565b7f4547475f414c52454144595f4e455354454400000000000000000000000000005f82015250565b5f613167601283612ad6565b915061317282613133565b602082019050919050565b5f6020820190508181035f8301526131948161315b565b9050919050565b5f6060820190506131ae5f830186612935565b6131bb6020830185612935565b6131c860408301846125df565b949350505050565b7f4547475f4e4f545f5945545f4e455354454400000000000000000000000000005f82015250565b5f613204601283612ad6565b915061320f826131d0565b602082019050919050565b5f6020820190508181035f830152613231816131f8565b9050919050565b7f4e455354494e475f494e434f4d504c45544500000000000000000000000000005f82015250565b5f61326c601283612ad6565b915061327782613238565b602082019050919050565b5f6020820190508181035f83015261329981613260565b9050919050565b7f4e4f545f5448455f4e45535445525f4f525f434f4e54524143545f4f574e45525f82015250565b5f6132d4602083612ad6565b91506132df826132a0565b602082019050919050565b5f6020820190508181035f830152613301816132c8565b9050919050565b5f819050919050565b5f819050919050565b61332b61332682613308565b613311565b82525050565b5f819050919050565b61334b61334682612581565b613331565b82525050565b5f61335b826124e6565b9050919050565b5f8160601b9050919050565b5f61337882613362565b9050919050565b5f6133898261336e565b9050919050565b6133a161339c82613351565b61337f565b82525050565b5f6133b2828861331a565b6020820191506133c2828761333a565b6020820191506133d28286613390565b6014820191506133e2828561333a565b6020820191506133f2828461333a565b6020820191508190509695505050505050565b5f61340f82612581565b915061341a83612581565b92508261342a57613429612c22565b5b828206905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f61348f602683612ad6565b915061349a82613435565b604082019050919050565b5f6020820190508181035f8301526134bc81613483565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f6134f7602083612ad6565b9150613502826134c3565b602082019050919050565b5f6020820190508181035f830152613524816134eb565b9050919050565b7f4554485f5452414e534645525f4641494c4544000000000000000000000000005f82015250565b5f61355f601383612ad6565b915061356a8261352b565b602082019050919050565b5f6020820190508181035f83015261358c81613553565b9050919050565b7f4558505f4f564552464c4f5700000000000000000000000000000000000000005f82015250565b5f6135c7600c83612ad6565b91506135d282613593565b602082019050919050565b5f6020820190508181035f8301526135f4816135bb565b905091905056fea2646970667358221220ad2bdc3991a42ac6154d6d82bf9dae1d0236913abc1dde663538fece54e3bd7b64736f6c63430008160033000000000000000000000000aee9f5908e70a749e9289d61cd37757e62bed50a00000000000000000000000000000000000000000000000000354a6ba7a18000000000000000000000000000000000000000000000000000008e1bc9bf040000000000000000000000000000000000000000000000000001ee8307d7c5990800000000000000000000000000000000000000000000000002f87191df43ea2c68
Deployed Bytecode
0x60806040526004361061014a575f3560e01c806393b49bdd116100b5578063c023b7bc1161006e578063c023b7bc14610472578063c8c18842146104ae578063dc38679c146104d6578063e0b464ae14610500578063f2fde38b14610528578063f466d4ab146105505761014a565b806393b49bdd146103625780639456ad091461039e57806398d5fdca146103b4578063a0712d68146103de578063a780f0bd1461040e578063aa985de01461044a5761014a565b80636d9d33b7116101075780636d9d33b714610258578063715018a614610294578063790fd479146102aa578063883d4cf2146102e65780638da5cb5b146103105780638dfe4b1f1461033a5761014a565b8063076a86941461014e57806309e03294146101785780630dbcecd5146101b4578063150b7a02146101f057806315a4d8601461022c5780633ccfd60b14610242575b5f80fd5b348015610159575f80fd5b5061016261058c565b60405161016f9190612560565b60405180910390f35b348015610183575f80fd5b5061019e600480360381019061019991906125b4565b6105b1565b6040516101ab91906125ee565b60405180910390f35b3480156101bf575f80fd5b506101da60048036038101906101d591906125b4565b610626565b6040516101e791906125ee565b60405180910390f35b3480156101fb575f80fd5b50610216600480360381019061021191906126a3565b61064a565b6040516102239190612761565b60405180910390f35b348015610237575f80fd5b5061024061065e565b005b34801561024d575f80fd5b506102566109dc565b005b348015610263575f80fd5b5061027e600480360381019061027991906127ad565b610a68565b60405161028b91906127e7565b60405180910390f35b34801561029f575f80fd5b506102a8610a9a565b005b3480156102b5575f80fd5b506102d060048036038101906102cb9190612800565b610aad565b6040516102dd91906128e2565b60405180910390f35b3480156102f1575f80fd5b506102fa610d0a565b604051610307919061291c565b60405180910390f35b34801561031b575f80fd5b50610324610d1c565b6040516103319190612944565b60405180910390f35b348015610345575f80fd5b50610360600480360381019061035b91906129b2565b610d43565b005b34801561036d575f80fd5b5061038860048036038101906103839190612800565b610d84565b60405161039591906128e2565b60405180910390f35b3480156103a9575f80fd5b506103b2610fdf565b005b3480156103bf575f80fd5b506103c8611002565b6040516103d591906125ee565b60405180910390f35b6103f860048036038101906103f391906125b4565b611029565b60405161040591906125ee565b60405180910390f35b348015610419575f80fd5b50610434600480360381019061042f91906125b4565b611344565b604051610441919061291c565b60405180910390f35b348015610455575f80fd5b50610470600480360381019061046b91906129fd565b611422565b005b34801561047d575f80fd5b50610498600480360381019061049391906125b4565b611876565b6040516104a591906125ee565b60405180910390f35b3480156104b9575f80fd5b506104d460048036038101906104cf91906125b4565b6118e9565b005b3480156104e1575f80fd5b506104ea611f20565b6040516104f791906127e7565b60405180910390f35b34801561050b575f80fd5b5061052660048036038101906105219190612a3b565b611f44565b005b348015610533575f80fd5b5061054e60048036038101906105499190612800565b611f85565b005b34801561055b575f80fd5b5061057660048036038101906105719190612a98565b612007565b60405161058391906125ee565b60405180910390f35b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f600482101580156105c45750600a8211155b610603576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fa90612b30565b60405180910390fd5b620203a0826187f06106159190612b7b565b61061f9190612bbc565b9050919050565b5f6187f0620203a0836106399190612bef565b6106439190612c4f565b9050919050565b5f63150b7a0260e01b905095945050505050565b610666612080565b5f600354146106aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a190612cc9565b60405180910390fd5b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b67fc9e66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107399190612cfb565b905060405180608001604052805f81526020015f81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001609681525060055f8081526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050508073ffffffffffffffffffffffffffffffffffffffff165f7fdb3da22d51c55d1ef1754d6364dfeab7810001722856b1bae07b2242a33473d9609660405161083191906125ee565b60405180910390a360405180608001604052805f81526020015f81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001600a81525060055f600181526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050508073ffffffffffffffffffffffffffffffffffffffff1660017fdb3da22d51c55d1ef1754d6364dfeab7810001722856b1bae07b2242a33473d9600a60405161093191906125ee565b60405180910390a35f5b60968110156109775760075f908060018154018082558091505060019003905f5260205f20015f9091909190915055808060010191505061093b565b505f5b600a8110156109b75760076001908060018154018082558091505060019003905f5260205f20015f9091909190915055808060010191505061097a565b50600160085f6101000a81548160ff0219169083151502179055504260038190555050565b6109e4612080565b6109ec610d1c565b73ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015610a2e573d5f803e3d5ffd5b507f7635c1d36c3210c9a5d0992d3653cf078347a14f938bb48667296c19ae0e1f0342604051610a5e91906125ee565b60405180910390a1565b5f610a93827f000000000000000000000000000000000000000000000001ee8307d7c59908006120fe565b9050919050565b610aa2612080565b610aab5f612114565b565b60605f805b60065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610ba0575f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610b4a57610b49612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610b7f5750805f01544310155b15610b915783610b8e90612d53565b93505b50508080600101915050610ab2565b505f808267ffffffffffffffff811115610bbd57610bbc612d9a565b5b604051908082528060200260200182016040528015610beb5781602001602082028036833780820191505090505b5090505f5b60065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610cfe575f60065f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610c8857610c87612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610cbd5750805f01544310155b15610cef5781848680610ccf90612d53565b975081518110610ce257610ce1612d26565b5b6020026020010181815250505b50508080600101915050610bf0565b50809350505050919050565b60085f9054906101000a900460ff1681565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f5b82829050811015610d7f57610d72838383818110610d6657610d65612d26565b5b905060200201356118e9565b8080600101915050610d45565b505050565b60605f805b60065f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610e76575f60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610e2157610e20612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610e555750805f015443105b15610e675783610e6490612d53565b93505b50508080600101915050610d89565b505f808267ffffffffffffffff811115610e9357610e92612d9a565b5b604051908082528060200260200182016040528015610ec15781602001602082028036833780820191505090505b5090505f5b60065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811015610fd3575f60065f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208281548110610f5e57610f5d612d26565b5b905f5260205f20015490505f60055f8381526020019081526020015f2090505f815f015414158015610f925750805f015443105b15610fc45781848680610fa490612d53565b975081518110610fb757610fb6612d26565b5b6020026020010181815250505b50508080600101915050610ec6565b50809350505050919050565b610fe7612080565b5f60085f6101000a81548160ff021916908315150217905550565b5f61102461101c600354426110179190612bbc565b6121d5565b600254612007565b905090565b5f60085f9054906101000a900460ff16611078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106f90612e11565b60405180910390fd5b6003544210156110bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b490612e79565b60405180910390fd5b61042d826002546110ce9190612bef565b111561110f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110690612ee1565b60405180910390fd5b5f8211801561111f575060328211155b61115e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115590612f49565b60405180910390fd5b611166611002565b90505f8183029050803410156111b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a890612fb1565b60405180910390fd5b8260025f82825401925050819055505f5b838110156113315760015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636a627842336040518263ffffffff1660e01b81526004016112249190612944565b5f604051808303815f87803b15801561123b575f80fd5b505af115801561124d573d5f803e3d5ffd5b505050503373ffffffffffffffffffffffffffffffffffffffff166001805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636be78f766040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112f79190612fe3565b037f3f30939db62a9977a0d3dd0a8776309093ded9da114c6095d1d189bcb43854dd60405160405180910390a380806001019150506111c2565b5061133e338234036121ed565b50919050565b5f8060055f8481526020019081526020015f206003015414801561137a57505f60055f8481526020019081526020015f205f0154145b801561141b575060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e79836040518263ffffffff1660e01b81526004016113db91906125ee565b602060405180830381865afa1580156113f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061141a9190613038565b5b9050919050565b60085f9054906101000a900460ff16611470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146790612e11565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff1660015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b81526004016114e191906125ee565b602060405180830381865afa1580156114fc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115209190612cfb565b73ffffffffffffffffffffffffffffffffffffffff1614611576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156d906130ad565b60405180910390fd5b5f60055f8481526020019081526020015f2060030154146115cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c390613115565b60405180910390fd5b5f60055f8481526020019081526020015f205f015414611621576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116189061317d565b60405180910390fd5b600481101580156116335750600a8111155b611672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166990612b30565b60405180910390fd5b5f61167c826105b1565b9050604051806080016040528082436116959190612bef565b81526020018281526020013373ffffffffffffffffffffffffffffffffffffffff1681526020015f81525060055f8581526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003015590505060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2083908060018154018082558091505060019003905f5260205f20015f90919091909150553373ffffffffffffffffffffffffffffffffffffffff16837fd9f5ab4cc12671e09c1c99df4949527872aa143457644a0ae270eebb8b58cd59836040516117de91906125ee565b60405180910390a360015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3330866040518463ffffffff1660e01b81526004016118449392919061319b565b5f604051808303815f87803b15801561185b575f80fd5b505af115801561186d573d5f803e3d5ffd5b50505050505050565b5f600482101580156118895750600a8211155b6118c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118bf90612b30565b60405180910390fd5b8160a76118d59190612b7b565b610a6b6118e29190612bbc565b9050919050565b5f60055f8381526020019081526020015f2090505f816003015414611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90613115565b60405180910390fd5b5f815f015403611988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197f9061321a565b60405180910390fd5b805f01544310156119ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c590613282565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480611a5d5750611a2e610d1c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611a9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a93906132ea565b60405180910390fd5b5f600143611aaa9190612bbc565b40600454414442604051602001611ac59594939291906133a7565b604051602081830303815290604052805190602001205f1c9050600160045f828254611af19190612bef565b925050819055505f611b068360010154610626565b90505f611b1282611876565b61271084611b209190613405565b1090505f8115611d30575f6007808054905086611b3d9190613405565b81548110611b4e57611b4d612d26565b5b905f5260205f200154905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e826040518263ffffffff1660e01b8152600401611bb391906125ee565b602060405180830381865afa158015611bce573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bf29190612cfb565b915060405180608001604052805f81526020015f81526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525060055f8981526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050508173ffffffffffffffffffffffffffffffffffffffff16866002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16887fdfe44e8c2446ef07b6112cd25fdf9a97c447d5673fd84cafae7bb4e48bc35dab84604051611d2291906125ee565b60405180910390a450611e8d565b3390508285600301819055505f855f01819055505f85600101819055505f5b8560030154811015611d8e57600787908060018154018082558091505060019003905f5260205f20015f90919091909150558080600101915050611d4f565b50846002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16867fdb3da22d51c55d1ef1754d6364dfeab7810001722856b1bae07b2242a33473d98760030154604051611dfd91906125ee565b60405180910390a360015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633190b9ea876040518263ffffffff1660e01b8152600401611e5f91906125ee565b5f604051808303815f87803b158015611e76575f80fd5b505af1158015611e88573d5f803e3d5ffd5b505050505b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3083896040518463ffffffff1660e01b8152600401611eeb9392919061319b565b5f604051808303815f87803b158015611f02575f80fd5b505af1158015611f14573d5f803e3d5ffd5b50505050505050505050565b7f00000000000000000000000000000000000000000000000000354a6ba7a1800081565b5f5b83839050811015611f7f57611f74848483818110611f6757611f66612d26565b5b9050602002013583611422565b806001019050611f46565b50505050565b611f8d612080565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ffb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ff2906134a5565b60405180910390fd5b61200481612114565b50565b5f6120787f00000000000000000000000000000000000000000000000000354a6ba7a1800061207361206e7fffffffffffffffffffffffffffffffffffffffffffffffffff6ef89cbd98e5666120676120626001890161223d565b610a68565b8803612250565b612266565b612485565b905092915050565b6120886124df565b73ffffffffffffffffffffffffffffffffffffffff166120a6610d1c565b73ffffffffffffffffffffffffffffffffffffffff16146120fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f39061350d565b60405180910390fd5b565b5f81670de0b6b3a7640000840205905092915050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f62015180670de0b6b3a76400008302049050919050565b5f805f805f85875af1905080612238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161222f90613575565b60405180910390fd5b505050565b5f670de0b6b3a764000082029050919050565b5f670de0b6b3a764000082840205905092915050565b5f7ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213612296575f9050612480565b680755bf798b4a1bf1e582126122e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122d8906135dd565b60405180910390fd5b6503782dace9d9604e83901b816122fb576122fa612c22565b5b0591505f60606b8000000000000000000000006bb17217f7d1cf79abc9e3b398606086901b8161232e5761232d612c22565b5b0501901d90506bb17217f7d1cf79abc9e3b3988102830392505f6c10fe68e7fd37d0007b713f7650840190506d02d16720577bd19bf614176fe9ea6060858302901d0190505f6d04a4fd9f2a8b96949216d2255a6c8583010390506e0587f503bb6ea29d25fcb7401964506060838302901d01905079d835ebba824c98fb31b83b2ca45c0000000000000000000000008582020190505f6c240c330e9fb2d9cbaf0fd5aafc860390506d0277594991cfc85f6e2461837cd96060878302901d0190506d1a521255e34f6a5061b25ef1c9c46060878302901d0390506db1bbb201f443cf962f1a1d3db4a56060878302901d0190506e02c72388d9f74f51a9331fed693f156060878302901d0390506e05180bb14799ab47a8a8cb2a527d576060878302901d01905080820594508360c30374029d9dc38563c32e5c2f6dc192ee70ef65f9978af38602901c9450505050505b919050565b5f7f800000000000000000000000000000000000000000000000000000000000000082145f19841416156124b7575f80fd5b818302905081838205148315176124cc575f80fd5b670de0b6b3a76400008105905092915050565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61252861252361251e846124e6565b612505565b6124e6565b9050919050565b5f6125398261250e565b9050919050565b5f61254a8261252f565b9050919050565b61255a81612540565b82525050565b5f6020820190506125735f830184612551565b92915050565b5f80fd5b5f80fd5b5f819050919050565b61259381612581565b811461259d575f80fd5b50565b5f813590506125ae8161258a565b92915050565b5f602082840312156125c9576125c8612579565b5b5f6125d6848285016125a0565b91505092915050565b6125e881612581565b82525050565b5f6020820190506126015f8301846125df565b92915050565b5f612611826124e6565b9050919050565b61262181612607565b811461262b575f80fd5b50565b5f8135905061263c81612618565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f84011261266357612662612642565b5b8235905067ffffffffffffffff8111156126805761267f612646565b5b60208301915083600182028301111561269c5761269b61264a565b5b9250929050565b5f805f805f608086880312156126bc576126bb612579565b5b5f6126c98882890161262e565b95505060206126da8882890161262e565b94505060406126eb888289016125a0565b935050606086013567ffffffffffffffff81111561270c5761270b61257d565b5b6127188882890161264e565b92509250509295509295909350565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61275b81612727565b82525050565b5f6020820190506127745f830184612752565b92915050565b5f819050919050565b61278c8161277a565b8114612796575f80fd5b50565b5f813590506127a781612783565b92915050565b5f602082840312156127c2576127c1612579565b5b5f6127cf84828501612799565b91505092915050565b6127e18161277a565b82525050565b5f6020820190506127fa5f8301846127d8565b92915050565b5f6020828403121561281557612814612579565b5b5f6128228482850161262e565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61285d81612581565b82525050565b5f61286e8383612854565b60208301905092915050565b5f602082019050919050565b5f6128908261282b565b61289a8185612835565b93506128a583612845565b805f5b838110156128d55781516128bc8882612863565b97506128c78361287a565b9250506001810190506128a8565b5085935050505092915050565b5f6020820190508181035f8301526128fa8184612886565b905092915050565b5f8115159050919050565b61291681612902565b82525050565b5f60208201905061292f5f83018461290d565b92915050565b61293e81612607565b82525050565b5f6020820190506129575f830184612935565b92915050565b5f8083601f84011261297257612971612642565b5b8235905067ffffffffffffffff81111561298f5761298e612646565b5b6020830191508360208202830111156129ab576129aa61264a565b5b9250929050565b5f80602083850312156129c8576129c7612579565b5b5f83013567ffffffffffffffff8111156129e5576129e461257d565b5b6129f18582860161295d565b92509250509250929050565b5f8060408385031215612a1357612a12612579565b5b5f612a20858286016125a0565b9250506020612a31858286016125a0565b9150509250929050565b5f805f60408486031215612a5257612a51612579565b5b5f84013567ffffffffffffffff811115612a6f57612a6e61257d565b5b612a7b8682870161295d565b93509350506020612a8e868287016125a0565b9150509250925092565b5f8060408385031215612aae57612aad612579565b5b5f612abb85828601612799565b9250506020612acc858286016125a0565b9150509250929050565b5f82825260208201905092915050565b7f494e56414c49445f52414e4b00000000000000000000000000000000000000005f82015250565b5f612b1a600c83612ad6565b9150612b2582612ae6565b602082019050919050565b5f6020820190508181035f830152612b4781612b0e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612b8582612581565b9150612b9083612581565b9250828202612b9e81612581565b91508282048414831517612bb557612bb4612b4e565b5b5092915050565b5f612bc682612581565b9150612bd183612581565b9250828203905081811115612be957612be8612b4e565b5b92915050565b5f612bf982612581565b9150612c0483612581565b9250828201905080821115612c1c57612c1b612b4e565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612c5982612581565b9150612c6483612581565b925082612c7457612c73612c22565b5b828204905092915050565b7f414c52454144595f4157414b45000000000000000000000000000000000000005f82015250565b5f612cb3600d83612ad6565b9150612cbe82612c7f565b602082019050919050565b5f6020820190508181035f830152612ce081612ca7565b9050919050565b5f81519050612cf581612618565b92915050565b5f60208284031215612d1057612d0f612579565b5b5f612d1d84828501612ce7565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f612d5d82612581565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612d8f57612d8e612b4e565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e455354494e475f494e414354495645000000000000000000000000000000005f82015250565b5f612dfb601083612ad6565b9150612e0682612dc7565b602082019050919050565b5f6020820190508181035f830152612e2881612def565b9050919050565b7f53414c455f494e414354495645000000000000000000000000000000000000005f82015250565b5f612e63600d83612ad6565b9150612e6e82612e2f565b602082019050919050565b5f6020820190508181035f830152612e9081612e57565b9050919050565b7f535550504c595f455848415553544544000000000000000000000000000000005f82015250565b5f612ecb601083612ad6565b9150612ed682612e97565b602082019050919050565b5f6020820190508181035f830152612ef881612ebf565b9050919050565b7f4f524445525f5154595f494e56414c49440000000000000000000000000000005f82015250565b5f612f33601183612ad6565b9150612f3e82612eff565b602082019050919050565b5f6020820190508181035f830152612f6081612f27565b9050919050565b7f554e4445525041494400000000000000000000000000000000000000000000005f82015250565b5f612f9b600983612ad6565b9150612fa682612f67565b602082019050919050565b5f6020820190508181035f830152612fc881612f8f565b9050919050565b5f81519050612fdd8161258a565b92915050565b5f60208284031215612ff857612ff7612579565b5b5f61300584828501612fcf565b91505092915050565b61301781612902565b8114613021575f80fd5b50565b5f815190506130328161300e565b92915050565b5f6020828403121561304d5761304c612579565b5b5f61305a84828501613024565b91505092915050565b7f4e4f545f5448455f4547475f4f574e45520000000000000000000000000000005f82015250565b5f613097601183612ad6565b91506130a282613063565b602082019050919050565b5f6020820190508181035f8301526130c48161308b565b9050919050565b7f4547475f414c52454144595f48415443484544000000000000000000000000005f82015250565b5f6130ff601383612ad6565b915061310a826130cb565b602082019050919050565b5f6020820190508181035f83015261312c816130f3565b9050919050565b7f4547475f414c52454144595f4e455354454400000000000000000000000000005f82015250565b5f613167601283612ad6565b915061317282613133565b602082019050919050565b5f6020820190508181035f8301526131948161315b565b9050919050565b5f6060820190506131ae5f830186612935565b6131bb6020830185612935565b6131c860408301846125df565b949350505050565b7f4547475f4e4f545f5945545f4e455354454400000000000000000000000000005f82015250565b5f613204601283612ad6565b915061320f826131d0565b602082019050919050565b5f6020820190508181035f830152613231816131f8565b9050919050565b7f4e455354494e475f494e434f4d504c45544500000000000000000000000000005f82015250565b5f61326c601283612ad6565b915061327782613238565b602082019050919050565b5f6020820190508181035f83015261329981613260565b9050919050565b7f4e4f545f5448455f4e45535445525f4f525f434f4e54524143545f4f574e45525f82015250565b5f6132d4602083612ad6565b91506132df826132a0565b602082019050919050565b5f6020820190508181035f830152613301816132c8565b9050919050565b5f819050919050565b5f819050919050565b61332b61332682613308565b613311565b82525050565b5f819050919050565b61334b61334682612581565b613331565b82525050565b5f61335b826124e6565b9050919050565b5f8160601b9050919050565b5f61337882613362565b9050919050565b5f6133898261336e565b9050919050565b6133a161339c82613351565b61337f565b82525050565b5f6133b2828861331a565b6020820191506133c2828761333a565b6020820191506133d28286613390565b6014820191506133e2828561333a565b6020820191506133f2828461333a565b6020820191508190509695505050505050565b5f61340f82612581565b915061341a83612581565b92508261342a57613429612c22565b5b828206905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f61348f602683612ad6565b915061349a82613435565b604082019050919050565b5f6020820190508181035f8301526134bc81613483565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f6134f7602083612ad6565b9150613502826134c3565b602082019050919050565b5f6020820190508181035f830152613524816134eb565b9050919050565b7f4554485f5452414e534645525f4641494c4544000000000000000000000000005f82015250565b5f61355f601383612ad6565b915061356a8261352b565b602082019050919050565b5f6020820190508181035f83015261358c81613553565b9050919050565b7f4558505f4f564552464c4f5700000000000000000000000000000000000000005f82015250565b5f6135c7600c83612ad6565b91506135d282613593565b602082019050919050565b5f6020820190508181035f8301526135f4816135bb565b905091905056fea2646970667358221220ad2bdc3991a42ac6154d6d82bf9dae1d0236913abc1dde663538fece54e3bd7b64736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000aee9f5908e70a749e9289d61cd37757e62bed50a00000000000000000000000000000000000000000000000000354a6ba7a18000000000000000000000000000000000000000000000000000008e1bc9bf040000000000000000000000000000000000000000000000000001ee8307d7c5990800000000000000000000000000000000000000000000000002f87191df43ea2c68
-----Decoded View---------------
Arg [0] : _roostAddress (address): 0xaeE9F5908e70a749e9289d61cD37757e62bED50A
Arg [1] : _targetPrice (int256): 15000000000000000
Arg [2] : _priceDecayPercent (int256): 40000000000000000
Arg [3] : _perTimeUnit (int256): 35633333300000000000
Arg [4] : _entropy (uint256): 54795738529296690280
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000aee9f5908e70a749e9289d61cd37757e62bed50a
Arg [1] : 00000000000000000000000000000000000000000000000000354a6ba7a18000
Arg [2] : 000000000000000000000000000000000000000000000000008e1bc9bf040000
Arg [3] : 000000000000000000000000000000000000000000000001ee8307d7c5990800
Arg [4] : 000000000000000000000000000000000000000000000002f87191df43ea2c68
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.