Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Boardroom
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./utils/ContractGuard.sol"; import "./utils/ShareWrapper.sol"; import "./interfaces/IWETH.sol"; import "./interfaces/IBasisAsset.sol"; import "./interfaces/ITreasury.sol"; import "./interfaces/IBoardroom.sol"; import "./interfaces/IEscrow.sol"; import "./interfaces/IOracle.sol"; /// @title Boardroom /// @notice This contract handles staking, reward allocation, and reward distribution for share holders. /// It supports multi-peg rewards by maintaining a separate reward snapshot history for each peg token. /// The contract is protected against reentrancy and is upgradeable. contract Boardroom is IBoardroom, ShareWrapper, ContractGuard, ReentrancyGuard, OwnableUpgradeable { using SafeERC20 for IERC20; /* ========== DATA STRUCTURES ========== */ /// @notice Holds per-member reward data. struct Memberseat { uint256 lastSnapshotIndex; // Index of the last snapshot when rewards were updated. uint256 rewardEarned; // Accumulated rewards earned but not yet claimed. } /// @notice Represents a snapshot of the boardroom state for a peg token. struct BoardroomSnapshot { uint256 time; // Block number when the snapshot was taken. uint256 rewardReceived; // Total rewards received in this snapshot. uint256 rewardPerShare; // Cumulative reward per share (scaled by 1e18). } /// @notice Stores data for a pending withdrawal request. struct PendingWithdraw { uint256 amount; // Amount of staked shares requested for withdrawal. uint256 unlockEpoch; // Epoch at which the withdrawal can be finalized. } /* ========== STATE VARIABLES ========== */ ITreasury public treasury; // Treasury contract reference. address[] public pegTokens; // List of peg token addresses (e.g., GREEN, BLUE). /// @notice Maps a member to their epoch timer start (used for lockup periods). mapping(address => uint256) public epochTimerStart; /// @notice Maps a peg token and member to their reward data. mapping(address => mapping(address => Memberseat)) public members; /// @notice Maps a peg token to its snapshot history. mapping(address => BoardroomSnapshot[]) public boardroomHistory; /// @notice Stores pending withdrawal requests for each member. mapping(address => PendingWithdraw) public pendingWithdrawals; /// @notice Number of epochs a member must wait after staking before they can withdraw. uint256 public withdrawLockupEpochs; /// @notice Number of epochs a member must wait after staking before they can claim rewards. uint256 public rewardLockupEpochs; /// @notice If a member does not claim rewards within this number of epochs, rewards will be burned. uint256 public claimRewardsBurnEpochs; /// @notice Configurable burn percentage for the immediate claim option (in basis points, where 10000 = 100%). uint256 public immediateClaimSacrificePercent; /// @notice Configurable vesting duration for Option 2 (in seconds). uint256 public vestingDuration; /// @notice Mapping from a peg token address to its escrow token address (for vesting claims). mapping(address => address) public escrowTokens; // For Option 3: IWETH public wrappedSonic; /// @notice Maps a peg token address to its Sonic-price oracle address. mapping(address => address) public tokenInSonicOracles; /// @notice Address of the collateral pool to which Sonic is forwarded. address public collateralPool; /// @notice Peg stability module fee in basis points (e.g., 1500 for 15%). Must be between 500 (5%) and 3000 (30%). uint256 public pegStabilityModuleFee; /* =================== Added variables for proxy compatibility =================== */ // Reserved for future variables /* ========== EVENTS ========== */ /// @notice Emitted when a member stakes shares. event Staked(address indexed user, uint256 amount); /// @notice Emitted when a member requests a pending withdrawal. event PendingWithdrawRequested(address indexed user, uint256 amount, uint256 unlockEpoch); /// @notice Emitted when a member cancels a pending withdrawal. event CancelPendingWithdraw(address indexed user, uint256 amount); /// @notice Emitted when a member finalizes a pending withdrawal. event PendingWithdrawFinalized(address indexed user, uint256 amount); /// @notice Emitted when a member claims rewards. event RewardPaid(address indexed token, address indexed user, uint256 reward); /// @notice Emitted when rewards are added to the boardroom snapshot. event RewardAdded(address indexed token, address indexed user, uint256 reward); /// @notice Emitted when a member sacrifices (burns) their reward. event RewardSacrificed(address indexed token, address indexed user, uint256 reward); /// @notice Emitted when a vested reward is recorded. event VestedRewardRecorded(address indexed token, address indexed user, uint256 amount, uint256 vestingEnd); /// @notice Emitted when native Sonic is used as a bribe. event SonicBribed(address indexed user, uint256 amount); /* ========== MODIFIERS ========== */ /// @notice Restricts function execution to the Treasury contract. modifier onlyTreasury() { require(address(treasury) == msg.sender, "Boardroom: caller is not the treasury"); _; } /// @notice Ensures the caller has a positive staked balance. modifier memberExists() { require(balanceOf(msg.sender) > 0, "Boardroom: The member does not exist"); _; } /// @notice Updates reward data for the given member across all peg tokens. modifier updateReward(address _member) { if (_member != address(0)) { uint256 len = pegTokens.length; for (uint256 i = 0; i < len; ++i) { address token = pegTokens[i]; Memberseat memory seat = members[token][_member]; seat.rewardEarned = earned(token, _member); seat.lastSnapshotIndex = latestSnapshotIndex(token); members[token][_member] = seat; } } _; } /* ========== GOVERNANCE FUNCTIONS ========== */ /** * @notice Initializes the Boardroom. * @param _green Address of the GREEN token. * @param _blue Address of the BLUE token. * @param _red Address of the RED token used for shares. * @param _collateralPool The collateral pool address. * @param _treasury The Treasury contract. */ function initialize( address _green, address _blue, address _red, address _collateralPool, ITreasury _treasury ) external initializer { OwnableUpgradeable.__Ownable_init(msg.sender); // Set the share token to RED. share = IERC20(_red); collateralPool = _collateralPool; treasury = _treasury; // Configure peg tokens (GREEN and BLUE). pegTokens.push(_green); pegTokens.push(_blue); // Initialize snapshot history for each peg token with an initial snapshot. boardroomHistory[_green].push(BoardroomSnapshot({ time: block.number, rewardReceived: 0, rewardPerShare: 0 })); boardroomHistory[_blue].push(BoardroomSnapshot({ time: block.number, rewardReceived: 0, rewardPerShare: 0 })); // Set lockup parameters. withdrawLockupEpochs = 6; // 6 epochs lockup for withdrawal. rewardLockupEpochs = 2; // 2 epochs lockup for reward claim. claimRewardsBurnEpochs = 8; // Rewards unclaimed for 8 epochs will be burned. // Set default immediate claim sacrifice percentage to 30% (3000 basis points). immediateClaimSacrificePercent = 3000; // Set default vesting duration for Option 2. vestingDuration = 7 days; // Set default peg stability module fee to 15% (1500 basis points). pegStabilityModuleFee = 1500; wrappedSonic = IWETH(0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38); } /** * @notice Allows the contract to receive native Sonic. */ receive() external payable { // Accept native Sonic deposits. } /** * @notice Sets the lockup durations for withdrawal, reward claim, and reward burn. * @param _withdrawLockupEpochs Number of epochs to lock withdrawal. * @param _rewardLockupEpochs Number of epochs to lock reward claims. * @param _claimRewardsBurnEpochs Number of epochs after which unclaimed rewards are burned. */ function setLockUp( uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs, uint256 _claimRewardsBurnEpochs ) external onlyOwner { require(_rewardLockupEpochs <= 21 && _withdrawLockupEpochs <= 21 && _claimRewardsBurnEpochs <= 21, "lockupEpochs cannot exceed 1 week"); require(_rewardLockupEpochs + 2 <= _claimRewardsBurnEpochs, "Need window for user to claim before burning rewards"); require(_claimRewardsBurnEpochs >= 6, "At least 2 days before rewards are burnt"); withdrawLockupEpochs = _withdrawLockupEpochs; rewardLockupEpochs = _rewardLockupEpochs; claimRewardsBurnEpochs = _claimRewardsBurnEpochs; } /** * @notice Updates the immediate claim sacrifice percentage. * @param _percent The new percentage in basis points (e.g., 5000 for 50%). Must be between 0 and 10000. */ function setImmediateClaimSacrificePercent(uint256 _percent) external onlyOwner { require(_percent <= 10000, "Invalid percentage"); immediateClaimSacrificePercent = _percent; } /** * @notice Sets the vesting duration for Option 2 (vesting claim). * @param _duration The new vesting duration in seconds. */ function setVestingDuration(uint256 _duration) external onlyOwner { require(_duration > 0, "Vesting duration must be > 0"); vestingDuration = _duration; } /** * @notice Sets the escrow token address for a given peg token. * @param _pegToken The peg token address. * @param _escrowToken The corresponding escrow token address. */ function setEscrowToken(address _pegToken, address _escrowToken) external onlyOwner { require(_escrowToken != address(0), "Zero address"); escrowTokens[_pegToken] = _escrowToken; } /** * @notice Sets the Wrapped Sonic contract. * @param _wrappedSonic The address of the Wrapped Sonic contract. */ function setWSonic(IWETH _wrappedSonic) external onlyOwner { require(address(_wrappedSonic) != address(0), "Invalid Wrapped Sonic address"); wrappedSonic = _wrappedSonic; } /** * @notice Sets the Sonic oracle for a given peg token. * @param _pegToken The peg token address. * @param _oracle The oracle address that returns the token price in Sonic. */ function setTokenInSonicOracle(address _pegToken, address _oracle) external onlyOwner { require(_pegToken != address(0) && _oracle != address(0), "Invalid address"); tokenInSonicOracles[_pegToken] = _oracle; } /** * @notice Sets the collateral pool address. * @param _collateralPool The new collateral pool address. */ function setCollateralPool(address _collateralPool) external onlyOwner { require(_collateralPool != address(0), "Invalid collateral pool address"); collateralPool = _collateralPool; } /** * @notice Sets the peg stability module fee. * @param _fee The new fee in basis points (e.g., 1500 for 15%). * It must be between 500 (5%) and 3000 (30%). */ function setPegStabilityModuleFee(uint256 _fee) external onlyOwner { require(_fee >= 500 && _fee <= 3000, "Boardroom: fee must be between 5% and 30%"); pegStabilityModuleFee = _fee; } /** * @notice Adds a new peg token to the boardroom. * @param _token The peg token address to add. */ function addPegToken(address _token) external onlyOwner { require(boardroomHistory[_token].length == 0, "Boardroom: boardroomHistory exists"); require(IERC20(_token).totalSupply() > 0, "Boardroom: invalid token"); uint256 len = pegTokens.length; for (uint256 i = 0; i < len; ++i) { require(pegTokens[i] != _token, "Boardroom: existing token"); } pegTokens.push(_token); boardroomHistory[_token].push(BoardroomSnapshot({ time: block.number, rewardReceived: 0, rewardPerShare: 0 })); } /* ========== VIEW FUNCTIONS ========== */ /** * @notice Returns the latest snapshot index for a given peg token. * @param _token The peg token address. * @return The index of the latest snapshot. */ function latestSnapshotIndex(address _token) public view returns (uint256) { return boardroomHistory[_token].length - 1; } /** * @notice Retrieves the latest snapshot for a given peg token. * @param _token The peg token address. * @return The latest BoardroomSnapshot. */ function getLatestSnapshot(address _token) internal view returns (BoardroomSnapshot memory) { return boardroomHistory[_token][latestSnapshotIndex(_token)]; } /** * @notice Retrieves the last snapshot index for a member and peg token. * @param _token The peg token address. * @param _member The member's address. * @return The snapshot index. */ function getLastSnapshotIndexOf(address _token, address _member) public view returns (uint256) { return members[_token][_member].lastSnapshotIndex; } /** * @notice Retrieves the last snapshot for a member for a specific peg token. * @param _token The peg token address. * @param _member The member's address. * @return The BoardroomSnapshot at the member's last snapshot index. */ function getLastSnapshotOf(address _token, address _member) internal view returns (BoardroomSnapshot memory) { return boardroomHistory[_token][getLastSnapshotIndexOf(_token, _member)]; } /** * @notice Checks whether a member can claim rewards based on the lockup period. * @param member The member's address. * @return True if the member can claim rewards. */ function canClaimReward(address member) external view returns (bool) { return epochTimerStart[member] + rewardLockupEpochs <= treasury.epoch(); } /** * @notice Provides information on whether a member's rewards will be burnt if unclaimed and the burn epoch. * @param member The member's address. * @return _burned True if rewards will be burnt. * @return _burningEpoch The epoch at which rewards will be burnt. */ function burningRewardsInfo(address member) external view returns (bool _burned, uint256 _burningEpoch) { uint256 startEpoch = epochTimerStart[member]; _burned = startEpoch + claimRewardsBurnEpochs <= treasury.epoch(); _burningEpoch = 0; if (startEpoch > 0 && startEpoch <= treasury.epoch()) { _burningEpoch = startEpoch + claimRewardsBurnEpochs; } } /** * @notice Returns the current treasury epoch. * @return The current epoch. */ function epoch() external view returns (uint256) { return treasury.epoch(); } /** * @notice Returns the timestamp for the next treasury epoch. * @return The next epoch's timestamp. */ function nextEpochPoint() external view returns (uint256) { return treasury.nextEpochPoint(); } /** * @notice Returns the length (in seconds) of the next treasury epoch. * @return The epoch length. */ function nextEpochLength() external view returns (uint256) { return treasury.nextEpochLength(); } /** * @notice Retrieves the peg token price from the Treasury. * @param _token The peg token address. * @return The peg token price. */ function getPegTokenPrice(address _token) external view returns (uint256) { return treasury.getPegTokenPrice(_token); } /** * @notice Retrieves the peg token price in Sonic by querying the corresponding oracle. * @param _token The peg token address. * @return The price in Sonic (scaled by 1e18). */ function getPegTokenPriceInSonic(address _token) public view returns (uint256) { try IOracle(tokenInSonicOracles[_token]).twap(_token, 1e18) returns (uint144 price) { return uint256(price); } catch { revert("Boardroom: oracle failed"); } } /** * @notice Calculates the total Sonic fee required for claiming rewards using Option 3. * @param _user The address of the member. * @return totalSonicFee The total amount of Sonic (in wei) required as a bribe fee. */ function getSonicFeeForOption3(address _user) external view returns (uint256 totalSonicFee) { uint256 len = pegTokens.length; totalSonicFee = 0; for (uint256 i = 0; i < len; ++i) { address token = pegTokens[i]; uint256 reward = earned(token, _user); // Calculation: fee = (priceInSonic * reward * pegStabilityModuleFee) / 1e22. // getPegTokenPriceInSonic returns the token price in Sonic scaled by 1e18, // pegStabilityModuleFee is in basis points (e.g., 1500 for 15%), // and dividing by 1e22 adjusts the scale. totalSonicFee += getPegTokenPriceInSonic(token) * reward * pegStabilityModuleFee / 1e22; } } /** * @notice Returns the reward per share for a given peg token. * @param _token The peg token address. * @return The reward per share (scaled by 1e18). */ function rewardPerShare(address _token) public view returns (uint256) { return getLatestSnapshot(_token).rewardPerShare; } /** * @notice Returns the number of peg tokens configured. * @return The count of peg tokens. */ function numOfPegTokens() public view returns (uint256) { return pegTokens.length; } /** * @notice Calculates the reward earned by a member for a specific peg token. * @param _token The peg token address. * @param _member The member's address. * @return The total earned reward. */ function earned(address _token, address _member) public view returns (uint256) { uint256 latestRPS = getLatestSnapshot(_token).rewardPerShare; uint256 storedRPS = getLastSnapshotOf(_token, _member).rewardPerShare; return (balanceOf(_member) * (latestRPS - storedRPS) / 1e18) + members[_token][_member].rewardEarned; } /** * @notice Returns the earned rewards for each peg token for a member. * @param _member The member's address. * @return _numOfPegTokens The number of peg tokens. * @return _pegTokenAddresses The list of peg token addresses. * @return _earnedPegTokens The list of earned rewards per peg token. */ function earnedAll(address _member) external view returns (uint256 _numOfPegTokens, address[] memory _pegTokenAddresses, uint256[] memory _earnedPegTokens) { _numOfPegTokens = numOfPegTokens(); _pegTokenAddresses = new address[](_numOfPegTokens); _earnedPegTokens = new uint256[](_numOfPegTokens); for (uint256 i = 0; i < _numOfPegTokens; i++) { _pegTokenAddresses[i] = pegTokens[i]; _earnedPegTokens[i] = earned(_pegTokenAddresses[i], _member); } } function vestingSchedule(address _token, address _member) public view returns (uint256 _claimable, uint256 _remaining, uint256 _endTime) { (uint256 _totalAmount, uint256 _claimedAmount, uint256 _startTime, uint256 _duration) = IEscrow(escrowTokens[_token]).vestingSchedule(_member); if (_duration > 0) { _endTime = _startTime + _duration; uint256 elapsed = block.timestamp > _endTime ? _duration : block.timestamp - _startTime; uint256 vestedAmount = (_totalAmount * elapsed) / _duration; _claimable = (vestedAmount <= _claimedAmount) ? 0 : vestedAmount - _claimedAmount; _remaining = _totalAmount - vestedAmount; } } function vestingScheduleAll(address _member) external view returns (uint256 _numOfPegTokens, address[] memory _pegTokenAddresses, uint256[] memory _claimables, uint256[] memory _remainings, uint256[] memory _endTimes) { _numOfPegTokens = numOfPegTokens(); _pegTokenAddresses = new address[](_numOfPegTokens); _claimables = new uint256[](_numOfPegTokens); _remainings = new uint256[](_numOfPegTokens); _endTimes = new uint256[](_numOfPegTokens); for (uint256 i = 0; i < _numOfPegTokens; i++) { address _token = pegTokens[i]; _pegTokenAddresses[i] = _token; (_claimables[i], _remainings[i], _endTimes[i]) = vestingSchedule(_token, _member); } } /* ========== MUTATIVE FUNCTIONS ========== */ /** * @notice Stakes share tokens into the boardroom. * Updates reward data, claims pending rewards if available, and resets the epoch timer. * @param amount The amount of shares to stake. */ function stake(uint256 amount) public override onlyOneBlock nonReentrant updateReward(msg.sender) { require(amount > 0, "Boardroom: Cannot stake 0"); uint256 currentEpoch = treasury.epoch(); if (epochTimerStart[msg.sender] + claimRewardsBurnEpochs <= treasury.epoch()) { _claimReward(0); // Option 3 may require sonic bribe cost calculation. } else { // Reset timer if reward lockup is still active. epochTimerStart[msg.sender] = currentEpoch; } super.stake(amount); epochTimerStart[msg.sender] = currentEpoch; // Reset lockup timer after staking. emit Staked(msg.sender, amount); } /** * @notice Initiates a withdrawal request by moving a specified amount of staked shares to a pending state. * The shares stop earning rewards immediately. * @param _amount The amount of shares to withdraw. */ function requestWithdraw(uint256 _amount) public onlyOneBlock nonReentrant memberExists updateReward(msg.sender) { require(_amount > 0, "Boardroom: Cannot withdraw 0"); uint256 unlockEpoch = treasury.epoch() + withdrawLockupEpochs; PendingWithdraw memory pending = pendingWithdrawals[msg.sender]; pending.amount += _amount; pending.unlockEpoch = unlockEpoch; pendingWithdrawals[msg.sender] = pending; _sacrificeReward(_amount); super._withdraw(_amount); emit PendingWithdrawRequested(msg.sender, _amount, unlockEpoch); } /** * @notice Cancels the current pending withdrawal request, returning the pending shares back to staked balance. */ function cancelPendingWithdraw() external onlyOneBlock nonReentrant updateReward(msg.sender) { PendingWithdraw memory pending = pendingWithdrawals[msg.sender]; uint256 amountToCancel = pending.amount; require(amountToCancel > 0, "Boardroom: no pending withdraw to cancel"); delete pendingWithdrawals[msg.sender]; // Clear pending withdrawal. super._cancelWithdraw(amountToCancel); emit CancelPendingWithdraw(msg.sender, amountToCancel); } /** * @notice Finalizes a pending withdrawal after the lockup period has expired. * Transfers the pending share tokens back to the member's wallet. */ function finalizeWithdraw() external onlyOneBlock nonReentrant updateReward(msg.sender) { PendingWithdraw memory pending = pendingWithdrawals[msg.sender]; require(pending.unlockEpoch <= treasury.epoch(), "Boardroom: still in withdraw lockup"); uint256 amountToWithdraw = pending.amount; delete pendingWithdrawals[msg.sender]; // Clear pending withdrawal. super._claimPendingWithdraw(amountToWithdraw); emit PendingWithdrawFinalized(msg.sender, amountToWithdraw); } /** * @notice Exits the boardroom by requesting withdrawal of all staked shares. */ function exit() external { requestWithdraw(balanceOf(msg.sender)); } /** * @dev Internal function that sacrifices a portion of a member's reward when initiating a withdrawal. * The sacrificed reward is burned. * @param _withdrawAmount The amount of staked shares being withdrawn. */ function _sacrificeReward(uint256 _withdrawAmount) internal updateReward(msg.sender) { uint256 len = pegTokens.length; for (uint256 i = 0; i < len; ++i) { address token = pegTokens[i]; uint256 reward = members[token][msg.sender].rewardEarned; if (reward > 0) { uint256 burnAmount = reward * _withdrawAmount / balanceOf(msg.sender); members[token][msg.sender].rewardEarned -= burnAmount; IBasisAsset(token).burn(burnAmount); emit RewardSacrificed(token, msg.sender, burnAmount); } } } function claimReward() external { require(epochTimerStart[msg.sender] + rewardLockupEpochs <= treasury.epoch(), "Boardroom: still in reward lockup"); _claimReward(1); } /** * @notice Claims accumulated rewards for all peg tokens for the caller. * Supports three options: * Option 1: Immediate Claim – burns a configurable percentage of the reward and pays out the rest. * Option 2: Vesting Claim – locks the reward in a vesting schedule. * Option 3: Option for direct claim with a Sonic bribe fee (for dynamic pricing via oracles). * @param _option The option selected (1 for Immediate, 2 for Vesting, 3 for direct claim with Sonic bribe). */ function claimRewardWithOption(uint256 _option) external payable { require(_option == 3 || msg.value == 0, "Only option 3 is payable"); require(epochTimerStart[msg.sender] + rewardLockupEpochs <= treasury.epoch(), "Boardroom: still in reward lockup"); _claimReward(_option); } /** * @dev Internal function to claim rewards based on the selected option. * For Option 1, a configurable percentage of the reward is burned. * For Option 2, rewards are locked in the escrow token (vesting). * For Option 3, a Sonic bribe fee is calculated and deducted. * @param _option The claim option selected. */ function _claimReward(uint256 _option) internal updateReward(msg.sender) { bool willBurn = epochTimerStart[msg.sender] + claimRewardsBurnEpochs <= treasury.epoch(); epochTimerStart[msg.sender] = treasury.epoch(); // Reset timer after claim. uint256 len = pegTokens.length; uint256 totalSonicFee = 0; for (uint256 i = 0; i < len; ++i) { address token = pegTokens[i]; uint256 reward = members[token][msg.sender].rewardEarned; if (reward > 0) { members[token][msg.sender].rewardEarned = 0; if (willBurn) { IBasisAsset(token).burn(reward); emit RewardSacrificed(token, msg.sender, reward); } else { if (_option == 1) { // Option 1: Immediate Claim with configurable sacrifice. uint256 immediateReward = reward * (10000 - immediateClaimSacrificePercent) / 10000; uint256 sacrifice = reward * immediateClaimSacrificePercent / 10000; IBasisAsset(token).burn(sacrifice); IERC20(token).safeTransfer(msg.sender, immediateReward); emit RewardPaid(token, msg.sender, immediateReward); emit RewardSacrificed(token, msg.sender, sacrifice); } else if (_option == 2) { // Option 2: Vesting Claim. // Retrieve the escrow token for the peg token. address escrowToken = escrowTokens[token]; require(escrowToken != address(0), "Boardroom: escrow token not set"); IERC20(token).approve(escrowToken, reward); IEscrow(escrowToken).startVesting(msg.sender, reward, vestingDuration); IERC20(token).approve(escrowToken, 0); emit VestedRewardRecorded(token, msg.sender, reward, block.timestamp + vestingDuration); } else if (_option == 3) { // Option 3: Direct Claim with Sonic bribe fee. totalSonicFee += getPegTokenPriceInSonic(token) * reward * pegStabilityModuleFee / 1e22; IERC20(token).safeTransfer(msg.sender, reward); emit RewardPaid(token, msg.sender, reward); } else { revert("Boardroom: unsupported claim option"); } } } } if (totalSonicFee > 0) { require(msg.value >= totalSonicFee, "Boardroom: insufficient Sonic for bribe fee"); emit SonicBribed(msg.sender, totalSonicFee); } if (msg.value > totalSonicFee) { uint256 refund = msg.value - totalSonicFee; (bool success, ) = msg.sender.call{value: refund}(""); require(success, "Boardroom: refund failed"); } } /** * @notice Claims vested rewards for a specific peg token. * @param _token The peg token address for which vested rewards are claimed. */ function claimVestedReward(address _token) public nonReentrant { IEscrow _escrowToken = IEscrow(escrowTokens[_token]); if (_escrowToken.availableToClaim(msg.sender) > 0) { _escrowToken.claimFor(msg.sender); } } function claimAllVestedRewards() public { uint256 len = pegTokens.length; for (uint256 i = 0; i < len; ++i) { claimVestedReward(pegTokens[i]); } } /** * @notice Allocates seigniorage rewards for a specific peg token. * Callable by the Treasury contract. * @param _token The peg token address. * @param _amount The amount of reward to allocate. */ function allocateSeignioragePegToken(address _token, uint256 _amount) external override onlyTreasury { require(_amount > 0, "Boardroom: Cannot allocate 0"); uint256 totalStaked = totalSupply(); require(totalStaked > 0, "Boardroom: Cannot allocate when totalSupply is 0"); require(boardroomHistory[_token].length > 0, "Boardroom: No snapshot history for token"); uint256 prevRPS = getLatestSnapshot(_token).rewardPerShare; uint256 nextRPS = prevRPS + _amount * 1e18 / totalStaked; BoardroomSnapshot memory newSnapshot = BoardroomSnapshot({ time: block.number, rewardReceived: _amount, rewardPerShare: nextRPS }); boardroomHistory[_token].push(newSnapshot); IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); emit RewardAdded(_token, msg.sender, _amount); } /** * @notice Collects all native Sonic from the contract, wraps it into wS (Wrapped Sonic), and forwards it to bribesSafe. */ function collectSonic() external { require(address(wrappedSonic) != address(0), "Boardroom: wrappedSonic not set"); uint256 amount = address(this).balance; require(amount > 0, "Boardroom: No Sonic balance to collect"); wrappedSonic.deposit{value: amount}(); IERC20(wrappedSonic).safeTransfer(collateralPool, amount); } /* ========== GOVERNANCE & ADMIN FUNCTIONS ========== */ /** * @notice Allows the owner to recover unsupported tokens (except core tokens). * @param _token The token to recover. * @param _amount The amount to recover. * @param _to The recipient address. */ function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external onlyOwner { uint256 len = pegTokens.length; for (uint256 i = 0; i < len; ++i) { require(address(_token) != pegTokens[i], "Boardroom: reward token"); } _token.safeTransfer(_to, _amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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. * * The initial owner is set to the address provided by the deployer. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IBasisAsset { function mint(address recipient, uint256 amount) external returns (bool); function burn(uint256 amount) external; function burnFrom(address from, uint256 amount) external; function isOperator() external returns (bool); function operator() external view returns (address); function transferOperator(address newOperator_) external; function transferOwnership(address newOwner_) external; function totalBurned() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IBoardroom { function allocateSeignioragePegToken(address _token, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IEpoch { function epoch() external view returns (uint256); function nextEpochPoint() external view returns (uint256); function nextEpochLength() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IEscrow { function vestingSchedule(address _user) external view returns (uint256 totalAmount, uint256 claimedAmount, uint256 startTime, uint256 duration); function totalClaimed(address _user) external view returns (uint256); function availableToClaim(address _user) external view returns (uint256); function fullClaimTime(address _user) external view returns (uint256); function startVesting(address _user, uint256 _amount, uint256 _vestingDuration) external; function claim() external; function claimFor(address _user) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IOracle { function update() external; function consult(address _token, uint256 _amountIn) external view returns (uint144 amountOut); function twap(address _token, uint256 _amountIn) external view returns (uint144 _amountOut); function getPegPrice() external view returns (uint256); function getPegPriceUpdated() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "./IEpoch.sol"; interface ITreasury is IEpoch { function getPegTokenPrice(address _token) external view returns (uint256); function getPegTokenUpdatedPrice(address _token) external view returns (uint256); function getPegTokenLockedBalance(address _token) external view returns (uint256); function getPegTokenCirculatingSupply(address _token) external view returns (uint256); function getPegTokenExpansionRate(address _token) external view returns (uint256); function getPegTokenExpansionAmount(address _token) external view returns (uint256); function previousEpochGreenPrice() external view returns (uint256); function boardroom() external view returns (address); function boardroomSharedPercent() external view returns (uint256); function daoFund() external view returns (address); function daoFundSharedPercent() external view returns (uint256); function collateralPool() external view returns (address); function collateralPoolSharedPercent() external view returns (uint256); function devFund() external view returns (address); function devFundSharedPercent() external view returns (uint256); function isSharePrinter(address account) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; contract ContractGuard { mapping(uint256 => mapping(address => bool)) private _status; function checkSameOriginReentranted() internal view returns (bool) { return _status[block.number][tx.origin]; } function checkSameSenderReentranted() internal view returns (bool) { return _status[block.number][msg.sender]; } modifier onlyOneBlock() { require(!checkSameOriginReentranted(), "ContractGuard: one block, one function"); require(!checkSameSenderReentranted(), "ContractGuard: one block, one function"); _; _status[block.number][tx.origin] = true; _status[block.number][msg.sender] = true; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title ShareWrapper * @dev A lightweight wrapper for staking an ERC20-based "share" token. * Users can stake tokens, which increases the total staked balance, * and can withdraw or claim them later. This contract is meant to be * inherited by a higher-level Boardroom-like contract. */ contract ShareWrapper { using SafeERC20 for IERC20; /// @notice The share token that users stake. IERC20 public share; /// @dev Tracks the total staked supply of the share token. uint256 private _totalStaked; /// @dev Tracks each user's staked balance. mapping(address => uint256) private _stakedBalances; /** * @notice Returns the total staked supply of the share token. */ function totalSupply() public view returns (uint256) { return _totalStaked; } /** * @notice Returns the staked balance of a given account. * @param account The address of the user. */ function balanceOf(address account) public view returns (uint256) { return _stakedBalances[account]; } /** * @notice Allows a user to stake a specified amount of the share token. * The contract adjusts for any potential deflationary token behavior * by measuring the contract's share balance before and after transfer. * @param amount The amount of the share token to stake. */ function stake(uint256 amount) public virtual { uint256 previousBalance = share.balanceOf(address(this)); share.safeTransferFrom(msg.sender, address(this), amount); // Recalculate the actual transferred amount in case of deflationary token mechanics. amount = share.balanceOf(address(this)) - previousBalance; _totalStaked += amount; _stakedBalances[msg.sender] += amount; } /** * @dev Internal function that reduces the caller's staked balance without * transferring tokens back to them. This is intended for "pending withdraw" * logic where the tokens remain in the contract until a finalize step. * @param amount The amount to remove from the caller's staked balance. */ function _withdraw(uint256 amount) internal virtual { uint256 userStakedBalance = _stakedBalances[msg.sender]; require(userStakedBalance >= amount, "ShareWrapper: withdraw request exceeds staked balance"); _totalStaked -= amount; _stakedBalances[msg.sender] = userStakedBalance - amount; } /** * @dev Internal function that restores a user's staked balance after a withdraw * request has been canceled. This effectively re-stakes the tokens for the user. * @param amount The amount to re-stake to the caller's balance. */ function _cancelWithdraw(uint256 amount) internal virtual { _totalStaked += amount; _stakedBalances[msg.sender] += amount; } /** * @dev Internal function that transfers share tokens from the contract * to the caller, finalizing the withdrawal process. * @param amount The amount of share tokens to transfer to the user. */ function _claimPendingWithdraw(uint256 amount) internal virtual { share.safeTransfer(msg.sender, amount); } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CancelPendingWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PendingWithdrawFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockEpoch","type":"uint256"}],"name":"PendingWithdrawRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardSacrificed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SonicBribed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestingEnd","type":"uint256"}],"name":"VestedRewardRecorded","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addPegToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"allocateSeignioragePegToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"boardroomHistory","outputs":[{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"rewardReceived","type":"uint256"},{"internalType":"uint256","name":"rewardPerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"member","type":"address"}],"name":"burningRewardsInfo","outputs":[{"internalType":"bool","name":"_burned","type":"bool"},{"internalType":"uint256","name":"_burningEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"member","type":"address"}],"name":"canClaimReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelPendingWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAllVestedRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_option","type":"uint256"}],"name":"claimRewardWithOption","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimRewardsBurnEpochs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"claimVestedReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectSonic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_member","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_member","type":"address"}],"name":"earnedAll","outputs":[{"internalType":"uint256","name":"_numOfPegTokens","type":"uint256"},{"internalType":"address[]","name":"_pegTokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"_earnedPegTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"epochTimerStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"escrowTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalizeWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_member","type":"address"}],"name":"getLastSnapshotIndexOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPegTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPegTokenPriceInSonic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getSonicFeeForOption3","outputs":[{"internalType":"uint256","name":"totalSonicFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"governanceRecoverUnsupported","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"immediateClaimSacrificePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_green","type":"address"},{"internalType":"address","name":"_blue","type":"address"},{"internalType":"address","name":"_red","type":"address"},{"internalType":"address","name":"_collateralPool","type":"address"},{"internalType":"contract ITreasury","name":"_treasury","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"latestSnapshotIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"members","outputs":[{"internalType":"uint256","name":"lastSnapshotIndex","type":"uint256"},{"internalType":"uint256","name":"rewardEarned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextEpochLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextEpochPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numOfPegTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegStabilityModuleFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pegTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingWithdrawals","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockEpoch","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"requestWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardLockupEpochs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"rewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralPool","type":"address"}],"name":"setCollateralPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pegToken","type":"address"},{"internalType":"address","name":"_escrowToken","type":"address"}],"name":"setEscrowToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percent","type":"uint256"}],"name":"setImmediateClaimSacrificePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_withdrawLockupEpochs","type":"uint256"},{"internalType":"uint256","name":"_rewardLockupEpochs","type":"uint256"},{"internalType":"uint256","name":"_claimRewardsBurnEpochs","type":"uint256"}],"name":"setLockUp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setPegStabilityModuleFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pegToken","type":"address"},{"internalType":"address","name":"_oracle","type":"address"}],"name":"setTokenInSonicOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"setVestingDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IWETH","name":"_wrappedSonic","type":"address"}],"name":"setWSonic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"share","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenInSonicOracles","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"contract ITreasury","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_member","type":"address"}],"name":"vestingSchedule","outputs":[{"internalType":"uint256","name":"_claimable","type":"uint256"},{"internalType":"uint256","name":"_remaining","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_member","type":"address"}],"name":"vestingScheduleAll","outputs":[{"internalType":"uint256","name":"_numOfPegTokens","type":"uint256"},{"internalType":"address[]","name":"_pegTokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"_claimables","type":"uint256[]"},{"internalType":"uint256[]","name":"_remainings","type":"uint256[]"},{"internalType":"uint256[]","name":"_endTimes","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawLockupEpochs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wrappedSonic","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052348015600f57600080fd5b506001600455615dea806100246000396000f3fe60806040526004361061039b5760003560e01c80637b1c85e3116101dc578063bfb4eee911610102578063de072be3116100a0578063f38c9dcf1161006f578063f38c9dcf14610b71578063f3f4370314610b91578063fc93a8d314610bc5578063ff0eccf614610c1857600080fd5b8063de072be314610ad9578063e8c6747914610b1c578063e9fad8ee14610b3c578063f2fde38b14610b5157600080fd5b8063ceccf59a116100dc578063ceccf59a14610a59578063d02b62ff14610a79578063d114048a14610a99578063d63abf3b14610ab957600080fd5b8063bfb4eee914610a02578063c5967c2614610a17578063ce75d56514610a2c57600080fd5b8063a803f4221161017a578063afa23de011610149578063afa23de014610963578063b88a802f14610983578063ba44a45a14610998578063be43e045146109ae57600080fd5b8063a803f422146108dc578063a894a1ee146108ef578063a8d5fd6514610905578063ae32dc9e1461093257600080fd5b8063900cf0cf116101b6578063900cf0cf1461086257806397cb5512146108775780639e88ec101461088d578063a694fc3a146108bc57600080fd5b80637b1c85e3146107e357806383341482146108035780638da5cb5b1461081857600080fd5b80633e85881c116102c157806361d027b31161025f57806370a082311161022e57806370a082311461074b578063715018a61461078e578063745400c9146107a357806379fbd8e0146107c357600080fd5b806361d027b3146106a35780636a599c00146106d05780636b10342a146106f05780636c368e5d1461071057600080fd5b806354575af41161029b57806354575af41461062e578063574c689a1461064e5780635c0dd7761461066e578063605783691461068357600080fd5b80633e85881c1461057957806345105308146105e1578063531e05411461060e57600080fd5b80631514617e116103395780631e85cd65116103085780631e85cd651461050e578063211dc32d146105245780632bf5a7a51461054457806330fcc7371461056457600080fd5b80631514617e146104a3578063157a0896146104b957806318160ddd146104d95780631ba28878146104ee57600080fd5b8063046335d011610375578063046335d01461041e57806307284ce91461044e5780630ffbdcaa146104635780631459457a1461048357600080fd5b8063022ba18d146103a757806302853687146103d0578063031514461461040757600080fd5b366103a257005b600080fd5b3480156103b357600080fd5b506103bd600c5481565b6040519081526020015b60405180910390f35b3480156103dc57600080fd5b506103f06103eb366004615971565b610c45565b6040805192151583526020830191909152016103c7565b34801561041357600080fd5b5061041c610dbc565b005b34801561042a57600080fd5b5061043e610439366004615971565b610f7f565b60405190151581526020016103c7565b34801561045a57600080fd5b506103bd61104e565b34801561046f57600080fd5b5061041c61047e366004615995565b6110e7565b34801561048f57600080fd5b5061041c61049e3660046159ae565b61115e565b3480156104af57600080fd5b506103bd600f5481565b3480156104c557600080fd5b5061041c6104d4366004615a1f565b61163d565b3480156104e557600080fd5b506001546103bd565b3480156104fa57600080fd5b5061041c610509366004615971565b611738565b34801561051a57600080fd5b506103bd600b5481565b34801561053057600080fd5b506103bd61053f366004615a1f565b611804565b34801561055057600080fd5b5061041c61055f366004615971565b6118c5565b34801561057057600080fd5b5061041c611be7565b34801561058557600080fd5b506105bc610594366004615971565b60106020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103c7565b3480156105ed57600080fd5b506103bd6105fc366004615971565b60076020526000908152604090205481565b34801561061a57600080fd5b506103bd610629366004615971565b612033565b34801561063a57600080fd5b5061041c610649366004615a58565b612048565b34801561065a57600080fd5b506105bc610669366004615995565b61212f565b34801561067a57600080fd5b5061041c612166565b34801561068f57600080fd5b5061041c61069e366004615995565b6124b5565b3480156106af57600080fd5b506005546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156106dc57600080fd5b506103bd6106eb366004615971565b612562565b3480156106fc57600080fd5b506103bd61070b366004615971565b6125f7565b34801561071c57600080fd5b5061073061072b366004615a9a565b612629565b604080519384526020840192909252908201526060016103c7565b34801561075757600080fd5b506103bd610766366004615971565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b34801561079a57600080fd5b5061041c61266b565b3480156107af57600080fd5b5061041c6107be366004615995565b61267f565b3480156107cf57600080fd5b5061041c6107de366004615a9a565b612b88565b3480156107ef57600080fd5b506107306107fe366004615a1f565b612ef0565b34801561080f57600080fd5b5061041c613027565b34801561082457600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff166105bc565b34801561086e57600080fd5b506103bd61307e565b34801561088357600080fd5b506103bd600e5481565b34801561089957600080fd5b506108ad6108a8366004615971565b6130ee565b6040516103c793929190615b4a565b3480156108c857600080fd5b5061041c6108d7366004615995565b61326d565b61041c6108ea366004615995565b6136e7565b3480156108fb57600080fd5b506103bd600d5481565b34801561091157600080fd5b506000546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561093e57600080fd5b5061095261094d366004615971565b61389f565b6040516103c7959493929190615b7f565b34801561096f57600080fd5b506103bd61097e366004615971565b613ad3565b34801561098f57600080fd5b5061041c613c1a565b3480156109a457600080fd5b506103bd60145481565b3480156109ba57600080fd5b506109ed6109c9366004615a1f565b60086020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016103c7565b348015610a0e57600080fd5b506006546103bd565b348015610a2357600080fd5b506103bd613d60565b348015610a3857600080fd5b506011546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a6557600080fd5b5061041c610a74366004615bde565b613dd0565b348015610a8557600080fd5b5061041c610a94366004615a1f565b613fbc565b348015610aa557600080fd5b5061041c610ab4366004615971565b614094565b348015610ac557600080fd5b5061041c610ad4366004615971565b6141cf565b348015610ae557600080fd5b506105bc610af4366004615971565b60126020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015610b2857600080fd5b5061041c610b37366004615995565b61429b565b348015610b4857600080fd5b5061041c614314565b348015610b5d57600080fd5b5061041c610b6c366004615971565b61432d565b348015610b7d57600080fd5b506103bd610b8c366004615971565b61438e565b348015610b9d57600080fd5b506109ed610bac366004615971565b600a602052600090815260409020805460019091015482565b348015610bd157600080fd5b506103bd610be0366004615a1f565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832093909416825291909152205490565b348015610c2457600080fd5b506013546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526007602090815260408083205460055482517f900cf0cf000000000000000000000000000000000000000000000000000000008152925194958695929491169263900cf0cf92600480830193928290030181865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec9190615c0a565b600d54610cf99083615c52565b1115925060009150600081118015610da15750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9d9190615c0a565b8111155b15610db657600d54610db39082615c52565b91505b50915091565b60115473ffffffffffffffffffffffffffffffffffffffff16610e40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f426f617264726f6f6d3a2077726170706564536f6e6963206e6f74207365740060448201526064015b60405180910390fd5b4780610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f426f617264726f6f6d3a204e6f20536f6e69632062616c616e636520746f206360448201527f6f6c6c65637400000000000000000000000000000000000000000000000000006064820152608401610e37565b601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610f3857600080fd5b505af1158015610f4c573d6000803e3d6000fd5b5050601354601154610f7c945073ffffffffffffffffffffffffffffffffffffffff908116935016905083614438565b50565b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa158015610fef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110139190615c0a565b600c5473ffffffffffffffffffffffffffffffffffffffff84166000908152600760205260409020546110469190615c52565b111592915050565b600554604080517f07284ce9000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916307284ce99160048083019260209291908290030181865afa1580156110be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e29190615c0a565b905090565b6110ef6144be565b60008111611159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f56657374696e67206475726174696f6e206d757374206265203e2030000000006044820152606401610e37565b600f55565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156111a95750825b905060008267ffffffffffffffff1660011480156111c65750303b155b9050811580156111d4575080155b1561120b576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001178555831561126c5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6112753361454c565b876000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060068a9080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506006899080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600960008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051806060016040528043815260200160008152602001600081525090806001815401808255809150506001900390600052602060002090600302016000909190919091506000820151816000015560208201518160010155604082015181600201555050600960008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060600160405280438152602001600081526020016000815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550506006600b819055506002600c819055506008600d81905550610bb8600e8190555062093a80600f819055506105dc60148190555073039e2fb66102314ce7b64ce5ce3e5183bc94ad38601160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083156116315784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b6116456144be565b73ffffffffffffffffffffffffffffffffffffffff82161580159061167f575073ffffffffffffffffffffffffffffffffffffffff811615155b6116e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c6964206164647265737300000000000000000000000000000000006044820152606401610e37565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260126020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b6117406144be565b73ffffffffffffffffffffffffffffffffffffffff81166117bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420636f6c6c61746572616c20706f6f6c2061646472657373006044820152606401610e37565b601380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806118108461455d565b604001519050600061182285856145fd565b60409081015173ffffffffffffffffffffffffffffffffffffffff8088166000908152600860209081528482209289168252919091529190912060010154909150670de0b6b3a76400006118768385615c65565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600260205260409020546118a69190615c78565b6118b09190615c8f565b6118ba9190615c52565b925050505b92915050565b6118cd6144be565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602052604090205415611980576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f426f617264726f6f6d3a20626f617264726f6f6d486973746f7279206578697360448201527f74730000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f19190615c0a565b11611a58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f426f617264726f6f6d3a20696e76616c696420746f6b656e00000000000000006044820152606401610e37565b60065460005b81811015611b21578273ffffffffffffffffffffffffffffffffffffffff1660068281548110611a9057611a90615cca565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611b19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f426f617264726f6f6d3a206578697374696e6720746f6b656e000000000000006044820152606401610e37565b600101611a5e565b50506006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093168317905560009182526009602090815260408084208151606081018352438152808401868152928101868152825480870184559287529390952094516003909102909401938455519183019190915551600290910155565b43600090815260036020908152604080832032845290915290205460ff1615611c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff1615611d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b611d456146ac565b338015611e2b5760065460005b81811015611e2857600060068281548110611d6f57611d6f615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526008835260408085209289168552918352928190208151808301909252805482526001015491810191909152909150611dd18286611804565b6020820152611ddf826125f7565b815273ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832094881683529381529290208151815591015160019182015501611d52565b50505b336000908152600a602090815260409182902082518084018452815481526001909101548183015260055483517f900cf0cf0000000000000000000000000000000000000000000000000000000081529351919373ffffffffffffffffffffffffffffffffffffffff9091169263900cf0cf926004808401938290030181865afa158015611ebd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee19190615c0a565b81602001511115611f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f426f617264726f6f6d3a207374696c6c20696e207769746864726177206c6f6360448201527f6b757000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b8051336000908152600a6020526040812081815560010155611f95816146ef565b60405181815233907fa7ac0e1b553998810071be4b2c13a205e9b1e9bd8984c4d35f251509f99da7c0906020015b60405180910390a2505050611fd86001600455565b436000908152600360209081526040808320328452909152808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092553384529190922080549091169091179055565b600061203e8261455d565b6040015192915050565b6120506144be565b60065460005b81811015612107576006818154811061207157612071615cca565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff908116908616036120ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f426f617264726f6f6d3a2072657761726420746f6b656e0000000000000000006044820152606401610e37565b600101612056565b5061212973ffffffffffffffffffffffffffffffffffffffff85168385614438565b50505050565b6006818154811061213f57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b43600090815260036020908152604080832032845290915290205460ff1615612211576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff16156122bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b6122c46146ac565b3380156123aa5760065460005b818110156123a7576000600682815481106122ee576122ee615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506123508286611804565b602082015261235e826125f7565b815273ffffffffffffffffffffffffffffffffffffffff9182166000908152600860209081526040808320948816835293815292902081518155910151600191820155016122d1565b50505b336000908152600a6020908152604091829020825180840190935280548084526001909101549183019190915280612464576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f426f617264726f6f6d3a206e6f2070656e64696e67207769746864726177207460448201527f6f2063616e63656c0000000000000000000000000000000000000000000000006064820152608401610e37565b336000908152600a602052604081208181556001015561248381614713565b60405181815233907f830bf94041e3c1419feb5338ff2c7ec25e889b84fd0b759dc780a87eb71ead9b90602001611fc3565b6124bd6144be565b6101f481101580156124d15750610bb88111155b61255d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f426f617264726f6f6d3a20666565206d757374206265206265747765656e203560448201527f2520616e642033302500000000000000000000000000000000000000000000006064820152608401610e37565b601455565b6005546040517f6a599c0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526000921690636a599c0090602401602060405180830381865afa1580156125d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bf9190615c0a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260408120546118bf90600190615c65565b6009602052816000526040600020818154811061264557600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6126736144be565b61267d6000614751565b565b43600090815260036020908152604080832032845290915290205460ff161561272a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff16156127d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b6127dd6146ac565b3360009081526002602052604081205411612879576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f426f617264726f6f6d3a20546865206d656d62657220646f6573206e6f74206560448201527f78697374000000000000000000000000000000000000000000000000000000006064820152608401610e37565b33801561295f5760065460005b8181101561295c576000600682815481106128a3576128a3615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506129058286611804565b6020820152612913826125f7565b815273ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832094881683529381529290208151815591015160019182015501612886565b50505b600082116129c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f426f617264726f6f6d3a2043616e6e6f742077697468647261772030000000006044820152606401610e37565b600b54600554604080517f900cf0cf00000000000000000000000000000000000000000000000000000000815290516000939273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa158015612a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a619190615c0a565b612a6b9190615c52565b336000908152600a602090815260409182902082518084019093528054808452600190910154918301919091529192509084908290612aab908390615c52565b9052506020808201838152336000908152600a9092526040909120825181559051600190910155612adb846147e7565b612ae484614a7f565b604080518581526020810184905233917ff4f76e43e2bb436aa044acf35b93bd185af6ebf3033a404043197d4f9d397a67910160405180910390a2505050612b2c6001600455565b50436000908152600360209081526040808320328452909152808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092553384529190922080549091169091179055565b60055473ffffffffffffffffffffffffffffffffffffffff163314612c2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f426f617264726f6f6d3a2063616c6c6572206973206e6f74207468652074726560448201527f61737572790000000000000000000000000000000000000000000000000000006064820152608401610e37565b60008111612c99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f426f617264726f6f6d3a2043616e6e6f7420616c6c6f636174652030000000006044820152606401610e37565b6000612ca460015490565b905060008111612d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f426f617264726f6f6d3a2043616e6e6f7420616c6c6f63617465207768656e2060448201527f746f74616c537570706c792069732030000000000000000000000000000000006064820152608401610e37565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020526040902054612de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f426f617264726f6f6d3a204e6f20736e617073686f7420686973746f7279206660448201527f6f7220746f6b656e0000000000000000000000000000000000000000000000006064820152608401610e37565b6000612df38461455d565b604001519050600082612e0e85670de0b6b3a7640000615c78565b612e189190615c8f565b612e229083615c52565b60408051606081018252438152602080820188815282840185815273ffffffffffffffffffffffffffffffffffffffff8b166000818152600985529586208054600181810183559188529490962085516003909502019384559151948301949094559251600290910155919250612e9b90333088614b55565b604051858152339073ffffffffffffffffffffffffffffffffffffffff8816907f0f7cde3c0518e1cc590491be5861d70a2e333f7e65af2e1ebd91a3c9a3cc638d9060200160405180910390a3505050505050565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601060205260408082205490517fffff6b0400000000000000000000000000000000000000000000000000000000815284841660048201529192839283928392839283928392169063ffff6b0490602401608060405180830381865afa158015612f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9f9190615cf9565b9350935093509350600081111561301c57612fba8183615c52565b94506000854211612fd457612fcf8342615c65565b612fd6565b815b9050600082612fe58388615c78565b612fef9190615c8f565b905084811115613008576130038582615c65565b61300b565b60005b98506130178187615c65565b975050505b505050509250925092565b60065460005b8181101561307a576130726006828154811061304b5761304b615cca565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16614094565b60010161302d565b5050565b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa1580156110be573d6000803e3d6000fd5b60006060806130fc60065490565b92508267ffffffffffffffff81111561311757613117615d2f565b604051908082528060200260200182016040528015613140578160200160208202803683370190505b5091508267ffffffffffffffff81111561315c5761315c615d2f565b604051908082528060200260200182016040528015613185578160200160208202803683370190505b50905060005b8381101561326557600681815481106131a6576131a6615cca565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168382815181106131e3576131e3615cca565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061324083828151811061323257613232615cca565b602002602001015186611804565b82828151811061325257613252615cca565b602090810291909101015260010161318b565b509193909250565b43600090815260036020908152604080832032845290915290205460ff1615613318576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff16156133c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b6133cb6146ac565b3380156134b15760065460005b818110156134ae576000600682815481106133f5576133f5615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506134578286611804565b6020820152613465826125f7565b815273ffffffffffffffffffffffffffffffffffffffff9182166000908152600860209081526040808320948816835293815292902081518155910151600191820155016133d8565b50505b6000821161351b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f426f617264726f6f6d3a2043616e6e6f74207374616b652030000000000000006044820152606401610e37565b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa15801561358b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135af9190615c0a565b9050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561361e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136429190615c0a565b600d543360009081526007602052604090205461365f9190615c52565b116136735761366e6000614b9b565b613686565b3360009081526007602052604090208190555b61368f836156a4565b3360008181526007602052604090819020839055517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906136d39086815260200190565b60405180910390a25050612b2c6001600455565b80600314806136f4575034155b61375a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79206f7074696f6e20332069732070617961626c6500000000000000006044820152606401610e37565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137eb9190615c0a565b600c54336000908152600760205260409020546138089190615c52565b1115613896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f426f617264726f6f6d3a207374696c6c20696e20726577617264206c6f636b7560448201527f70000000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b610f7c81614b9b565b60006060806060806138b060065490565b94508467ffffffffffffffff8111156138cb576138cb615d2f565b6040519080825280602002602001820160405280156138f4578160200160208202803683370190505b5093508467ffffffffffffffff81111561391057613910615d2f565b604051908082528060200260200182016040528015613939578160200160208202803683370190505b5092508467ffffffffffffffff81111561395557613955615d2f565b60405190808252806020026020018201604052801561397e578160200160208202803683370190505b5091508467ffffffffffffffff81111561399a5761399a615d2f565b6040519080825280602002602001820160405280156139c3578160200160208202803683370190505b50905060005b85811015613ac9576000600682815481106139e6576139e6615cca565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080868381518110613a2657613a26615cca565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613a6a8189612ef0565b878581518110613a7c57613a7c615cca565b60200260200101878681518110613a9557613a95615cca565b60200260200101878781518110613aae57613aae615cca565b602090810291909101019290925291905252506001016139c9565b5091939590929450565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152601260205260408082205490517f6808a1280000000000000000000000000000000000000000000000000000000081526004810193909352670de0b6b3a7640000602484015290921690636808a12890604401602060405180830381865afa925050508015613b9a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613b9791810190615d5e565b60015b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f426f617264726f6f6d3a206f7261636c65206661696c656400000000000000006044820152606401610e37565b71ffffffffffffffffffffffffffffffffffff1692915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cab9190615c0a565b600c5433600090815260076020526040902054613cc89190615c52565b1115613d56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f426f617264726f6f6d3a207374696c6c20696e20726577617264206c6f636b7560448201527f70000000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b61267d6001614b9b565b600554604080517fc5967c26000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c5967c269160048083019260209291908290030181865afa1580156110be573d6000803e3d6000fd5b613dd86144be565b60158211158015613dea575060158311155b8015613df7575060158111155b613e83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f6c6f636b757045706f6368732063616e6e6f742065786365656420312077656560448201527f6b000000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b80613e8f836002615c52565b1115613f1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4e6565642077696e646f7720666f72207573657220746f20636c61696d20626560448201527f666f7265206275726e696e6720726577617264730000000000000000000000006064820152608401610e37565b6006811015613fae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4174206c6561737420322064617973206265666f72652072657761726473206160448201527f7265206275726e740000000000000000000000000000000000000000000000006064820152608401610e37565b600b92909255600c55600d55565b613fc46144be565b73ffffffffffffffffffffffffffffffffffffffff8116614041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610e37565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260106020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b61409c6146ac565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152601060205260408082205490517f0da451880000000000000000000000000000000000000000000000000000000081523360048201529216918290630da4518890602401602060405180830381865afa15801561411a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061413e9190615c0a565b11156141c4576040517fddeae03300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff82169063ddeae03390602401600060405180830381600087803b1580156141ab57600080fd5b505af11580156141bf573d6000803e3d6000fd5b505050505b50610f7c6001600455565b6141d76144be565b73ffffffffffffffffffffffffffffffffffffffff8116614254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c6964205772617070656420536f6e696320616464726573730000006044820152606401610e37565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6142a36144be565b61271081111561430f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c69642070657263656e7461676500000000000000000000000000006044820152606401610e37565b600e55565b3360009081526002602052604090205461267d9061267f565b6143356144be565b73ffffffffffffffffffffffffffffffffffffffff8116614385576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610e37565b610f7c81614751565b600654600090815b81811015614431576000600682815481106143b3576143b3615cca565b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff1691506143e08287611804565b905069021e19e0c9bab2400000601454826143fa85613ad3565b6144049190615c78565b61440e9190615c78565b6144189190615c8f565b6144229086615c52565b94505050806001019050614396565b5050919050565b60405173ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390526144b991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061583c565b505050565b336144fd7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461267d576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610e37565b6145546158e0565b610f7c81615947565b61458160405180606001604052806000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff821660009081526009602052604090206145af836125f7565b815481106145bf576145bf615cca565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509050919050565b61462160405180606001604052806000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600960209081526040808320600883528184209487168452939091529020548154811061466d5761466d615cca565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b6002600454036146e8576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600455565b600054610f7c9073ffffffffffffffffffffffffffffffffffffffff163383614438565b80600160008282546147259190615c52565b90915550503360009081526002602052604081208054839290614749908490615c52565b909155505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b3380156148cd5760065460005b818110156148ca5760006006828154811061481157614811615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506148738286611804565b6020820152614881826125f7565b815273ffffffffffffffffffffffffffffffffffffffff9182166000908152600860209081526040808320948816835293815292902081518155910151600191820155016147f4565b50505b60065460005b81811015612129576000600682815481106148f0576148f0615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083526008825260408084203385529092529120600101549091508015614a75573360009081526002602052604081205461494f8884615c78565b6149599190615c8f565b73ffffffffffffffffffffffffffffffffffffffff841660009081526008602090815260408083203384529091528120600101805492935083929091906149a1908490615c65565b90915550506040517f42966c680000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8416906342966c6890602401600060405180830381600087803b158015614a0e57600080fd5b505af1158015614a22573d6000803e3d6000fd5b505060405183815233925073ffffffffffffffffffffffffffffffffffffffff861691507f9c283dd95e385befdece653d1614dd1436f12871baa12799d9b460a8e0729d719060200160405180910390a3505b50506001016148d3565b3360009081526002602052604090205481811015614b1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f5368617265577261707065723a2077697468647261772072657175657374206560448201527f786365656473207374616b65642062616c616e636500000000000000000000006064820152608401610e37565b8160016000828254614b319190615c65565b90915550614b4190508282615c65565b336000908152600260205260409020555050565b60405173ffffffffffffffffffffffffffffffffffffffff84811660248301528381166044830152606482018390526121299186918216906323b872dd90608401614472565b338015614c815760065460005b81811015614c7e57600060068281548110614bc557614bc5615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526008835260408085209289168552918352928190208151808301909252805482526001015491810191909152909150614c278286611804565b6020820152614c35826125f7565b815273ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832094881683529381529290208151815591015160019182015501614ba8565b50505b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa158015614cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d159190615c0a565b600d5433600090815260076020526040902054614d329190615c52565b11159050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614da3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dc79190615c0a565b3360009081526007602052604081209190915560065490805b8281101561550457600060068281548110614dfd57614dfd615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff1680835260088252604080842033855290925291206001015490915080156154fa5773ffffffffffffffffffffffffffffffffffffffff821660009081526008602090815260408083203384529091528120600101558515614f4f576040517f42966c680000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8316906342966c6890602401600060405180830381600087803b158015614ee457600080fd5b505af1158015614ef8573d6000803e3d6000fd5b505060405183815233925073ffffffffffffffffffffffffffffffffffffffff851691507f9c283dd95e385befdece653d1614dd1436f12871baa12799d9b460a8e0729d71906020015b60405180910390a36154fa565b876001036150e5576000612710600e54612710614f6c9190615c65565b614f769084615c78565b614f809190615c8f565b90506000612710600e5484614f959190615c78565b614f9f9190615c8f565b6040517f42966c680000000000000000000000000000000000000000000000000000000081526004810182905290915073ffffffffffffffffffffffffffffffffffffffff8516906342966c6890602401600060405180830381600087803b15801561500a57600080fd5b505af115801561501e573d6000803e3d6000fd5b506150449250505073ffffffffffffffffffffffffffffffffffffffff85163384614438565b604051828152339073ffffffffffffffffffffffffffffffffffffffff8616907f540798df468d7b23d11f156fdb954cb19ad414d150722a7b6d55ba369dea792e9060200160405180910390a3604051818152339073ffffffffffffffffffffffffffffffffffffffff8616907f9c283dd95e385befdece653d1614dd1436f12871baa12799d9b460a8e0729d719060200160405180910390a350506154fa565b876002036153bd5773ffffffffffffffffffffffffffffffffffffffff808316600090815260106020526040902054168061517c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f426f617264726f6f6d3a20657363726f7720746f6b656e206e6f7420736574006044820152606401610e37565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526024820184905284169063095ea7b3906044016020604051808303816000875af11580156151f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152159190615d92565b50600f546040517f9cbb49c500000000000000000000000000000000000000000000000000000000815233600482015260248101849052604481019190915273ffffffffffffffffffffffffffffffffffffffff821690639cbb49c590606401600060405180830381600087803b15801561528f57600080fd5b505af11580156152a3573d6000803e3d6000fd5b50506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152600060248301528616925063095ea7b391506044016020604051808303816000875af115801561531c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153409190615d92565b503373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f9bec8e4151fb07c0ab2da36c80aa0fa271bfcbe4cef0666451b6ec263cfc40e484600f544261539f9190615c52565b6040805192835260208301919091520160405180910390a3506154fa565b876003036154725769021e19e0c9bab2400000601454826153dd85613ad3565b6153e79190615c78565b6153f19190615c78565b6153fb9190615c8f565b6154059085615c52565b935061542873ffffffffffffffffffffffffffffffffffffffff83163383614438565b604051818152339073ffffffffffffffffffffffffffffffffffffffff8416907f540798df468d7b23d11f156fdb954cb19ad414d150722a7b6d55ba369dea792e90602001614f42565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f426f617264726f6f6d3a20756e737570706f7274656420636c61696d206f707460448201527f696f6e00000000000000000000000000000000000000000000000000000000006064820152608401610e37565b5050600101614de0565b5080156155d1578034101561559b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f426f617264726f6f6d3a20696e73756666696369656e7420536f6e696320666f60448201527f72206272696265206665650000000000000000000000000000000000000000006064820152608401610e37565b60405181815233907fddc489be4a820da49f4d7541cad7f27d908be13530f8f3ff2ce97a8f75137edf9060200160405180910390a25b8034111561569d5760006155e58234615c65565b604051909150600090339083908381818185875af1925050503d806000811461562a576040519150601f19603f3d011682016040523d82523d6000602084013e61562f565b606091505b505090508061569a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f426f617264726f6f6d3a20726566756e64206661696c656400000000000000006044820152606401610e37565b50505b5050505050565b600080546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015615713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906157379190615c0a565b60005490915061575f9073ffffffffffffffffffffffffffffffffffffffff16333085614b55565b6000546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156157cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906157f19190615c0a565b6157fb9190615c65565b9150816001600082825461580f9190615c52565b90915550503360009081526002602052604081208054849290615833908490615c52565b90915550505050565b600080602060008451602086016000885af18061585f576040513d6000823e3d81fd5b50506000513d91508115615877578060011415615891565b73ffffffffffffffffffffffffffffffffffffffff84163b155b15612129576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610e37565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661267d576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143356158e0565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b60006020828403121561598357600080fd5b813561598e8161594f565b9392505050565b6000602082840312156159a757600080fd5b5035919050565b600080600080600060a086880312156159c657600080fd5b85356159d18161594f565b945060208601356159e18161594f565b935060408601356159f18161594f565b92506060860135615a018161594f565b91506080860135615a118161594f565b809150509295509295909350565b60008060408385031215615a3257600080fd5b8235615a3d8161594f565b91506020830135615a4d8161594f565b809150509250929050565b600080600060608486031215615a6d57600080fd5b8335615a788161594f565b9250602084013591506040840135615a8f8161594f565b809150509250925092565b60008060408385031215615aad57600080fd5b8235615ab88161594f565b946020939093013593505050565b600081518084526020840193506020830160005b82811015615b0e57815173ffffffffffffffffffffffffffffffffffffffff16865260209586019590910190600101615ada565b5093949350505050565b600081518084526020840193506020830160005b82811015615b0e578151865260209586019590910190600101615b2c565b838152606060208201526000615b636060830185615ac6565b8281036040840152615b758185615b18565b9695505050505050565b85815260a060208201526000615b9860a0830187615ac6565b8281036040840152615baa8187615b18565b90508281036060840152615bbe8186615b18565b90508281036080840152615bd28185615b18565b98975050505050505050565b600080600060608486031215615bf357600080fd5b505081359360208301359350604090920135919050565b600060208284031215615c1c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156118bf576118bf615c23565b818103818111156118bf576118bf615c23565b80820281158282048414176118bf576118bf615c23565b600082615cc5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060008060808587031215615d0f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215615d7057600080fd5b815171ffffffffffffffffffffffffffffffffffff8116811461598e57600080fd5b600060208284031215615da457600080fd5b8151801515811461598e57600080fdfea26469706673582212204dc0283f2f8d744e2dfbf163335ddb1f37b0f5bf43ce53316a1917c343ba82c364736f6c634300081c0033
Deployed Bytecode
0x60806040526004361061039b5760003560e01c80637b1c85e3116101dc578063bfb4eee911610102578063de072be3116100a0578063f38c9dcf1161006f578063f38c9dcf14610b71578063f3f4370314610b91578063fc93a8d314610bc5578063ff0eccf614610c1857600080fd5b8063de072be314610ad9578063e8c6747914610b1c578063e9fad8ee14610b3c578063f2fde38b14610b5157600080fd5b8063ceccf59a116100dc578063ceccf59a14610a59578063d02b62ff14610a79578063d114048a14610a99578063d63abf3b14610ab957600080fd5b8063bfb4eee914610a02578063c5967c2614610a17578063ce75d56514610a2c57600080fd5b8063a803f4221161017a578063afa23de011610149578063afa23de014610963578063b88a802f14610983578063ba44a45a14610998578063be43e045146109ae57600080fd5b8063a803f422146108dc578063a894a1ee146108ef578063a8d5fd6514610905578063ae32dc9e1461093257600080fd5b8063900cf0cf116101b6578063900cf0cf1461086257806397cb5512146108775780639e88ec101461088d578063a694fc3a146108bc57600080fd5b80637b1c85e3146107e357806383341482146108035780638da5cb5b1461081857600080fd5b80633e85881c116102c157806361d027b31161025f57806370a082311161022e57806370a082311461074b578063715018a61461078e578063745400c9146107a357806379fbd8e0146107c357600080fd5b806361d027b3146106a35780636a599c00146106d05780636b10342a146106f05780636c368e5d1461071057600080fd5b806354575af41161029b57806354575af41461062e578063574c689a1461064e5780635c0dd7761461066e578063605783691461068357600080fd5b80633e85881c1461057957806345105308146105e1578063531e05411461060e57600080fd5b80631514617e116103395780631e85cd65116103085780631e85cd651461050e578063211dc32d146105245780632bf5a7a51461054457806330fcc7371461056457600080fd5b80631514617e146104a3578063157a0896146104b957806318160ddd146104d95780631ba28878146104ee57600080fd5b8063046335d011610375578063046335d01461041e57806307284ce91461044e5780630ffbdcaa146104635780631459457a1461048357600080fd5b8063022ba18d146103a757806302853687146103d0578063031514461461040757600080fd5b366103a257005b600080fd5b3480156103b357600080fd5b506103bd600c5481565b6040519081526020015b60405180910390f35b3480156103dc57600080fd5b506103f06103eb366004615971565b610c45565b6040805192151583526020830191909152016103c7565b34801561041357600080fd5b5061041c610dbc565b005b34801561042a57600080fd5b5061043e610439366004615971565b610f7f565b60405190151581526020016103c7565b34801561045a57600080fd5b506103bd61104e565b34801561046f57600080fd5b5061041c61047e366004615995565b6110e7565b34801561048f57600080fd5b5061041c61049e3660046159ae565b61115e565b3480156104af57600080fd5b506103bd600f5481565b3480156104c557600080fd5b5061041c6104d4366004615a1f565b61163d565b3480156104e557600080fd5b506001546103bd565b3480156104fa57600080fd5b5061041c610509366004615971565b611738565b34801561051a57600080fd5b506103bd600b5481565b34801561053057600080fd5b506103bd61053f366004615a1f565b611804565b34801561055057600080fd5b5061041c61055f366004615971565b6118c5565b34801561057057600080fd5b5061041c611be7565b34801561058557600080fd5b506105bc610594366004615971565b60106020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103c7565b3480156105ed57600080fd5b506103bd6105fc366004615971565b60076020526000908152604090205481565b34801561061a57600080fd5b506103bd610629366004615971565b612033565b34801561063a57600080fd5b5061041c610649366004615a58565b612048565b34801561065a57600080fd5b506105bc610669366004615995565b61212f565b34801561067a57600080fd5b5061041c612166565b34801561068f57600080fd5b5061041c61069e366004615995565b6124b5565b3480156106af57600080fd5b506005546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156106dc57600080fd5b506103bd6106eb366004615971565b612562565b3480156106fc57600080fd5b506103bd61070b366004615971565b6125f7565b34801561071c57600080fd5b5061073061072b366004615a9a565b612629565b604080519384526020840192909252908201526060016103c7565b34801561075757600080fd5b506103bd610766366004615971565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b34801561079a57600080fd5b5061041c61266b565b3480156107af57600080fd5b5061041c6107be366004615995565b61267f565b3480156107cf57600080fd5b5061041c6107de366004615a9a565b612b88565b3480156107ef57600080fd5b506107306107fe366004615a1f565b612ef0565b34801561080f57600080fd5b5061041c613027565b34801561082457600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff166105bc565b34801561086e57600080fd5b506103bd61307e565b34801561088357600080fd5b506103bd600e5481565b34801561089957600080fd5b506108ad6108a8366004615971565b6130ee565b6040516103c793929190615b4a565b3480156108c857600080fd5b5061041c6108d7366004615995565b61326d565b61041c6108ea366004615995565b6136e7565b3480156108fb57600080fd5b506103bd600d5481565b34801561091157600080fd5b506000546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561093e57600080fd5b5061095261094d366004615971565b61389f565b6040516103c7959493929190615b7f565b34801561096f57600080fd5b506103bd61097e366004615971565b613ad3565b34801561098f57600080fd5b5061041c613c1a565b3480156109a457600080fd5b506103bd60145481565b3480156109ba57600080fd5b506109ed6109c9366004615a1f565b60086020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016103c7565b348015610a0e57600080fd5b506006546103bd565b348015610a2357600080fd5b506103bd613d60565b348015610a3857600080fd5b506011546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610a6557600080fd5b5061041c610a74366004615bde565b613dd0565b348015610a8557600080fd5b5061041c610a94366004615a1f565b613fbc565b348015610aa557600080fd5b5061041c610ab4366004615971565b614094565b348015610ac557600080fd5b5061041c610ad4366004615971565b6141cf565b348015610ae557600080fd5b506105bc610af4366004615971565b60126020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015610b2857600080fd5b5061041c610b37366004615995565b61429b565b348015610b4857600080fd5b5061041c614314565b348015610b5d57600080fd5b5061041c610b6c366004615971565b61432d565b348015610b7d57600080fd5b506103bd610b8c366004615971565b61438e565b348015610b9d57600080fd5b506109ed610bac366004615971565b600a602052600090815260409020805460019091015482565b348015610bd157600080fd5b506103bd610be0366004615a1f565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832093909416825291909152205490565b348015610c2457600080fd5b506013546105bc9073ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526007602090815260408083205460055482517f900cf0cf000000000000000000000000000000000000000000000000000000008152925194958695929491169263900cf0cf92600480830193928290030181865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec9190615c0a565b600d54610cf99083615c52565b1115925060009150600081118015610da15750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9d9190615c0a565b8111155b15610db657600d54610db39082615c52565b91505b50915091565b60115473ffffffffffffffffffffffffffffffffffffffff16610e40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f426f617264726f6f6d3a2077726170706564536f6e6963206e6f74207365740060448201526064015b60405180910390fd5b4780610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f426f617264726f6f6d3a204e6f20536f6e69632062616c616e636520746f206360448201527f6f6c6c65637400000000000000000000000000000000000000000000000000006064820152608401610e37565b601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610f3857600080fd5b505af1158015610f4c573d6000803e3d6000fd5b5050601354601154610f7c945073ffffffffffffffffffffffffffffffffffffffff908116935016905083614438565b50565b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa158015610fef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110139190615c0a565b600c5473ffffffffffffffffffffffffffffffffffffffff84166000908152600760205260409020546110469190615c52565b111592915050565b600554604080517f07284ce9000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916307284ce99160048083019260209291908290030181865afa1580156110be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e29190615c0a565b905090565b6110ef6144be565b60008111611159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f56657374696e67206475726174696f6e206d757374206265203e2030000000006044820152606401610e37565b600f55565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156111a95750825b905060008267ffffffffffffffff1660011480156111c65750303b155b9050811580156111d4575080155b1561120b576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001178555831561126c5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b6112753361454c565b876000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060068a9080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506006899080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600960008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020604051806060016040528043815260200160008152602001600081525090806001815401808255809150506001900390600052602060002090600302016000909190919091506000820151816000015560208201518160010155604082015181600201555050600960008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060600160405280438152602001600081526020016000815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550506006600b819055506002600c819055506008600d81905550610bb8600e8190555062093a80600f819055506105dc60148190555073039e2fb66102314ce7b64ce5ce3e5183bc94ad38601160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083156116315784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b6116456144be565b73ffffffffffffffffffffffffffffffffffffffff82161580159061167f575073ffffffffffffffffffffffffffffffffffffffff811615155b6116e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c6964206164647265737300000000000000000000000000000000006044820152606401610e37565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260126020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b6117406144be565b73ffffffffffffffffffffffffffffffffffffffff81166117bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420636f6c6c61746572616c20706f6f6c2061646472657373006044820152606401610e37565b601380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806118108461455d565b604001519050600061182285856145fd565b60409081015173ffffffffffffffffffffffffffffffffffffffff8088166000908152600860209081528482209289168252919091529190912060010154909150670de0b6b3a76400006118768385615c65565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600260205260409020546118a69190615c78565b6118b09190615c8f565b6118ba9190615c52565b925050505b92915050565b6118cd6144be565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602052604090205415611980576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f426f617264726f6f6d3a20626f617264726f6f6d486973746f7279206578697360448201527f74730000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f19190615c0a565b11611a58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f426f617264726f6f6d3a20696e76616c696420746f6b656e00000000000000006044820152606401610e37565b60065460005b81811015611b21578273ffffffffffffffffffffffffffffffffffffffff1660068281548110611a9057611a90615cca565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1603611b19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f426f617264726f6f6d3a206578697374696e6720746f6b656e000000000000006044820152606401610e37565b600101611a5e565b50506006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093168317905560009182526009602090815260408084208151606081018352438152808401868152928101868152825480870184559287529390952094516003909102909401938455519183019190915551600290910155565b43600090815260036020908152604080832032845290915290205460ff1615611c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff1615611d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b611d456146ac565b338015611e2b5760065460005b81811015611e2857600060068281548110611d6f57611d6f615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526008835260408085209289168552918352928190208151808301909252805482526001015491810191909152909150611dd18286611804565b6020820152611ddf826125f7565b815273ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832094881683529381529290208151815591015160019182015501611d52565b50505b336000908152600a602090815260409182902082518084018452815481526001909101548183015260055483517f900cf0cf0000000000000000000000000000000000000000000000000000000081529351919373ffffffffffffffffffffffffffffffffffffffff9091169263900cf0cf926004808401938290030181865afa158015611ebd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee19190615c0a565b81602001511115611f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f426f617264726f6f6d3a207374696c6c20696e207769746864726177206c6f6360448201527f6b757000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b8051336000908152600a6020526040812081815560010155611f95816146ef565b60405181815233907fa7ac0e1b553998810071be4b2c13a205e9b1e9bd8984c4d35f251509f99da7c0906020015b60405180910390a2505050611fd86001600455565b436000908152600360209081526040808320328452909152808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092553384529190922080549091169091179055565b600061203e8261455d565b6040015192915050565b6120506144be565b60065460005b81811015612107576006818154811061207157612071615cca565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff908116908616036120ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f426f617264726f6f6d3a2072657761726420746f6b656e0000000000000000006044820152606401610e37565b600101612056565b5061212973ffffffffffffffffffffffffffffffffffffffff85168385614438565b50505050565b6006818154811061213f57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b43600090815260036020908152604080832032845290915290205460ff1615612211576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff16156122bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b6122c46146ac565b3380156123aa5760065460005b818110156123a7576000600682815481106122ee576122ee615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506123508286611804565b602082015261235e826125f7565b815273ffffffffffffffffffffffffffffffffffffffff9182166000908152600860209081526040808320948816835293815292902081518155910151600191820155016122d1565b50505b336000908152600a6020908152604091829020825180840190935280548084526001909101549183019190915280612464576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f426f617264726f6f6d3a206e6f2070656e64696e67207769746864726177207460448201527f6f2063616e63656c0000000000000000000000000000000000000000000000006064820152608401610e37565b336000908152600a602052604081208181556001015561248381614713565b60405181815233907f830bf94041e3c1419feb5338ff2c7ec25e889b84fd0b759dc780a87eb71ead9b90602001611fc3565b6124bd6144be565b6101f481101580156124d15750610bb88111155b61255d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f426f617264726f6f6d3a20666565206d757374206265206265747765656e203560448201527f2520616e642033302500000000000000000000000000000000000000000000006064820152608401610e37565b601455565b6005546040517f6a599c0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526000921690636a599c0090602401602060405180830381865afa1580156125d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bf9190615c0a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600960205260408120546118bf90600190615c65565b6009602052816000526040600020818154811061264557600080fd5b600091825260209091206003909102018054600182015460029092015490935090915083565b6126736144be565b61267d6000614751565b565b43600090815260036020908152604080832032845290915290205460ff161561272a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff16156127d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b6127dd6146ac565b3360009081526002602052604081205411612879576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f426f617264726f6f6d3a20546865206d656d62657220646f6573206e6f74206560448201527f78697374000000000000000000000000000000000000000000000000000000006064820152608401610e37565b33801561295f5760065460005b8181101561295c576000600682815481106128a3576128a3615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506129058286611804565b6020820152612913826125f7565b815273ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832094881683529381529290208151815591015160019182015501612886565b50505b600082116129c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f426f617264726f6f6d3a2043616e6e6f742077697468647261772030000000006044820152606401610e37565b600b54600554604080517f900cf0cf00000000000000000000000000000000000000000000000000000000815290516000939273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa158015612a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a619190615c0a565b612a6b9190615c52565b336000908152600a602090815260409182902082518084019093528054808452600190910154918301919091529192509084908290612aab908390615c52565b9052506020808201838152336000908152600a9092526040909120825181559051600190910155612adb846147e7565b612ae484614a7f565b604080518581526020810184905233917ff4f76e43e2bb436aa044acf35b93bd185af6ebf3033a404043197d4f9d397a67910160405180910390a2505050612b2c6001600455565b50436000908152600360209081526040808320328452909152808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091821681179092553384529190922080549091169091179055565b60055473ffffffffffffffffffffffffffffffffffffffff163314612c2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f426f617264726f6f6d3a2063616c6c6572206973206e6f74207468652074726560448201527f61737572790000000000000000000000000000000000000000000000000000006064820152608401610e37565b60008111612c99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f426f617264726f6f6d3a2043616e6e6f7420616c6c6f636174652030000000006044820152606401610e37565b6000612ca460015490565b905060008111612d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f426f617264726f6f6d3a2043616e6e6f7420616c6c6f63617465207768656e2060448201527f746f74616c537570706c792069732030000000000000000000000000000000006064820152608401610e37565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020526040902054612de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f426f617264726f6f6d3a204e6f20736e617073686f7420686973746f7279206660448201527f6f7220746f6b656e0000000000000000000000000000000000000000000000006064820152608401610e37565b6000612df38461455d565b604001519050600082612e0e85670de0b6b3a7640000615c78565b612e189190615c8f565b612e229083615c52565b60408051606081018252438152602080820188815282840185815273ffffffffffffffffffffffffffffffffffffffff8b166000818152600985529586208054600181810183559188529490962085516003909502019384559151948301949094559251600290910155919250612e9b90333088614b55565b604051858152339073ffffffffffffffffffffffffffffffffffffffff8816907f0f7cde3c0518e1cc590491be5861d70a2e333f7e65af2e1ebd91a3c9a3cc638d9060200160405180910390a3505050505050565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601060205260408082205490517fffff6b0400000000000000000000000000000000000000000000000000000000815284841660048201529192839283928392839283928392169063ffff6b0490602401608060405180830381865afa158015612f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9f9190615cf9565b9350935093509350600081111561301c57612fba8183615c52565b94506000854211612fd457612fcf8342615c65565b612fd6565b815b9050600082612fe58388615c78565b612fef9190615c8f565b905084811115613008576130038582615c65565b61300b565b60005b98506130178187615c65565b975050505b505050509250925092565b60065460005b8181101561307a576130726006828154811061304b5761304b615cca565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16614094565b60010161302d565b5050565b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa1580156110be573d6000803e3d6000fd5b60006060806130fc60065490565b92508267ffffffffffffffff81111561311757613117615d2f565b604051908082528060200260200182016040528015613140578160200160208202803683370190505b5091508267ffffffffffffffff81111561315c5761315c615d2f565b604051908082528060200260200182016040528015613185578160200160208202803683370190505b50905060005b8381101561326557600681815481106131a6576131a6615cca565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168382815181106131e3576131e3615cca565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061324083828151811061323257613232615cca565b602002602001015186611804565b82828151811061325257613252615cca565b602090810291909101015260010161318b565b509193909250565b43600090815260036020908152604080832032845290915290205460ff1615613318576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b43600090815260036020908152604080832033845290915290205460ff16156133c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610e37565b6133cb6146ac565b3380156134b15760065460005b818110156134ae576000600682815481106133f5576133f5615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506134578286611804565b6020820152613465826125f7565b815273ffffffffffffffffffffffffffffffffffffffff9182166000908152600860209081526040808320948816835293815292902081518155910151600191820155016133d8565b50505b6000821161351b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f426f617264726f6f6d3a2043616e6e6f74207374616b652030000000000000006044820152606401610e37565b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa15801561358b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135af9190615c0a565b9050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561361e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136429190615c0a565b600d543360009081526007602052604090205461365f9190615c52565b116136735761366e6000614b9b565b613686565b3360009081526007602052604090208190555b61368f836156a4565b3360008181526007602052604090819020839055517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d906136d39086815260200190565b60405180910390a25050612b2c6001600455565b80600314806136f4575034155b61375a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f6e6c79206f7074696f6e20332069732070617961626c6500000000000000006044820152606401610e37565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137eb9190615c0a565b600c54336000908152600760205260409020546138089190615c52565b1115613896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f426f617264726f6f6d3a207374696c6c20696e20726577617264206c6f636b7560448201527f70000000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b610f7c81614b9b565b60006060806060806138b060065490565b94508467ffffffffffffffff8111156138cb576138cb615d2f565b6040519080825280602002602001820160405280156138f4578160200160208202803683370190505b5093508467ffffffffffffffff81111561391057613910615d2f565b604051908082528060200260200182016040528015613939578160200160208202803683370190505b5092508467ffffffffffffffff81111561395557613955615d2f565b60405190808252806020026020018201604052801561397e578160200160208202803683370190505b5091508467ffffffffffffffff81111561399a5761399a615d2f565b6040519080825280602002602001820160405280156139c3578160200160208202803683370190505b50905060005b85811015613ac9576000600682815481106139e6576139e6615cca565b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080868381518110613a2657613a26615cca565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613a6a8189612ef0565b878581518110613a7c57613a7c615cca565b60200260200101878681518110613a9557613a95615cca565b60200260200101878781518110613aae57613aae615cca565b602090810291909101019290925291905252506001016139c9565b5091939590929450565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152601260205260408082205490517f6808a1280000000000000000000000000000000000000000000000000000000081526004810193909352670de0b6b3a7640000602484015290921690636808a12890604401602060405180830381865afa925050508015613b9a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613b9791810190615d5e565b60015b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f426f617264726f6f6d3a206f7261636c65206661696c656400000000000000006044820152606401610e37565b71ffffffffffffffffffffffffffffffffffff1692915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cab9190615c0a565b600c5433600090815260076020526040902054613cc89190615c52565b1115613d56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f426f617264726f6f6d3a207374696c6c20696e20726577617264206c6f636b7560448201527f70000000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b61267d6001614b9b565b600554604080517fc5967c26000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c5967c269160048083019260209291908290030181865afa1580156110be573d6000803e3d6000fd5b613dd86144be565b60158211158015613dea575060158311155b8015613df7575060158111155b613e83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f6c6f636b757045706f6368732063616e6e6f742065786365656420312077656560448201527f6b000000000000000000000000000000000000000000000000000000000000006064820152608401610e37565b80613e8f836002615c52565b1115613f1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4e6565642077696e646f7720666f72207573657220746f20636c61696d20626560448201527f666f7265206275726e696e6720726577617264730000000000000000000000006064820152608401610e37565b6006811015613fae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4174206c6561737420322064617973206265666f72652072657761726473206160448201527f7265206275726e740000000000000000000000000000000000000000000000006064820152608401610e37565b600b92909255600c55600d55565b613fc46144be565b73ffffffffffffffffffffffffffffffffffffffff8116614041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610e37565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260106020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b61409c6146ac565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152601060205260408082205490517f0da451880000000000000000000000000000000000000000000000000000000081523360048201529216918290630da4518890602401602060405180830381865afa15801561411a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061413e9190615c0a565b11156141c4576040517fddeae03300000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff82169063ddeae03390602401600060405180830381600087803b1580156141ab57600080fd5b505af11580156141bf573d6000803e3d6000fd5b505050505b50610f7c6001600455565b6141d76144be565b73ffffffffffffffffffffffffffffffffffffffff8116614254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c6964205772617070656420536f6e696320616464726573730000006044820152606401610e37565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6142a36144be565b61271081111561430f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c69642070657263656e7461676500000000000000000000000000006044820152606401610e37565b600e55565b3360009081526002602052604090205461267d9061267f565b6143356144be565b73ffffffffffffffffffffffffffffffffffffffff8116614385576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610e37565b610f7c81614751565b600654600090815b81811015614431576000600682815481106143b3576143b3615cca565b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff1691506143e08287611804565b905069021e19e0c9bab2400000601454826143fa85613ad3565b6144049190615c78565b61440e9190615c78565b6144189190615c8f565b6144229086615c52565b94505050806001019050614396565b5050919050565b60405173ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390526144b991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061583c565b505050565b336144fd7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff161461267d576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610e37565b6145546158e0565b610f7c81615947565b61458160405180606001604052806000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff821660009081526009602052604090206145af836125f7565b815481106145bf576145bf615cca565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509050919050565b61462160405180606001604052806000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600960209081526040808320600883528184209487168452939091529020548154811061466d5761466d615cca565b90600052602060002090600302016040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b6002600454036146e8576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600455565b600054610f7c9073ffffffffffffffffffffffffffffffffffffffff163383614438565b80600160008282546147259190615c52565b90915550503360009081526002602052604081208054839290614749908490615c52565b909155505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b3380156148cd5760065460005b818110156148ca5760006006828154811061481157614811615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff90811680845260088352604080852092891685529183529281902081518083019092528054825260010154918101919091529091506148738286611804565b6020820152614881826125f7565b815273ffffffffffffffffffffffffffffffffffffffff9182166000908152600860209081526040808320948816835293815292902081518155910151600191820155016147f4565b50505b60065460005b81811015612129576000600682815481106148f0576148f0615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168083526008825260408084203385529092529120600101549091508015614a75573360009081526002602052604081205461494f8884615c78565b6149599190615c8f565b73ffffffffffffffffffffffffffffffffffffffff841660009081526008602090815260408083203384529091528120600101805492935083929091906149a1908490615c65565b90915550506040517f42966c680000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8416906342966c6890602401600060405180830381600087803b158015614a0e57600080fd5b505af1158015614a22573d6000803e3d6000fd5b505060405183815233925073ffffffffffffffffffffffffffffffffffffffff861691507f9c283dd95e385befdece653d1614dd1436f12871baa12799d9b460a8e0729d719060200160405180910390a3505b50506001016148d3565b3360009081526002602052604090205481811015614b1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f5368617265577261707065723a2077697468647261772072657175657374206560448201527f786365656473207374616b65642062616c616e636500000000000000000000006064820152608401610e37565b8160016000828254614b319190615c65565b90915550614b4190508282615c65565b336000908152600260205260409020555050565b60405173ffffffffffffffffffffffffffffffffffffffff84811660248301528381166044830152606482018390526121299186918216906323b872dd90608401614472565b338015614c815760065460005b81811015614c7e57600060068281548110614bc557614bc5615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526008835260408085209289168552918352928190208151808301909252805482526001015491810191909152909150614c278286611804565b6020820152614c35826125f7565b815273ffffffffffffffffffffffffffffffffffffffff918216600090815260086020908152604080832094881683529381529290208151815591015160019182015501614ba8565b50505b600554604080517f900cf0cf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163900cf0cf9160048083019260209291908290030181865afa158015614cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d159190615c0a565b600d5433600090815260076020526040902054614d329190615c52565b11159050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614da3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dc79190615c0a565b3360009081526007602052604081209190915560065490805b8281101561550457600060068281548110614dfd57614dfd615cca565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff1680835260088252604080842033855290925291206001015490915080156154fa5773ffffffffffffffffffffffffffffffffffffffff821660009081526008602090815260408083203384529091528120600101558515614f4f576040517f42966c680000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8316906342966c6890602401600060405180830381600087803b158015614ee457600080fd5b505af1158015614ef8573d6000803e3d6000fd5b505060405183815233925073ffffffffffffffffffffffffffffffffffffffff851691507f9c283dd95e385befdece653d1614dd1436f12871baa12799d9b460a8e0729d71906020015b60405180910390a36154fa565b876001036150e5576000612710600e54612710614f6c9190615c65565b614f769084615c78565b614f809190615c8f565b90506000612710600e5484614f959190615c78565b614f9f9190615c8f565b6040517f42966c680000000000000000000000000000000000000000000000000000000081526004810182905290915073ffffffffffffffffffffffffffffffffffffffff8516906342966c6890602401600060405180830381600087803b15801561500a57600080fd5b505af115801561501e573d6000803e3d6000fd5b506150449250505073ffffffffffffffffffffffffffffffffffffffff85163384614438565b604051828152339073ffffffffffffffffffffffffffffffffffffffff8616907f540798df468d7b23d11f156fdb954cb19ad414d150722a7b6d55ba369dea792e9060200160405180910390a3604051818152339073ffffffffffffffffffffffffffffffffffffffff8616907f9c283dd95e385befdece653d1614dd1436f12871baa12799d9b460a8e0729d719060200160405180910390a350506154fa565b876002036153bd5773ffffffffffffffffffffffffffffffffffffffff808316600090815260106020526040902054168061517c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f426f617264726f6f6d3a20657363726f7720746f6b656e206e6f7420736574006044820152606401610e37565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526024820184905284169063095ea7b3906044016020604051808303816000875af11580156151f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152159190615d92565b50600f546040517f9cbb49c500000000000000000000000000000000000000000000000000000000815233600482015260248101849052604481019190915273ffffffffffffffffffffffffffffffffffffffff821690639cbb49c590606401600060405180830381600087803b15801561528f57600080fd5b505af11580156152a3573d6000803e3d6000fd5b50506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152600060248301528616925063095ea7b391506044016020604051808303816000875af115801561531c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153409190615d92565b503373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f9bec8e4151fb07c0ab2da36c80aa0fa271bfcbe4cef0666451b6ec263cfc40e484600f544261539f9190615c52565b6040805192835260208301919091520160405180910390a3506154fa565b876003036154725769021e19e0c9bab2400000601454826153dd85613ad3565b6153e79190615c78565b6153f19190615c78565b6153fb9190615c8f565b6154059085615c52565b935061542873ffffffffffffffffffffffffffffffffffffffff83163383614438565b604051818152339073ffffffffffffffffffffffffffffffffffffffff8416907f540798df468d7b23d11f156fdb954cb19ad414d150722a7b6d55ba369dea792e90602001614f42565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f426f617264726f6f6d3a20756e737570706f7274656420636c61696d206f707460448201527f696f6e00000000000000000000000000000000000000000000000000000000006064820152608401610e37565b5050600101614de0565b5080156155d1578034101561559b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f426f617264726f6f6d3a20696e73756666696369656e7420536f6e696320666f60448201527f72206272696265206665650000000000000000000000000000000000000000006064820152608401610e37565b60405181815233907fddc489be4a820da49f4d7541cad7f27d908be13530f8f3ff2ce97a8f75137edf9060200160405180910390a25b8034111561569d5760006155e58234615c65565b604051909150600090339083908381818185875af1925050503d806000811461562a576040519150601f19603f3d011682016040523d82523d6000602084013e61562f565b606091505b505090508061569a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f426f617264726f6f6d3a20726566756e64206661696c656400000000000000006044820152606401610e37565b50505b5050505050565b600080546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015615713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906157379190615c0a565b60005490915061575f9073ffffffffffffffffffffffffffffffffffffffff16333085614b55565b6000546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156157cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906157f19190615c0a565b6157fb9190615c65565b9150816001600082825461580f9190615c52565b90915550503360009081526002602052604081208054849290615833908490615c52565b90915550505050565b600080602060008451602086016000885af18061585f576040513d6000823e3d81fd5b50506000513d91508115615877578060011415615891565b73ffffffffffffffffffffffffffffffffffffffff84163b155b15612129576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610e37565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661267d576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143356158e0565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b60006020828403121561598357600080fd5b813561598e8161594f565b9392505050565b6000602082840312156159a757600080fd5b5035919050565b600080600080600060a086880312156159c657600080fd5b85356159d18161594f565b945060208601356159e18161594f565b935060408601356159f18161594f565b92506060860135615a018161594f565b91506080860135615a118161594f565b809150509295509295909350565b60008060408385031215615a3257600080fd5b8235615a3d8161594f565b91506020830135615a4d8161594f565b809150509250929050565b600080600060608486031215615a6d57600080fd5b8335615a788161594f565b9250602084013591506040840135615a8f8161594f565b809150509250925092565b60008060408385031215615aad57600080fd5b8235615ab88161594f565b946020939093013593505050565b600081518084526020840193506020830160005b82811015615b0e57815173ffffffffffffffffffffffffffffffffffffffff16865260209586019590910190600101615ada565b5093949350505050565b600081518084526020840193506020830160005b82811015615b0e578151865260209586019590910190600101615b2c565b838152606060208201526000615b636060830185615ac6565b8281036040840152615b758185615b18565b9695505050505050565b85815260a060208201526000615b9860a0830187615ac6565b8281036040840152615baa8187615b18565b90508281036060840152615bbe8186615b18565b90508281036080840152615bd28185615b18565b98975050505050505050565b600080600060608486031215615bf357600080fd5b505081359360208301359350604090920135919050565b600060208284031215615c1c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156118bf576118bf615c23565b818103818111156118bf576118bf615c23565b80820281158282048414176118bf576118bf615c23565b600082615cc5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060008060808587031215615d0f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215615d7057600080fd5b815171ffffffffffffffffffffffffffffffffffff8116811461598e57600080fd5b600060208284031215615da457600080fd5b8151801515811461598e57600080fdfea26469706673582212204dc0283f2f8d744e2dfbf163335ddb1f37b0f5bf43ce53316a1917c343ba82c364736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.