Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 12 from a total of 12 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Delegate | 20120784 | 187 days ago | IN | 0 ETH | 0.00131365 | ||||
Delegate | 19588923 | 261 days ago | IN | 0 ETH | 0.00468016 | ||||
Delegate | 19574538 | 263 days ago | IN | 0 ETH | 0.00479419 | ||||
Delegate | 19145666 | 324 days ago | IN | 0 ETH | 0.00406888 | ||||
Delegate | 19107550 | 329 days ago | IN | 0 ETH | 0.00102772 | ||||
Delegate | 19107549 | 329 days ago | IN | 0 ETH | 0.0022055 | ||||
Delegate | 19107526 | 329 days ago | IN | 0 ETH | 0.00293055 | ||||
Delegate | 18348691 | 435 days ago | IN | 0 ETH | 0.00124356 | ||||
Delegate | 18193866 | 457 days ago | IN | 0 ETH | 0.00202554 | ||||
Delegate | 18185620 | 458 days ago | IN | 0 ETH | 0.00251459 | ||||
Delegate | 18185617 | 458 days ago | IN | 0 ETH | 0.00280213 | ||||
Delegate | 17878540 | 501 days ago | IN | 0 ETH | 0.00684084 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
VeFxsVotingDelegation
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: ISC pragma solidity ^0.8.19; // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================= VeFxsVotingDelegation ====================== // ==================================================================== // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Jon Walch: https://github.com/jonwalch // Contributors // Dennis: https://github.com/denett // Drake Evans: https://github.com/DrakeEvans // Jamie Turley: https://github.com/jyturley // Reviewers // Sam Kazemian: https://github.com/samkazemian // ==================================================================== import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { IERC5805 } from "@openzeppelin/contracts/interfaces/IERC5805.sol"; import { IVeFxs } from "./interfaces/IVeFxs.sol"; import { IVeFxsVotingDelegation } from "./interfaces/IVeFxsVotingDelegation.sol"; /// @title VeFxsVotingDelegation /// @author Jon Walch (Frax Finance) https://github.com/jonwalch /// @notice Contract that keeps track of voting weights and delegations, leveraging veFXS contract VeFxsVotingDelegation is EIP712, IERC5805 { using SafeCast for uint256; /// @notice A week uint256 public constant WEEK = 7 days; /// @notice Max veFXS lock duration uint256 public constant MAX_LOCK_DURATION = 365 days * 4; /// @notice vote weight multiplier taken from veFXS uint256 public constant VOTE_WEIGHT_MULTIPLIER = 3; /// @notice Typehash needed for delegations by signature /// @dev keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)") bytes32 public constant DELEGATION_TYPEHASH = 0xe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf; /// @notice veFXS contract IVeFxs public immutable VE_FXS; /// @notice Nonces needed for delegations by signature mapping(address signer => uint256 nonce) public $nonces; /// @notice Mapping from delegator to delegate including additional parameters for our weight calculations. mapping(address delegator => IVeFxsVotingDelegation.Delegation delegate) public $delegations; /// @notice Mapping from delegate to their checkpoints. Checkpoints correspond to daily rounded dates of delegation. mapping(address delegate => IVeFxsVotingDelegation.DelegateCheckpoint[]) public $delegateCheckpoints; /// @notice Mapping from delegate to weekly rounded time of expiry to the aggregated values at time of expiration. Mirrors veFXS expiration. mapping(address delegate => mapping(uint256 week => IVeFxsVotingDelegation.Expiration)) public $expiredDelegations; /// @notice The ```constructor``` function is called on deployment /// @param veFxs Address of veFXS contract constructor(address veFxs, string memory name, string memory version) EIP712(name, version) { VE_FXS = IVeFxs(veFxs); } /// @notice The ```getCheckpoint``` function is called to retrieve a specific delegation checkpoint /// @dev Get the checkpoint for a delegate at a given index. /// @param delegateAddress Address of delegate /// @param index Integer index of the checkpoint /// @return delegateCheckpoint DelegateCheckpoint of ```delegate``` at ```index``` function getCheckpoint( address delegateAddress, uint32 index ) external view returns (IVeFxsVotingDelegation.DelegateCheckpoint memory) { return $delegateCheckpoints[delegateAddress][index]; } /// @notice The ```_calculateDelegatedWeight``` function calculates weight delegated to ```account``` accounting for any weight that expired since the nearest checkpoint /// @dev May include own weight if account previously delegated to someone else and then back to themselves /// @param voter Address of voter /// @param timestamp A block.timestamp, typically corresponding to a proposal snapshot /// @return delegatedWeight Voting weight corresponding to all ```delegateAccount```'s received delegations function _calculateDelegatedWeight( address voter, uint256 timestamp ) internal view returns (uint256 delegatedWeight) { // Check if delegate account has any delegations IVeFxsVotingDelegation.DelegateCheckpoint memory checkpoint = _checkpointBinarySearch({ _$checkpoints: $delegateCheckpoints[voter], timestamp: timestamp }); // If checkpoint is empty, short circuit and return 0 delegated weight if (checkpoint.timestamp == 0) { return 0; } // It's possible that some delegated veFXS has expired. // Add up all expirations during this time period, week by week. (uint256 totalExpiredBias, uint256 totalExpiredSlope, uint256 totalExpiredFxs) = _calculateExpirations({ account: voter, start: checkpoint.timestamp, end: timestamp, checkpoint: checkpoint }); uint256 expirationAdjustedBias = checkpoint.normalizedBias - totalExpiredBias; uint256 expirationAdjustedSlope = checkpoint.normalizedSlope - totalExpiredSlope; uint256 expirationAdjustedFxs = checkpoint.totalFxs - totalExpiredFxs; uint256 voteDecay = expirationAdjustedSlope * timestamp; uint256 biasAtTimestamp = (expirationAdjustedBias > voteDecay) ? expirationAdjustedBias - voteDecay : 0; // If all delegations are expired they have no voting weight. This differs from veFXS, which returns the locked FXS amount if it has not yet been withdrawn. delegatedWeight = expirationAdjustedFxs + (VOTE_WEIGHT_MULTIPLIER * biasAtTimestamp); } /// @notice The ```_calculateVotingWeight``` function calculates ```account```'s voting weight. Is 0 if they ever delegated and the delegation is in effect. /// @param voter Address of voter /// @param timestamp A block.timestamp, typically corresponding to a proposal snapshot /// @return votingWeight Voting weight corresponding to ```account```'s veFXS balance function _calculateVotingWeight(address voter, uint256 timestamp) internal view returns (uint256) { // If lock is expired they have no voting weight. This differs from veFXS, which returns the locked FXS amount if it has not yet been withdrawn. if (VE_FXS.locked(voter).end <= timestamp) return 0; uint256 firstDelegationTimestamp = $delegations[voter].firstDelegationTimestamp; // Never delegated OR this timestamp is before the first delegation by account if (firstDelegationTimestamp == 0 || timestamp < firstDelegationTimestamp) { try VE_FXS.balanceOf({ addr: voter, _t: timestamp }) returns (uint256 _balance) { return _balance; } catch {} } return 0; } /// @notice The ```calculateExpirations``` function calculates all expired delegations for an account since the last checkpoint. /// @dev Can be used in tandem with writeNewCheckpointForExpirations() to write a new checkpoint /// @dev Long time periods between checkpoints can increase gas costs for delegate() and castVote() /// @dev See _calculateExpirations /// @param delegateAddress Address of delegate /// @return calculatedCheckpoint A new DelegateCheckpoint to write based on expirations since previous checkpoint function calculateExpiredDelegations( address delegateAddress ) public view returns (IVeFxsVotingDelegation.DelegateCheckpoint memory calculatedCheckpoint) { IVeFxsVotingDelegation.DelegateCheckpoint[] storage $userDelegationCheckpoints = $delegateCheckpoints[ delegateAddress ]; // This ensures that checkpoints take effect at the next epoch uint256 checkpointTimestamp = ((block.timestamp / 1 days) * 1 days) + 1 days; uint256 checkpointsLength = $userDelegationCheckpoints.length; // Nothing to expire if no one delegated to you if (checkpointsLength == 0) return calculatedCheckpoint; IVeFxsVotingDelegation.DelegateCheckpoint memory lastCheckpoint = $userDelegationCheckpoints[ checkpointsLength - 1 ]; // Nothing expired because the most recent checkpoint is already written if (lastCheckpoint.timestamp == checkpointTimestamp) { return calculatedCheckpoint; } (uint256 totalExpiredBias, uint256 totalExpiredSlope, uint256 totalExpiredFxs) = _calculateExpirations({ account: delegateAddress, start: lastCheckpoint.timestamp, end: checkpointTimestamp, checkpoint: lastCheckpoint }); // All will be 0 if no expirations, only need to check one of them if (totalExpiredFxs == 0) return calculatedCheckpoint; /// NOTE: Checkpoint values will always be larger than or equal to expired values unchecked { calculatedCheckpoint = IVeFxsVotingDelegation.DelegateCheckpoint({ timestamp: uint128(checkpointTimestamp), normalizedBias: uint128(lastCheckpoint.normalizedBias - totalExpiredBias), normalizedSlope: uint128(lastCheckpoint.normalizedSlope - totalExpiredSlope), totalFxs: uint128(lastCheckpoint.totalFxs - totalExpiredFxs) }); } } /// @notice The ```writeNewCheckpointForExpirations``` function writes a new checkpoint if any weight has expired since the previous checkpoint /// @dev Long time periods between checkpoints can increase gas costs for delegate() and castVote() /// @dev See _calculateExpirations /// @param delegateAddress Address of delegate function writeNewCheckpointForExpiredDelegations(address delegateAddress) external { IVeFxsVotingDelegation.DelegateCheckpoint memory newCheckpoint = calculateExpiredDelegations(delegateAddress); if (newCheckpoint.timestamp == 0) revert IVeFxsVotingDelegation.NoExpirations(); $delegateCheckpoints[delegateAddress].push(newCheckpoint); } function CLOCK_MODE() public pure override returns (string memory) { return "mode=timestamp"; } function clock() public view override returns (uint48) { return uint48(block.timestamp); } /// @notice The ```_getVotingWeight``` function calculates a voter's voting weight at ```timestamp``` /// @param voter Address of voter /// @param timestamp A block.timestamp, typically corresponding to a proposal snapshot /// @return totalVotingWeight Voting weight of ```voter``` at ```timestamp``` function _getVotingWeight(address voter, uint256 timestamp) internal view returns (uint256 totalVotingWeight) { totalVotingWeight = _calculateVotingWeight({ voter: voter, timestamp: timestamp }) + _calculateDelegatedWeight({ voter: voter, timestamp: timestamp }); } /// @notice The ```getVotes``` function calculates a voter's weight at ```timestamp``` /// @param voter Address of voter /// @param timepoint A block.timestamp, typically corresponding to a proposal snapshot /// @return votingWeight Voting weight of ```voterAddress``` at ```timepoint``` function getVotes(address voter, uint256 timepoint) external view returns (uint256) { return _getVotingWeight({ voter: voter, timestamp: timepoint }); } /// @notice The ```getVotes``` function calculates a voter's weight at the current block.timestamp /// @param voter Address of voter /// @return votingWeight Voting weight of ```voterAddress``` at ```block.timestamp``` function getVotes(address voter) external view returns (uint256 votingWeight) { votingWeight = _getVotingWeight({ voter: voter, timestamp: block.timestamp }); } /// @notice The ```getPastVotes``` function calculates a voter's weight at ```timepoint``` /// @param voter Address of voter /// @param timepoint A block.timestamp, typically corresponding to a proposal snapshot, must be in past /// @return pastVotingWeight Voting weight of ```account``` at ```timepoint``` in past function getPastVotes(address voter, uint256 timepoint) external view returns (uint256 pastVotingWeight) { if (timepoint >= block.timestamp) revert IVeFxsVotingDelegation.TimestampInFuture(); pastVotingWeight = _getVotingWeight({ voter: voter, timestamp: timepoint }); } /// @notice The ```getPastTotalSupply``` function retrieves the total supply of veFXS at ```blockNumber``` /// @dev Must use block.number instead of timestamp because VE_FXS.totalSupply(timestamp) doesn't work for historical values. /// @param blockNumber block.number of total supply, must be in past /// @return pastTotalSupply veFXS supply at ```blockNumber``` function getPastTotalSupply(uint256 blockNumber) external view returns (uint256 pastTotalSupply) { // Future blocks are not valid if (blockNumber >= block.number) revert IVeFxsVotingDelegation.BlockNumberInFuture(); // Our total voting weight isn't the same as VE_FXS.totalSupplyAt(blockNumber) because // we expire all voting weight when the lock ends, which also may not be accounted for yet. // This is close enough. pastTotalSupply = VE_FXS.totalSupplyAt(blockNumber); } /// @notice The ```delegates``` function returns who the address of the delegate, that delegatorAddress has chosen /// @param delegator Address of delegator /// @return delegateAddress Address of the delegate function delegates(address delegator) external view returns (address delegateAddress) { delegateAddress = $delegations[delegator].delegate; } /// @notice The ```delegate``` function delegates votes from signer to ```delegatee``` at the next epoch /// @param delegatee Address to delegate to function delegate(address delegatee) external { _delegate({ delegator: msg.sender, delegatee: delegatee }); } /// @notice The ```delegate``` function delegates votes from signer to ```delegatee``` /// @param delegatee Address to delegate to /// @param nonce Nonce of signed message /// @param expiry Expiry time of message /// @param v Recovery ID /// @param r Output of an ECDSA signature /// @param s Output of an ECDSA signature function delegateBySig( address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) public virtual override { // Revert if signature is expired if (block.timestamp > expiry) revert IVeFxsVotingDelegation.SignatureExpired(); address signer = ECDSA.recover( _hashTypedDataV4(keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry))), v, r, s ); // Increment nonce and check against incremented value if (nonce != $nonces[signer]++) revert IVeFxsVotingDelegation.InvalidSignatureNonce(); _delegate(signer, delegatee); } /// @notice The ```_delegate``` function delegates votes from signer to ```delegatee``` at the next epoch /// @param delegator Caller delegating their weight /// @param delegatee Address to delegate to /// @dev An account can only delegate to one account at a time. The previous delegation will be overwritten. /// @dev To undelegate, ```delegatee``` should be ```address(delegator)``` function _delegate(address delegator, address delegatee) internal { // Revert if delegating to self with address(0), should be address(delegator) if (delegatee == address(0)) revert IVeFxsVotingDelegation.IncorrectSelfDelegation(); IVeFxsVotingDelegation.Delegation memory previousDelegation = $delegations[delegator]; // This ensures that checkpoints take effect at the next epoch uint256 checkpointTimestamp = ((block.timestamp / 1 days) * 1 days) + 1 days; IVeFxsVotingDelegation.NormalizedVeFxsLockInfo memory normalizedDelegatorVeFxsLockInfo = _getNormalizedVeFxsLockInfo({ delegator: delegator, checkpointTimestamp: checkpointTimestamp }); _moveVotingPowerFromPreviousDelegate({ previousDelegation: previousDelegation, checkpointTimestamp: checkpointTimestamp }); _moveVotingPowerToNewDelegate({ newDelegate: delegatee, delegatorVeFxsLockInfo: normalizedDelegatorVeFxsLockInfo, checkpointTimestamp: checkpointTimestamp }); // NOTE: Unsafe casting because these values will never exceed the size of their respective types $delegations[delegator] = IVeFxsVotingDelegation.Delegation({ delegate: delegatee, firstDelegationTimestamp: previousDelegation.firstDelegationTimestamp == 0 ? uint48(checkpointTimestamp) : previousDelegation.firstDelegationTimestamp, expiry: uint48(normalizedDelegatorVeFxsLockInfo.expiry), bias: uint96(normalizedDelegatorVeFxsLockInfo.bias), fxs: uint96(normalizedDelegatorVeFxsLockInfo.fxs), slope: uint64(normalizedDelegatorVeFxsLockInfo.slope) }); emit DelegateChanged({ delegator: delegator, fromDelegate: previousDelegation.delegate, toDelegate: delegatee }); } /// @notice The ```_getNormalizedVeFxsLockInfo``` function retrieves lock information from veFXS. We normalize and store this information to calculate voting weights /// @param delegator Address of the delegator /// @param checkpointTimestamp block.timestamp of the next checkpoint epoch /// @return normalizedVeFxsLockInfo Information about delegator's lock from veFXS contract, normalized function _getNormalizedVeFxsLockInfo( address delegator, uint256 checkpointTimestamp ) private view returns (IVeFxsVotingDelegation.NormalizedVeFxsLockInfo memory normalizedVeFxsLockInfo) { // Check expiry in case we need to revert uint256 expiry = VE_FXS.locked(delegator).end; if (expiry <= checkpointTimestamp) revert IVeFxsVotingDelegation.CantDelegateLockExpired(); // Most recent epoch uint256 epoch = VE_FXS.user_point_epoch(delegator); // Values for delegator at the most recent epoch (int128 userBias, int128 userSlope, , , uint256 userFxs) = VE_FXS.user_point_history({ _addr: delegator, _idx: epoch }); // Get the timestamp of the last update in veFXS user history uint256 lastUpdate = VE_FXS.user_point_history__ts({ _addr: delegator, _idx: epoch }); // Set return values normalizedVeFxsLockInfo.slope = SafeCast.toUint256(userSlope); normalizedVeFxsLockInfo.fxs = userFxs; normalizedVeFxsLockInfo.expiry = expiry; // Normalize bias to unix epoch, so all biases can be added and subtracted directly normalizedVeFxsLockInfo.bias = SafeCast.toUint256(userBias) + normalizedVeFxsLockInfo.slope * lastUpdate; } /// @notice The ```_checkpointBinarySearch``` function does a binary search for the closest checkpoint before ```timestamp``` /// @param _$checkpoints Storage pointer to the account's DelegateCheckpoints /// @param timestamp block.timestamp to get voting power at, frequently proposal snapshot /// @return closestCheckpoint The closest DelegateCheckpoint before timestamp function _checkpointBinarySearch( IVeFxsVotingDelegation.DelegateCheckpoint[] storage _$checkpoints, uint256 timestamp ) private view returns (IVeFxsVotingDelegation.DelegateCheckpoint memory closestCheckpoint) { uint256 checkpointsLength = _$checkpoints.length; // What the newest checkpoint could be for timestamp (rounded to whole days). It will be earlier when checkpoints are sparse. uint256 roundedDownTimestamp = (timestamp / 1 days) * 1 days; // Newest checkpoint's timestamp (already rounded to whole days) uint256 lastCheckpointTimestamp = checkpointsLength > 0 ? _$checkpoints[checkpointsLength - 1].timestamp : 0; // The furthest back a checkpoint will ever be is the number of days delta between timestamp and the last // checkpoints timestamp. This happens when there was a checkpoint written every single day over that period. // If roundedDownTimestamp > lastCheckpointTimestamp that means that we can just use the last index as // the checkpoint. uint256 delta = lastCheckpointTimestamp > roundedDownTimestamp ? (lastCheckpointTimestamp - roundedDownTimestamp) / 1 days : 0; // low index is equal to the last checkpoints index minus the index delta uint256 low = (checkpointsLength > 0 && checkpointsLength - 1 > delta) ? checkpointsLength - 1 - delta : 0; uint256 high = checkpointsLength; while (low < high) { uint256 mid = Math.average(low, high); if (_$checkpoints[mid].timestamp > timestamp) { high = mid; } else { low = mid + 1; } } closestCheckpoint = high == 0 ? closestCheckpoint : _$checkpoints[high - 1]; } /// @notice The ```_moveVotingPowerFromPreviousDelegate``` function removes voting power from the previous delegate, handling expirations /// @notice and writing a new DelegateCheckpoint /// @param previousDelegation The delegator's previous delegation /// @param checkpointTimestamp block.timestamp of the next DelegateCheckpoint's epoch function _moveVotingPowerFromPreviousDelegate( IVeFxsVotingDelegation.Delegation memory previousDelegation, uint256 checkpointTimestamp ) private { // Remove voting power from previous delegate, if they exist if (previousDelegation.delegate != address(0)) { // Get the last Checkpoint for previous delegate IVeFxsVotingDelegation.DelegateCheckpoint[] storage $previousDelegationCheckpoints = $delegateCheckpoints[ previousDelegation.delegate ]; uint256 accountCheckpointsLength = $previousDelegationCheckpoints.length; // NOTE: we know that _accountsCheckpointLength > 0 because we have already checked that the previous delegation exists IVeFxsVotingDelegation.DelegateCheckpoint memory lastCheckpoint = $previousDelegationCheckpoints[ accountCheckpointsLength - 1 ]; uint256 oldWeightOldDelegate = _getVotingWeight(previousDelegation.delegate, checkpointTimestamp); // Handle Expirations // Only subtract when the delegator's expiration is in the future. This way, the former delegates voting power // will still properly expire for proposals that happen between previousDelegation.expiry and a new delegation. // See testExpiredLockRedelegateNoVotingWeight(). if (previousDelegation.expiry > checkpointTimestamp) { // Calculations IVeFxsVotingDelegation.Expiration memory expiration = $expiredDelegations[previousDelegation.delegate][ previousDelegation.expiry ]; // All expiration fields will never exceed their size so subtraction doesnt need to be checked // and they can be unsafely cast unchecked { expiration.bias -= uint96(previousDelegation.bias); expiration.slope -= uint64(previousDelegation.slope); expiration.fxs -= uint96(previousDelegation.fxs); } // Effects $expiredDelegations[previousDelegation.delegate][previousDelegation.expiry] = expiration; } { // Calculate new checkpoint IVeFxsVotingDelegation.DelegateCheckpoint memory newCheckpoint = _calculateCheckpoint({ previousCheckpoint: lastCheckpoint, account: previousDelegation.delegate, isDeltaPositive: false, deltaBias: previousDelegation.bias, deltaSlope: previousDelegation.slope, deltaFxs: previousDelegation.fxs, checkpointTimestamp: checkpointTimestamp, previousDelegationExpiry: previousDelegation.expiry }); // Write new checkpoint _writeCheckpoint({ $userDelegationCheckpoints: $previousDelegationCheckpoints, accountCheckpointsLength: accountCheckpointsLength, newCheckpoint: newCheckpoint, lastCheckpoint: lastCheckpoint }); } // NOTE: oldWeightOldDelegate has had voting power decay since the previous event, meaning that // this event shouldn't be relied on. We did our best to conform to the standard. emit DelegateVotesChanged({ delegate: previousDelegation.delegate, previousBalance: oldWeightOldDelegate, newBalance: _getVotingWeight({ voter: previousDelegation.delegate, timestamp: checkpointTimestamp }) }); } } /// @notice The ```_moveVotingPowerToNewDelegate``` function adds voting power to the new delegate, handling expirations /// @notice and writing a new DelegateCheckpoint /// @param newDelegate The new delegate that is being delegated to /// @param delegatorVeFxsLockInfo Information about the delegator's veFXS lock /// @param checkpointTimestamp block.timestamp of the next DelegateCheckpoint's epoch function _moveVotingPowerToNewDelegate( address newDelegate, IVeFxsVotingDelegation.NormalizedVeFxsLockInfo memory delegatorVeFxsLockInfo, uint256 checkpointTimestamp ) private { // Get the last checkpoint for the new delegate IVeFxsVotingDelegation.DelegateCheckpoint[] storage $newDelegateCheckpoints = $delegateCheckpoints[newDelegate]; uint256 accountCheckpointsLength = $newDelegateCheckpoints.length; IVeFxsVotingDelegation.DelegateCheckpoint memory lastCheckpoint = accountCheckpointsLength == 0 ? IVeFxsVotingDelegation.DelegateCheckpoint(0, 0, 0, 0) : $newDelegateCheckpoints[accountCheckpointsLength - 1]; uint256 oldWeightNewDelegate = _getVotingWeight(newDelegate, checkpointTimestamp); // Handle expiration // Calculations IVeFxsVotingDelegation.Expiration memory expiration = $expiredDelegations[newDelegate][ delegatorVeFxsLockInfo.expiry ]; // NOTE: All expiration fields will never exceed their size so addition doesnt need to be checked // and can be unsafely cast unchecked { expiration.bias += uint96(delegatorVeFxsLockInfo.bias); expiration.slope += uint64(delegatorVeFxsLockInfo.slope); expiration.fxs += uint96(delegatorVeFxsLockInfo.fxs); } // Effects $expiredDelegations[newDelegate][delegatorVeFxsLockInfo.expiry] = expiration; // Calculate new checkpoint IVeFxsVotingDelegation.DelegateCheckpoint memory newCheckpoint = _calculateCheckpoint({ previousCheckpoint: lastCheckpoint, isDeltaPositive: true, account: newDelegate, deltaBias: delegatorVeFxsLockInfo.bias, deltaSlope: delegatorVeFxsLockInfo.slope, deltaFxs: delegatorVeFxsLockInfo.fxs, checkpointTimestamp: checkpointTimestamp, previousDelegationExpiry: 0 // not used }); // Write new checkpoint _writeCheckpoint({ $userDelegationCheckpoints: $newDelegateCheckpoints, accountCheckpointsLength: accountCheckpointsLength, newCheckpoint: newCheckpoint, lastCheckpoint: lastCheckpoint }); // NOTE: oldWeightNewDelegate has had voting power decay since the previous event, meaning that // this event shouldn't be relied on. We did our best to conform to the standard. emit DelegateVotesChanged({ delegate: newDelegate, previousBalance: oldWeightNewDelegate, newBalance: _getVotingWeight({ voter: newDelegate, timestamp: checkpointTimestamp }) }); } /// @notice The ```_calculateCheckpoint``` function calculates the values to be written for the new DelegateCheckpoint /// @param previousCheckpoint The previous checkpoint for account /// @param account The account to calculate the expirations for /// @param isDeltaPositive Whether adding or subtracting from the previous checkpoint /// @param deltaBias Amount of bias to add or subtract /// @param deltaSlope Amount of slope to add or subtract /// @param deltaFxs Amount of FXS to add or subtract /// @param checkpointTimestamp block.timestamp of the next DelegateCheckpoint's epoch /// @param previousDelegationExpiry When the previous delegation expires /// @return newCheckpoint The new DelegateCheckpoint to be stored function _calculateCheckpoint( IVeFxsVotingDelegation.DelegateCheckpoint memory previousCheckpoint, address account, bool isDeltaPositive, uint256 deltaBias, uint256 deltaSlope, uint256 deltaFxs, uint256 checkpointTimestamp, uint256 previousDelegationExpiry ) private view returns (IVeFxsVotingDelegation.DelegateCheckpoint memory newCheckpoint) { // If this is the first checkpoint, create a new one and early return if (previousCheckpoint.timestamp == 0) { return IVeFxsVotingDelegation.DelegateCheckpoint({ // can be unsafely cast because values will never exceed uint128 max timestamp: uint128(checkpointTimestamp), normalizedBias: uint128(deltaBias), normalizedSlope: uint128(deltaSlope), totalFxs: uint128(deltaFxs) }); } newCheckpoint.timestamp = previousCheckpoint.timestamp; newCheckpoint.normalizedBias = previousCheckpoint.normalizedBias; newCheckpoint.normalizedSlope = previousCheckpoint.normalizedSlope; newCheckpoint.totalFxs = previousCheckpoint.totalFxs; // All checkpoint fields will never exceed their size so addition and subtraction doesnt need to be checked unchecked { // Add or subtract the delta to the previous checkpoint if (isDeltaPositive) { newCheckpoint.normalizedBias += uint128(deltaBias); newCheckpoint.normalizedSlope += uint128(deltaSlope); newCheckpoint.totalFxs += uint128(deltaFxs); } else { // only subtract the weight from this account if it has not already expired in a previous checkpoint if (previousDelegationExpiry > previousCheckpoint.timestamp) { newCheckpoint.normalizedBias -= uint128(deltaBias); newCheckpoint.normalizedSlope -= uint128(deltaSlope); newCheckpoint.totalFxs -= uint128(deltaFxs); } } // If there have been expirations, incorporate the adjustments by subtracting them from the checkpoint if (newCheckpoint.timestamp != checkpointTimestamp) { (uint256 totalExpiredBias, uint256 totalExpiredSlope, uint256 totalExpiredFxs) = _calculateExpirations({ account: account, start: newCheckpoint.timestamp, end: checkpointTimestamp, checkpoint: previousCheckpoint }); newCheckpoint.timestamp = uint128(checkpointTimestamp); newCheckpoint.normalizedBias -= uint128(totalExpiredBias); newCheckpoint.normalizedSlope -= uint128(totalExpiredSlope); newCheckpoint.totalFxs -= uint128(totalExpiredFxs); } } } /// @notice The ```_writeCheckpoint``` function pushes a new checkpoint to the array or updates the most recent one if it already exists for the current epoch /// @param $userDelegationCheckpoints Pointer to the user's delegation checkpoints /// @param accountCheckpointsLength The length of the user's delegation checkpoints /// @param newCheckpoint The new checkpoint returned from _calculateCheckpoint() /// @param lastCheckpoint The most recent delegate checkpoint function _writeCheckpoint( IVeFxsVotingDelegation.DelegateCheckpoint[] storage $userDelegationCheckpoints, uint256 accountCheckpointsLength, IVeFxsVotingDelegation.DelegateCheckpoint memory newCheckpoint, IVeFxsVotingDelegation.DelegateCheckpoint memory lastCheckpoint ) internal { // If the newCheckpoint has the same timestamp as the last checkpoint, overwrite it if (accountCheckpointsLength > 0 && lastCheckpoint.timestamp == newCheckpoint.timestamp) { $userDelegationCheckpoints[accountCheckpointsLength - 1] = newCheckpoint; } else { // Otherwise, push a new checkpoint $userDelegationCheckpoints.push(newCheckpoint); } } /// @notice The ```_calculateExpirations``` function generates a summation of all bias, slope, and fxs for all delegations that expire during the specified time window for ```account``` /// @param account Delegate account to generate summations for /// @param start Timestamp to start the summations from. The start is not included /// @param end Timestamp to end the summations. The end is included /// @param checkpoint Checkpoint to start expirations at /// @return totalExpiredBias Total bias that expired for delegate ```account``` during timeframe /// @return totalExpiredSlope Total slope that expired for delegate ```account``` during timeframe /// @return totalExpiredFxs Total FXS that expired for delegate ```account``` during timeframe function _calculateExpirations( address account, uint256 start, uint256 end, IVeFxsVotingDelegation.DelegateCheckpoint memory checkpoint ) private view returns (uint256 totalExpiredBias, uint256 totalExpiredSlope, uint256 totalExpiredFxs) { unchecked { // Maximum lock time for veFXS is 4 years, it will all be expired if (end > start + MAX_LOCK_DURATION) { totalExpiredBias = checkpoint.normalizedBias; totalExpiredSlope = checkpoint.normalizedSlope; totalExpiredFxs = checkpoint.totalFxs; } else { // Total values will always be less than or equal to a checkpoint's values uint256 currentWeek = WEEK + (start / WEEK) * WEEK; mapping(uint256 => IVeFxsVotingDelegation.Expiration) storage $delegateExpirations = $expiredDelegations[account]; // Sum values from currentWeek until end while (currentWeek <= end) { IVeFxsVotingDelegation.Expiration memory expiration = $delegateExpirations[currentWeek]; totalExpiredBias += expiration.bias; totalExpiredSlope += expiration.slope; totalExpiredFxs += expiration.fxs; currentWeek += WEEK; } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.8; import "./ECDSA.sol"; import "../ShortStrings.sol"; import "../../interfaces/IERC5267.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _name.toStringWithFallback(_nameFallback), _version.toStringWithFallback(_versionFallback), block.chainid, address(this), bytes32(0), new uint256[](0) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol) pragma solidity ^0.8.0; import "../governance/utils/IVotes.sol"; import "./IERC6372.sol"; interface IERC5805 is IERC6372, IVotes {}
// SPDX-License-Identifier: ISC pragma solidity >=0.6.11; pragma abicoder v2; interface IVeFxs { struct LockedBalance { int128 amount; uint256 end; } function commit_transfer_ownership(address addr) external; function apply_transfer_ownership() external; function commit_smart_wallet_checker(address addr) external; function apply_smart_wallet_checker() external; function toggleEmergencyUnlock() external; function recoverERC20(address token_addr, uint256 amount) external; function get_last_user_slope(address addr) external view returns (int128); function user_point_history__ts(address _addr, uint256 _idx) external view returns (uint256); function locked__end(address _addr) external view returns (uint256); function checkpoint() external; function deposit_for(address _addr, uint256 _value) external; function create_lock(uint256 _value, uint256 _unlock_time) external; function increase_amount(uint256 _value) external; function increase_unlock_time(uint256 _unlock_time) external; function withdraw() external; function balanceOf(address addr) external view returns (uint256); function balanceOf(address addr, uint256 _t) external view returns (uint256); function balanceOfAt(address addr, uint256 _block) external view returns (uint256); function totalSupply() external view returns (uint256); function totalSupply(uint256 t) external view returns (uint256); function totalSupplyAt(uint256 _block) external view returns (uint256); function totalFXSSupply() external view returns (uint256); function totalFXSSupplyAt(uint256 _block) external view returns (uint256); function changeController(address _newController) external; function token() external view returns (address); function supply() external view returns (uint256); function locked(address addr) external view returns (LockedBalance memory); function epoch() external view returns (uint256); function point_history( uint256 arg0 ) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_history( address _addr, uint256 _idx ) external view returns (int128 bias, int128 slope, uint256 ts, uint256 blk, uint256 fxs_amt); function user_point_epoch(address arg0) external view returns (uint256); function slope_changes(uint256 arg0) external view returns (int128); function controller() external view returns (address); function transfersEnabled() external view returns (bool); function emergencyUnlockActive() external view returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function version() external view returns (string memory); function decimals() external view returns (uint256); function future_smart_wallet_checker() external view returns (address); function smart_wallet_checker() external view returns (address); function admin() external view returns (address); function future_admin() external view returns (address); }
// SPDX-License-Identifier: ISC pragma solidity >=0.8.19; interface IVeFxsVotingDelegation { /// Represents the values of a single delegation at the time `delegate()` is called, /// to be subtracted when removing delegation struct Delegation { address delegate; uint48 firstDelegationTimestamp; uint48 expiry; // __________ uint96 bias; uint96 fxs; uint64 slope; } /// A representation of a delegate and all its delegators at a particular timestamp struct DelegateCheckpoint { uint128 normalizedBias; uint128 totalFxs; // _________ uint128 normalizedSlope; uint128 timestamp; // Rounded up to the nearest day } /// Represents the total bias, slope, and FXS amount of all accounts that expire for a specific delegate /// in a particular week struct Expiration { uint96 bias; uint96 fxs; uint64 slope; } // Only used in memory struct NormalizedVeFxsLockInfo { uint256 bias; uint256 slope; uint256 fxs; uint256 expiry; } function $delegateCheckpoints( address, uint256 ) external view returns (uint128 normalizedBias, uint128 totalFxs, uint128 normalizedSlope, uint128 timestamp); function $delegations( address ) external view returns ( address delegate, uint48 firstDelegationTimestamp, uint48 expiry, uint96 bias, uint96 fxs, uint64 slope ); function $expiredDelegations(address, uint256) external view returns (uint96 bias, uint96 fxs, uint64 slope); function $nonces(address) external view returns (uint256); function CLOCK_MODE() external pure returns (string memory); function DELEGATION_TYPEHASH() external view returns (bytes32); function MAX_LOCK_DURATION() external view returns (uint256); function VE_FXS() external view returns (address); function VOTE_WEIGHT_MULTIPLIER() external view returns (uint256); function WEEK() external view returns (uint256); function calculateExpiredDelegations( address delegateAddress ) external view returns (DelegateCheckpoint memory calculatedCheckpoint); function clock() external view returns (uint48); function delegate(address delegatee) external; function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; function delegates(address delegator) external view returns (address delegateAddress); function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); function getCheckpoint(address delegateAddress, uint32 index) external view returns (DelegateCheckpoint memory); function getPastTotalSupply(uint256 blockNumber) external view returns (uint256 pastTotalSupply); function getPastVotes(address voter, uint256 timepoint) external view returns (uint256 pastVotingWeight); function getVotes(address voter) external view returns (uint256 votingWeight); function getVotes(address voter, uint256 timepoint) external view returns (uint256); function writeNewCheckpointForExpiredDelegations(address delegateAddress) external; error BlockNumberInFuture(); error CantDelegateLockExpired(); error IncorrectSelfDelegation(); error InvalidSignatureNonce(); error NoExpirations(); error SignatureExpired(); error TimestampInFuture(); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) pragma solidity ^0.8.8; import "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(_FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.0; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol) pragma solidity ^0.8.0; /** * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts. * * _Available since v4.5._ */ interface IVotes { /** * @dev Emitted when an account changes their delegate. */ event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /** * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. */ event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); /** * @dev Returns the current amount of votes that `account` has. */ function getVotes(address account) external view returns (uint256); /** * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is * configured to use block numbers, this will return the value at the end of the corresponding block. */ function getPastVotes(address account, uint256 timepoint) external view returns (uint256); /** * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is * configured to use block numbers, this will return the value at the end of the corresponding block. * * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. * Votes that have not been delegated are still part of total supply, even though they would not participate in a * vote. */ function getPastTotalSupply(uint256 timepoint) external view returns (uint256); /** * @dev Returns the delegate that `account` has chosen. */ function delegates(address account) external view returns (address); /** * @dev Delegates votes from the sender to `delegatee`. */ function delegate(address delegatee) external; /** * @dev Delegates votes from signer to `delegatee`. */ function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol) pragma solidity ^0.8.0; interface IERC6372 { /** * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). */ function clock() external view returns (uint48); /** * @dev Description of the clock */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
{ "remappings": [ "@gnosis.pm/=node_modules/@gnosis.pm/safe-contracts/", "@openzeppelin/=node_modules/openzeppelin-solidity/", "ds-test/=node_modules/ds-test/src/", "forge-std/=node_modules/forge-std/src/", "frax-std/=node_modules/frax-standard-solidity/src/", "safe-contracts/=node_modules/@gnosis.pm/safe-contracts/contracts/", "safe-tools/=node_modules/safe-tools/src/", "solady/=node_modules/solady/src/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"veFxs","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BlockNumberInFuture","type":"error"},{"inputs":[],"name":"CantDelegateLockExpired","type":"error"},{"inputs":[],"name":"IncorrectSelfDelegation","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidSignatureNonce","type":"error"},{"inputs":[],"name":"NoExpirations","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"TimestampInFuture","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"$delegateCheckpoints","outputs":[{"internalType":"uint128","name":"normalizedBias","type":"uint128"},{"internalType":"uint128","name":"totalFxs","type":"uint128"},{"internalType":"uint128","name":"normalizedSlope","type":"uint128"},{"internalType":"uint128","name":"timestamp","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"$delegations","outputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint48","name":"firstDelegationTimestamp","type":"uint48"},{"internalType":"uint48","name":"expiry","type":"uint48"},{"internalType":"uint96","name":"bias","type":"uint96"},{"internalType":"uint96","name":"fxs","type":"uint96"},{"internalType":"uint64","name":"slope","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"week","type":"uint256"}],"name":"$expiredDelegations","outputs":[{"internalType":"uint96","name":"bias","type":"uint96"},{"internalType":"uint96","name":"fxs","type":"uint96"},{"internalType":"uint64","name":"slope","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"$nonces","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LOCK_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VE_FXS","outputs":[{"internalType":"contract IVeFxs","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTE_WEIGHT_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegateAddress","type":"address"}],"name":"calculateExpiredDelegations","outputs":[{"components":[{"internalType":"uint128","name":"normalizedBias","type":"uint128"},{"internalType":"uint128","name":"totalFxs","type":"uint128"},{"internalType":"uint128","name":"normalizedSlope","type":"uint128"},{"internalType":"uint128","name":"timestamp","type":"uint128"}],"internalType":"struct IVeFxsVotingDelegation.DelegateCheckpoint","name":"calculatedCheckpoint","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"delegateAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegateAddress","type":"address"},{"internalType":"uint32","name":"index","type":"uint32"}],"name":"getCheckpoint","outputs":[{"components":[{"internalType":"uint128","name":"normalizedBias","type":"uint128"},{"internalType":"uint128","name":"totalFxs","type":"uint128"},{"internalType":"uint128","name":"normalizedSlope","type":"uint128"},{"internalType":"uint128","name":"timestamp","type":"uint128"}],"internalType":"struct IVeFxsVotingDelegation.DelegateCheckpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"pastTotalSupply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"pastVotingWeight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"votingWeight","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegateAddress","type":"address"}],"name":"writeNewCheckpointForExpiredDelegations","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101808060405234620001c057620034d38038038091620000218285620001c5565b8339810190606081830312620001c05780516001600160a01b03811690819003620001c05760208201516001600160401b039290838111620001c057846200006b9183016200020e565b936040820151848111620001c0576200008592016200020e565b92620000918162000269565b610120908152620000a2856200041d565b9161014092835260208151910120948560e0526020815191012094610100958087524660a0526040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815260c081019581871090871117620001aa57856040525190206080523060c052610160928352612f6994856200056a863960805185611ce5015260a05185611da0015260c05185611cb6015260e05185611d3401525184611d5a015251836107060152518261073001525181818161062c01528181610a8c015281816118d601528181611f0a01528181611fa90152818161204501526120e80152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b601f909101601f19168101906001600160401b03821190821017620001aa57604052565b60005b838110620001fd5750506000910152565b8181015183820152602001620001ec565b81601f82011215620001c05780516001600160401b038111620001aa576040519262000245601f8301601f191660200185620001c5565b81845260208284010111620001c057620002669160208085019101620001e9565b90565b80516020919082811015620002e9575090601f825111620002a757808251920151908083106200029857501790565b82600019910360031b1b161790565b604490620002db9260405193849263305a27a960e01b845280600485015282519283918260248701528686019101620001e9565b601f01601f19168101030190fd5b6001600160401b038111620001aa576000928354926001938481811c9116801562000412575b83821014620003fe57601f8111620003c8575b5081601f8411600114620003615750928293918392869462000355575b50501b916000199060031b1c191617905560ff90565b0151925038806200033f565b919083601f1981168780528488209488905b88838310620003ad575050501062000393575b505050811b01905560ff90565b015160001960f88460031b161c1916905538808062000386565b85870151885590960195948501948793509081019062000373565b85805284601f848820920160051c820191601f860160051c015b828110620003f257505062000322565b878155018590620003e2565b634e487b7160e01b86526022600452602486fd5b90607f16906200030f565b8051602090818110156200044a5750601f825111620002a757808251920151908083106200029857501790565b9192916001600160401b038111620001aa5760019182548381811c911680156200055e575b828210146200054857601f81116200050f575b5080601f8311600114620004c2575081929394600092620004b6575b5050600019600383901b1c191690821b17905560ff90565b0151905038806200049e565b90601f198316958460005282600020926000905b888210620004f757505083859697106200039357505050811b01905560ff90565b808785968294968601518155019501930190620004d6565b8360005283601f83600020920160051c820191601f850160051c015b8281106200053b57505062000482565b600081550184906200052b565b634e487b7160e01b600052602260045260246000fd5b90607f16906200046f56fe608060408181526004918236101561001657600080fd5b600092833560e01c918263101f46d514610d96575081631c94541214610d0857816334940fa814610c7c5781633a46b1a814610bfa5781633b3eb8a614610b6c5781634bf5d7e914610aed5781634f1bfc9e14610ab0578163506d1f8114610a41578163587cde1e146109dc5781635c19a95c1461099b5781636e22c4af146108ed57816375f9e3961461084157816384b0196e146106d05781638e539e8c146105aa57816391ddadf414610569578163944c39301461052f5781639ab24eb0146104db578163b06128211461042b578163c3cda5201461020d57508063e7a324dc146101b5578063eb9019d4146101555763f4359ce51461011757600080fd5b3461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905162093a808152f35b5080fd5b503461015157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020906101ae610192610df5565b6101a86024356101a281846118bc565b92611522565b9061129d565b9051908152f35b503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157602090517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8152f35b8383346101515760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157610246610df5565b9060243560443560643560ff81168103610427578142116103ff57835160208101907fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf825273ffffffffffffffffffffffffffffffffffffffff938488168783015285606083015260808201526080815260a0810181811067ffffffffffffffff8211176103d357865251902061032f94939291610327916102e6611c9f565b908651917f190100000000000000000000000000000000000000000000000000000000000083526002830152602282015260a4359160426084359220611c03565b949094611a6a565b831685526002602052818520908154917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83146103a7576001830190550361037f57509061037c91611dc6565b80f35b8490517fc4689a54000000000000000000000000000000000000000000000000000000008152fd5b60248760118a7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60248960418c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8684517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b8383346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157610464610df5565b9061046e826112b7565b916fffffffffffffffffffffffffffffffff606084015116156104b3579373ffffffffffffffffffffffffffffffffffffffff61037c949516855260205283206114f4565b8482517fc1ccb3d1000000000000000000000000000000000000000000000000000000008152fd5b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020906101ae61051a610df5565b6101a861052742836118bc565b914290611522565b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905160038152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905165ffffffffffff42168152f35b83833461015157602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc578035438110156106a4578251917f981b24d0000000000000000000000000000000000000000000000000000000008352820152838160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa928315610699578093610664575b505051908152f35b909192508382813d8311610692575b61067d8183610f65565b8101031261068f57505190838061065c565b80fd5b503d610673565b8251903d90823e3d90fd5b5090517f089b2f6f000000000000000000000000000000000000000000000000000000008152fd5b8280fd5b919050346106cc57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc5761072a7f0000000000000000000000000000000000000000000000000000000000000000610fa6565b926107547f000000000000000000000000000000000000000000000000000000000000000061111c565b908251926020928385019585871067ffffffffffffffff881117610815575092806107cb8388966107be998b9996528686528151998a997f0f000000000000000000000000000000000000000000000000000000000000008b5260e0868c015260e08b0190610e1d565b91898303908a0152610e1d565b924660608801523060808801528460a088015286840360c088015251928381520193925b8281106107fe57505050500390f35b8351855286955093810193928101926001016107ef565b8360416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b82843461068f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261068f57610879610df5565b9273ffffffffffffffffffffffffffffffffffffffff6024359416825260205281812090815484101561068f57506080926108b391610e7b565b509060018254920154908051926fffffffffffffffffffffffffffffffff908181168552851c6020850152821690830152821c6060820152f35b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157908160c09273ffffffffffffffffffffffffffffffffffffffff9283610942610df5565b1681526003602052209060018254920154918151938116845265ffffffffffff8160a01c16602085015260d01c908301526bffffffffffffffffffffffff80821660608401528160601c166080830152821c60a0820152f35b833461068f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261068f5761037c6109d6610df5565b33611dc6565b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020918173ffffffffffffffffffffffffffffffffffffffff9182610a30610df5565b168152600385522054169051908152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101515760209051630784ce008152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151578051610b6891610b2c82610f49565b600e82527f6d6f64653d74696d657374616d70000000000000000000000000000000000000602083015251918291602083526020830190610e1d565b0390f35b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157610b6890610bb1610bac610df5565b6112b7565b90519182918291909160606080820193816fffffffffffffffffffffffffffffffff91828151168552826020820151166020860152826040820151166040860152015116910152565b82843461068f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261068f5750610c33610df5565b916024359042821015610c555750826101a8826101a26101ae946020976118bc565b82517f47860b97000000000000000000000000000000000000000000000000000000008152fd5b9050346106cc57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc57610cb4610df5565b906024359163ffffffff83168303610d04579183610b6895610cfe9373ffffffffffffffffffffffffffffffffffffffff610bb196610cf16111ef565b5016825260205220610e7b565b50611214565b8480fd5b50503461015157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151578060609273ffffffffffffffffffffffffffffffffffffffff610d59610df5565b168152600560205281812060243582526020522054908051916bffffffffffffffffffffffff808216845281851c16602084015260c01c90820152f35b849084346106cc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc5760209273ffffffffffffffffffffffffffffffffffffffff610de8610df5565b1681526002845220548152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610e1857565b600080fd5b919082519283825260005b848110610e675750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610e28565b8054821015610e975760005260206000209060011b0190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080810190811067ffffffffffffffff821117610ee257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60c0810190811067ffffffffffffffff821117610ee257604052565b6060810190811067ffffffffffffffff821117610ee257604052565b6040810190811067ffffffffffffffff821117610ee257604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610ee257604052565b60ff8114610ffc5760ff811690601f8211610fd25760405191610fc883610f49565b8252602082015290565b60046040517fb3512b0c000000000000000000000000000000000000000000000000000000008152fd5b506040516000805490600182811c90808416938415611112575b60209485841081146110e557838752869493929181156110a6575060011461104a575b505061104792500382610f65565b90565b60008080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56395935091905b81831061108e57505061104793508201013880611039565b85548784018501529485019486945091830191611076565b90506110479593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611039565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b91607f1691611016565b60ff811461113e5760ff811690601f8211610fd25760405191610fc883610f49565b50604051600060019081549182811c908084169384156111e5575b60209485841081146110e557838752869493929181156110a6575060011461118957505061104792500382610f65565b60008181527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf695935091905b8183106111cd57505061104793508201013880611039565b855487840185015294850194869450918301916111b5565b91607f1691611159565b604051906111fc82610ec6565b60006060838281528260208201528260408201520152565b9060405161122181610ec6565b6060819360018154916fffffffffffffffffffffffffffffffff92838116865260801c60208601520154908116604084015260801c910152565b8181029291811591840414171561126e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820180921161126e57565b9190820391821161126e57565b6112bf6111ef565b90600073ffffffffffffffffffffffffffffffffffffffff82168152600460205260408120906201518091824204928084029380850482149015171561142b5783018093116113fe5780549182156113c9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019283116113d1575061134991610cfe91610e7b565b6fffffffffffffffffffffffffffffffff92836060830151168381146113c95783839161137593612e6b565b91909582156113bf5750908460208180809581885116031698816040880151160316940151160316604051946113aa86610ec6565b85526020850152604084015216606082015290565b9550505050505090565b505050505090565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b906114c557815160208301516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffffffffffff00000000000000000000000000000000608092831b8116919091178455604085015160609095015190911b16921691909117600190910155565b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b9081549168010000000000000000831015610ee2578261151c9160016114c395018155610e7b565b90611458565b91909160009073ffffffffffffffffffffffffffffffffffffffff8116825260049384602052604083206115546111ef565b81546201518092838504938085029480860482149015171561179e57821580159190611865577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401848111611839576115b060019185610e7b565b50015460801c955b6fffffffffffffffffffffffffffffffff968716908082111561182f576115de916112aa565b04905b806117fd575b156117f6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018381116117ca5790611620916112aa565b82811061175b5750816116f0575050925b816060850151169081156116e65761167661168593602061165b8888611669999761167f97612e6b565b9491848b9a929a51166112aa565b978360408b0151166112aa565b970151166112aa565b9361125b565b808211156116de57611696916112aa565b915b826003029260038404036116b2575061104792935061129d565b806011867f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b505081611698565b5093955050505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201925090821161172f5761172991610cfe91610e7b565b92611631565b60248660118a7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b9160019061176f818518831c82861661129d565b91878161177c8587610e7b565b50015460801c111561179057505091611620565b909350810180911115611620575b60248860118c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60248960118d7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5086611620565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018381116117ca5781106115e7565b50505087906115e1565b60248a60118e7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b88956115b8565b519081600f0b8203610e1857565b90816040910312610e185760405190604082019082821067ffffffffffffffff831117610ee2576020916040526118b08161186c565b83520151602082015290565b9073ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000000000000000000000000000000000000000000016906040918251937fcbf9fe5f00000000000000000000000000000000000000000000000000000000855285168060048601528385602481855afa948515611a5f57600095611a30575b50826020809601511115611a25576000526003845265ffffffffffff836000205460a01c168015908115611a1b575b5061197e575b5050505050600090565b91517efdd58e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff94909416600485015260248401528190839060449082905afa9182916000936119ea575b50506110475780808080611974565b8181949293943d8311611a14575b611a028183610f65565b8101031261068f5750519038806119db565b503d6119f8565b905082103861196e565b505050505050600090565b611a51919550843d8611611a58575b611a498183610f65565b81019061187a565b933861193f565b503d611a3f565b84513d6000823e3d90fd5b6005811015611bd45780611a7b5750565b60018103611ae15760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152fd5b60028103611b475760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152fd5b600314611b5057565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9291907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311611c935791608094939160ff602094604051948552168484015260408301526060820152600093849182805260015afa15611c8657815173ffffffffffffffffffffffffffffffffffffffff811615611c80579190565b50600190565b50604051903d90823e3d90fd5b50505050600090600390565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016301480611d9d575b15611d07577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a08152611d9781610f11565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614611cde565b73ffffffffffffffffffffffffffffffffffffffff821615612ac45773ffffffffffffffffffffffffffffffffffffffff81166000526003602052604060002091600160405193611e1685610f11565b805473ffffffffffffffffffffffffffffffffffffffff8116865265ffffffffffff8160a01c16602087015260d01c604086015201546bffffffffffffffffffffffff811660608501526bffffffffffffffffffffffff8160601c16608085015260c01c60a08401526201518090814204918083029280840482149015171561126e57808301831161126e57611eaa6111ef565b906040517fcbf9fe5f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616600482015260408160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156129e657602091600091612aa5575b500151818501811115612a7b576040517f010ae75700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8716600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156129e657600091612a49575b506040517f28d09d4700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff881660048201526024810182905260a0818060448101038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156129e6576000916000906000926129f2575b506040517fda020a1800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b166004820152602481019490945260208480604481015b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9384156129e6576000946129aa575b509161215494612149926121326101a895600f0b612aee565b60208a015260408901526060880152600f0b612aee565b91602086015161125b565b825273ffffffffffffffffffffffffffffffffffffffff86511680612689575b5073ffffffffffffffffffffffffffffffffffffffff83166000526004602052604060002080549081156000146125fb579267ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff968796946125c6946123c289986040516121dd81610ec6565b60008152600060208201526000604082015260006060820152905b6122136122078688018c6118bc565b6101a88789018d611522565b938b8b166000526005602052604060002060608a01516000526020526123a060406000206bffffffffffffffffffffffff8b8180604080519561225587610f2d565b54938285168752828560601c1660208801528460c01c828801528280825116818716011687528f806020830151168660c01c0116828801520151169160601c16011660208201528d8d166000526005602052604060002060608c015160005260205289604080600020926bffffffffffffffffffffffff8151167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008554161784556123566bffffffffffffffffffffffff60208301511685907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b0151825477ffffffffffffffffffffffffffffffffffffffffffffffff16911660c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016179055565b6123bc898c815160208301519060408b8d019401519288612cff565b91612def565b6123dd6123d1838501896118bc565b6101a88486018a611522565b60405191825260208201527fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724604089891692a260208b015165ffffffffffff1691826125f35765ffffffffffff92500116915b61257d6bffffffffffffffffffffffff65ffffffffffff606084015116928181511685602084604085015116930151169465ffffffffffff604051986124758a610f11565b8c8c168a52166020890152604088015260608701526080860190815260a08601938452888c166000526003602052816060600160406000208c8a511679ffffffffffff000000000000000000000000000000000000000060208c015160a01b16907fffffffffffff000000000000000000000000000000000000000000000000000060408d015160d01b16911717815501970151167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000875416178655511684907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b51825477ffffffffffffffffffffffffffffffffffffffffffffffff16911660c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016179055565b1693511691167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a4565b505091612430565b94939192817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81011161126e5767ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9695879695846123c28998612683610cfe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6125c69a0183610e7b565b906121f8565b60005260046020526040600020805490817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81011161126e576127ab906126f5610cfe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff850183610e7b565b9061272a73ffffffffffffffffffffffffffffffffffffffff8b51166101a8612720888c01836118bc565b91888c0190611522565b9385890165ffffffffffff60408d01511611612813575b6123bc8973ffffffffffffffffffffffffffffffffffffffff8d51168d6bffffffffffffffffffffffff60608201511667ffffffffffffffff60a083015116908b65ffffffffffff60406bffffffffffffffffffffffff6080870151169501511695019389612b57565b7fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724604073ffffffffffffffffffffffffffffffffffffffff895116926128026127f6868a01866118bc565b6101a8878b0187611522565b82519182526020820152a238612174565b73ffffffffffffffffffffffffffffffffffffffff8b51166000526005602052604060002065ffffffffffff60408d0151166000526020526129a560406000206bffffffffffffffffffffffff8d818060806040519561287287610f2d565b54938285168752828560601c1660208801528460c01c604088015282806060830151168187160316875267ffffffffffffffff8060a0830151168660c01c031660408801520151169160601c160316602082015273ffffffffffffffffffffffffffffffffffffffff8d511660005260056020528c65ffffffffffff6040806000209201511660005260205267ffffffffffffffff604080600020926bffffffffffffffffffffffff8151167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008554161784556123566bffffffffffffffffffffffff60208301511685907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b612741565b91929093506020823d6020116129de575b816129c860209383610f65565b81010312610e1857905192909190612154612119565b3d91506129bb565b6040513d6000823e3d90fd5b9250505060a0813d60a011612a41575b81612a0f60a09383610f65565b81010312610e18576120cf91612a248261186c565b60206080612a3382860161186c565b94015191939192945061207b565b3d9150612a02565b90506020813d602011612a73575b81612a6460209383610f65565b81010312610e18575138611fda565b3d9150612a57565b60046040517f14271110000000000000000000000000000000000000000000000000000000008152fd5b612abe915060403d604011611a5857611a498183610f65565b38611f3d565b60046040517f3252b88f000000000000000000000000000000000000000000000000000000008152fd5b60008112612af95790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152fd5b9196959492612b646111ef565b976fffffffffffffffffffffffffffffffff60608501511615612cbc57886fffffffffffffffffffffffffffffffff606086015116968760608301526fffffffffffffffffffffffffffffffff865116928383526fffffffffffffffffffffffffffffffff6040880151168060408501526fffffffffffffffffffffffffffffffff60208901511694602085019b868d526fffffffffffffffffffffffffffffffff60608b01511610612c81575b50505050505050828403612c28575b5050505050565b6fffffffffffffffffffffffffffffffff838180612c4d819896829883988498612e6b565b9790941660608d015216818b5116031689521681604089015116031660408701521681835116031690523880808080612c21565b6fffffffffffffffffffffffffffffffff92831690038216909352938416909103831660408b01528216900316855238808881808080612c12565b9697509150506fffffffffffffffffffffffffffffffff8094508092938160405197612ce789610ec6565b16875216602086015216604084015216606082015290565b90959495929192612d0e6111ef565b9660608301946fffffffffffffffffffffffffffffffff958681511615612dd45784939291878b968180809551169960608a01998b8b528280855116808352818060208160408a0151169889604088015201511698160116905216011660408c01528160208c01991601168752808503612d8c575b50505050505050565b858080612d9f8198968583988498612e6b565b989192909516905216818b51160316895216816040890151160316604087015216818351160316905238808080808080612d83565b509697509394858094935080925060405197612ce789610ec6565b90928315159081612e42575b5015612e38577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830192831161126e576114c39261151c91610e7b565b6114c392506114f4565b606091506fffffffffffffffffffffffffffffffff918291015116906060840151161438612dfb565b9091600092600092838093630784ce0084018111600014612eb457505050505050506fffffffffffffffffffffffffffffffff9182825116926020816040850151169301511690565b9193959794965073ffffffffffffffffffffffffffffffffffffffff62093a808080950402840194168152602090600582526040908181205b84871115612efe5750505050505050565b90919293948698999a8197845282865284808520815190612f1e82610f2d565b54926bffffffffffffffffffffffff91828516928382528560601c1694858b83015260c01c9384910152019c019a0198019493929190959495612eed56fea164736f6c6343000813000a000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000155665467873566f74696e6744656c65676174696f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060408181526004918236101561001657600080fd5b600092833560e01c918263101f46d514610d96575081631c94541214610d0857816334940fa814610c7c5781633a46b1a814610bfa5781633b3eb8a614610b6c5781634bf5d7e914610aed5781634f1bfc9e14610ab0578163506d1f8114610a41578163587cde1e146109dc5781635c19a95c1461099b5781636e22c4af146108ed57816375f9e3961461084157816384b0196e146106d05781638e539e8c146105aa57816391ddadf414610569578163944c39301461052f5781639ab24eb0146104db578163b06128211461042b578163c3cda5201461020d57508063e7a324dc146101b5578063eb9019d4146101555763f4359ce51461011757600080fd5b3461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905162093a808152f35b5080fd5b503461015157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020906101ae610192610df5565b6101a86024356101a281846118bc565b92611522565b9061129d565b9051908152f35b503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157602090517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8152f35b8383346101515760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157610246610df5565b9060243560443560643560ff81168103610427578142116103ff57835160208101907fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf825273ffffffffffffffffffffffffffffffffffffffff938488168783015285606083015260808201526080815260a0810181811067ffffffffffffffff8211176103d357865251902061032f94939291610327916102e6611c9f565b908651917f190100000000000000000000000000000000000000000000000000000000000083526002830152602282015260a4359160426084359220611c03565b949094611a6a565b831685526002602052818520908154917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83146103a7576001830190550361037f57509061037c91611dc6565b80f35b8490517fc4689a54000000000000000000000000000000000000000000000000000000008152fd5b60248760118a7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60248960418c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8684517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b8383346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157610464610df5565b9061046e826112b7565b916fffffffffffffffffffffffffffffffff606084015116156104b3579373ffffffffffffffffffffffffffffffffffffffff61037c949516855260205283206114f4565b8482517fc1ccb3d1000000000000000000000000000000000000000000000000000000008152fd5b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020906101ae61051a610df5565b6101a861052742836118bc565b914290611522565b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905160038152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905165ffffffffffff42168152f35b83833461015157602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc578035438110156106a4578251917f981b24d0000000000000000000000000000000000000000000000000000000008352820152838160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0165afa928315610699578093610664575b505051908152f35b909192508382813d8311610692575b61067d8183610f65565b8101031261068f57505190838061065c565b80fd5b503d610673565b8251903d90823e3d90fd5b5090517f089b2f6f000000000000000000000000000000000000000000000000000000008152fd5b8280fd5b919050346106cc57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc5761072a7f5665467873566f74696e6744656c65676174696f6e0000000000000000000015610fa6565b926107547f310000000000000000000000000000000000000000000000000000000000000161111c565b908251926020928385019585871067ffffffffffffffff881117610815575092806107cb8388966107be998b9996528686528151998a997f0f000000000000000000000000000000000000000000000000000000000000008b5260e0868c015260e08b0190610e1d565b91898303908a0152610e1d565b924660608801523060808801528460a088015286840360c088015251928381520193925b8281106107fe57505050500390f35b8351855286955093810193928101926001016107ef565b8360416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b82843461068f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261068f57610879610df5565b9273ffffffffffffffffffffffffffffffffffffffff6024359416825260205281812090815484101561068f57506080926108b391610e7b565b509060018254920154908051926fffffffffffffffffffffffffffffffff908181168552851c6020850152821690830152821c6060820152f35b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157908160c09273ffffffffffffffffffffffffffffffffffffffff9283610942610df5565b1681526003602052209060018254920154918151938116845265ffffffffffff8160a01c16602085015260d01c908301526bffffffffffffffffffffffff80821660608401528160601c166080830152821c60a0820152f35b833461068f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261068f5761037c6109d6610df5565b33611dc6565b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020918173ffffffffffffffffffffffffffffffffffffffff9182610a30610df5565b168152600385522054169051908152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0168152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101515760209051630784ce008152f35b50503461015157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151578051610b6891610b2c82610f49565b600e82527f6d6f64653d74696d657374616d70000000000000000000000000000000000000602083015251918291602083526020830190610e1d565b0390f35b5050346101515760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015157610b6890610bb1610bac610df5565b6112b7565b90519182918291909160606080820193816fffffffffffffffffffffffffffffffff91828151168552826020820151166020860152826040820151166040860152015116910152565b82843461068f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261068f5750610c33610df5565b916024359042821015610c555750826101a8826101a26101ae946020976118bc565b82517f47860b97000000000000000000000000000000000000000000000000000000008152fd5b9050346106cc57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc57610cb4610df5565b906024359163ffffffff83168303610d04579183610b6895610cfe9373ffffffffffffffffffffffffffffffffffffffff610bb196610cf16111ef565b5016825260205220610e7b565b50611214565b8480fd5b50503461015157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610151578060609273ffffffffffffffffffffffffffffffffffffffff610d59610df5565b168152600560205281812060243582526020522054908051916bffffffffffffffffffffffff808216845281851c16602084015260c01c90820152f35b849084346106cc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106cc5760209273ffffffffffffffffffffffffffffffffffffffff610de8610df5565b1681526002845220548152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610e1857565b600080fd5b919082519283825260005b848110610e675750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610e28565b8054821015610e975760005260206000209060011b0190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080810190811067ffffffffffffffff821117610ee257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60c0810190811067ffffffffffffffff821117610ee257604052565b6060810190811067ffffffffffffffff821117610ee257604052565b6040810190811067ffffffffffffffff821117610ee257604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610ee257604052565b60ff8114610ffc5760ff811690601f8211610fd25760405191610fc883610f49565b8252602082015290565b60046040517fb3512b0c000000000000000000000000000000000000000000000000000000008152fd5b506040516000805490600182811c90808416938415611112575b60209485841081146110e557838752869493929181156110a6575060011461104a575b505061104792500382610f65565b90565b60008080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56395935091905b81831061108e57505061104793508201013880611039565b85548784018501529485019486945091830191611076565b90506110479593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611039565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b91607f1691611016565b60ff811461113e5760ff811690601f8211610fd25760405191610fc883610f49565b50604051600060019081549182811c908084169384156111e5575b60209485841081146110e557838752869493929181156110a6575060011461118957505061104792500382610f65565b60008181527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf695935091905b8183106111cd57505061104793508201013880611039565b855487840185015294850194869450918301916111b5565b91607f1691611159565b604051906111fc82610ec6565b60006060838281528260208201528260408201520152565b9060405161122181610ec6565b6060819360018154916fffffffffffffffffffffffffffffffff92838116865260801c60208601520154908116604084015260801c910152565b8181029291811591840414171561126e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820180921161126e57565b9190820391821161126e57565b6112bf6111ef565b90600073ffffffffffffffffffffffffffffffffffffffff82168152600460205260408120906201518091824204928084029380850482149015171561142b5783018093116113fe5780549182156113c9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019283116113d1575061134991610cfe91610e7b565b6fffffffffffffffffffffffffffffffff92836060830151168381146113c95783839161137593612e6b565b91909582156113bf5750908460208180809581885116031698816040880151160316940151160316604051946113aa86610ec6565b85526020850152604084015216606082015290565b9550505050505090565b505050505090565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b906114c557815160208301516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffffffffffff00000000000000000000000000000000608092831b8116919091178455604085015160609095015190911b16921691909117600190910155565b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b9081549168010000000000000000831015610ee2578261151c9160016114c395018155610e7b565b90611458565b91909160009073ffffffffffffffffffffffffffffffffffffffff8116825260049384602052604083206115546111ef565b81546201518092838504938085029480860482149015171561179e57821580159190611865577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401848111611839576115b060019185610e7b565b50015460801c955b6fffffffffffffffffffffffffffffffff968716908082111561182f576115de916112aa565b04905b806117fd575b156117f6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018381116117ca5790611620916112aa565b82811061175b5750816116f0575050925b816060850151169081156116e65761167661168593602061165b8888611669999761167f97612e6b565b9491848b9a929a51166112aa565b978360408b0151166112aa565b970151166112aa565b9361125b565b808211156116de57611696916112aa565b915b826003029260038404036116b2575061104792935061129d565b806011867f4e487b71000000000000000000000000000000000000000000000000000000006024945252fd5b505081611698565b5093955050505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201925090821161172f5761172991610cfe91610e7b565b92611631565b60248660118a7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b9160019061176f818518831c82861661129d565b91878161177c8587610e7b565b50015460801c111561179057505091611620565b909350810180911115611620575b60248860118c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60248960118d7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5086611620565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018381116117ca5781106115e7565b50505087906115e1565b60248a60118e7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b88956115b8565b519081600f0b8203610e1857565b90816040910312610e185760405190604082019082821067ffffffffffffffff831117610ee2576020916040526118b08161186c565b83520151602082015290565b9073ffffffffffffffffffffffffffffffffffffffff90817f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b016906040918251937fcbf9fe5f00000000000000000000000000000000000000000000000000000000855285168060048601528385602481855afa948515611a5f57600095611a30575b50826020809601511115611a25576000526003845265ffffffffffff836000205460a01c168015908115611a1b575b5061197e575b5050505050600090565b91517efdd58e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff94909416600485015260248401528190839060449082905afa9182916000936119ea575b50506110475780808080611974565b8181949293943d8311611a14575b611a028183610f65565b8101031261068f5750519038806119db565b503d6119f8565b905082103861196e565b505050505050600090565b611a51919550843d8611611a58575b611a498183610f65565b81019061187a565b933861193f565b503d611a3f565b84513d6000823e3d90fd5b6005811015611bd45780611a7b5750565b60018103611ae15760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152fd5b60028103611b475760646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152fd5b600314611b5057565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9291907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311611c935791608094939160ff602094604051948552168484015260408301526060820152600093849182805260015afa15611c8657815173ffffffffffffffffffffffffffffffffffffffff811615611c80579190565b50600190565b50604051903d90823e3d90fd5b50505050600090600390565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b83c4f3a6729fb7d5e19b720092162df439f56716301480611d9d575b15611d07577f7fe24e004d050b0dec799c65dff98542560cc11245f76821cd43f8c89886cab990565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fa07003d5f6686ee8309a11d6a6d07ebad10ea48ba10f95597658cd093105acf560408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152611d9781610f11565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000014614611cde565b73ffffffffffffffffffffffffffffffffffffffff821615612ac45773ffffffffffffffffffffffffffffffffffffffff81166000526003602052604060002091600160405193611e1685610f11565b805473ffffffffffffffffffffffffffffffffffffffff8116865265ffffffffffff8160a01c16602087015260d01c604086015201546bffffffffffffffffffffffff811660608501526bffffffffffffffffffffffff8160601c16608085015260c01c60a08401526201518090814204918083029280840482149015171561126e57808301831161126e57611eaa6111ef565b906040517fcbf9fe5f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616600482015260408160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0165afa80156129e657602091600091612aa5575b500151818501811115612a7b576040517f010ae75700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8716600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0165afa9081156129e657600091612a49575b506040517f28d09d4700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff881660048201526024810182905260a0818060448101038173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0165afa80156129e6576000916000906000926129f2575b506040517fda020a1800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b166004820152602481019490945260208480604481015b038173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0165afa9384156129e6576000946129aa575b509161215494612149926121326101a895600f0b612aee565b60208a015260408901526060880152600f0b612aee565b91602086015161125b565b825273ffffffffffffffffffffffffffffffffffffffff86511680612689575b5073ffffffffffffffffffffffffffffffffffffffff83166000526004602052604060002080549081156000146125fb579267ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff968796946125c6946123c289986040516121dd81610ec6565b60008152600060208201526000604082015260006060820152905b6122136122078688018c6118bc565b6101a88789018d611522565b938b8b166000526005602052604060002060608a01516000526020526123a060406000206bffffffffffffffffffffffff8b8180604080519561225587610f2d565b54938285168752828560601c1660208801528460c01c828801528280825116818716011687528f806020830151168660c01c0116828801520151169160601c16011660208201528d8d166000526005602052604060002060608c015160005260205289604080600020926bffffffffffffffffffffffff8151167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008554161784556123566bffffffffffffffffffffffff60208301511685907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b0151825477ffffffffffffffffffffffffffffffffffffffffffffffff16911660c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016179055565b6123bc898c815160208301519060408b8d019401519288612cff565b91612def565b6123dd6123d1838501896118bc565b6101a88486018a611522565b60405191825260208201527fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724604089891692a260208b015165ffffffffffff1691826125f35765ffffffffffff92500116915b61257d6bffffffffffffffffffffffff65ffffffffffff606084015116928181511685602084604085015116930151169465ffffffffffff604051986124758a610f11565b8c8c168a52166020890152604088015260608701526080860190815260a08601938452888c166000526003602052816060600160406000208c8a511679ffffffffffff000000000000000000000000000000000000000060208c015160a01b16907fffffffffffff000000000000000000000000000000000000000000000000000060408d015160d01b16911717815501970151167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000875416178655511684907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b51825477ffffffffffffffffffffffffffffffffffffffffffffffff16911660c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016179055565b1693511691167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a4565b505091612430565b94939192817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81011161126e5767ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9695879695846123c28998612683610cfe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6125c69a0183610e7b565b906121f8565b60005260046020526040600020805490817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81011161126e576127ab906126f5610cfe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff850183610e7b565b9061272a73ffffffffffffffffffffffffffffffffffffffff8b51166101a8612720888c01836118bc565b91888c0190611522565b9385890165ffffffffffff60408d01511611612813575b6123bc8973ffffffffffffffffffffffffffffffffffffffff8d51168d6bffffffffffffffffffffffff60608201511667ffffffffffffffff60a083015116908b65ffffffffffff60406bffffffffffffffffffffffff6080870151169501511695019389612b57565b7fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724604073ffffffffffffffffffffffffffffffffffffffff895116926128026127f6868a01866118bc565b6101a8878b0187611522565b82519182526020820152a238612174565b73ffffffffffffffffffffffffffffffffffffffff8b51166000526005602052604060002065ffffffffffff60408d0151166000526020526129a560406000206bffffffffffffffffffffffff8d818060806040519561287287610f2d565b54938285168752828560601c1660208801528460c01c604088015282806060830151168187160316875267ffffffffffffffff8060a0830151168660c01c031660408801520151169160601c160316602082015273ffffffffffffffffffffffffffffffffffffffff8d511660005260056020528c65ffffffffffff6040806000209201511660005260205267ffffffffffffffff604080600020926bffffffffffffffffffffffff8151167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008554161784556123566bffffffffffffffffffffffff60208301511685907fffffffffffffffff000000000000000000000000ffffffffffffffffffffffff77ffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b612741565b91929093506020823d6020116129de575b816129c860209383610f65565b81010312610e1857905192909190612154612119565b3d91506129bb565b6040513d6000823e3d90fd5b9250505060a0813d60a011612a41575b81612a0f60a09383610f65565b81010312610e18576120cf91612a248261186c565b60206080612a3382860161186c565b94015191939192945061207b565b3d9150612a02565b90506020813d602011612a73575b81612a6460209383610f65565b81010312610e18575138611fda565b3d9150612a57565b60046040517f14271110000000000000000000000000000000000000000000000000000000008152fd5b612abe915060403d604011611a5857611a498183610f65565b38611f3d565b60046040517f3252b88f000000000000000000000000000000000000000000000000000000008152fd5b60008112612af95790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152fd5b9196959492612b646111ef565b976fffffffffffffffffffffffffffffffff60608501511615612cbc57886fffffffffffffffffffffffffffffffff606086015116968760608301526fffffffffffffffffffffffffffffffff865116928383526fffffffffffffffffffffffffffffffff6040880151168060408501526fffffffffffffffffffffffffffffffff60208901511694602085019b868d526fffffffffffffffffffffffffffffffff60608b01511610612c81575b50505050505050828403612c28575b5050505050565b6fffffffffffffffffffffffffffffffff838180612c4d819896829883988498612e6b565b9790941660608d015216818b5116031689521681604089015116031660408701521681835116031690523880808080612c21565b6fffffffffffffffffffffffffffffffff92831690038216909352938416909103831660408b01528216900316855238808881808080612c12565b9697509150506fffffffffffffffffffffffffffffffff8094508092938160405197612ce789610ec6565b16875216602086015216604084015216606082015290565b90959495929192612d0e6111ef565b9660608301946fffffffffffffffffffffffffffffffff958681511615612dd45784939291878b968180809551169960608a01998b8b528280855116808352818060208160408a0151169889604088015201511698160116905216011660408c01528160208c01991601168752808503612d8c575b50505050505050565b858080612d9f8198968583988498612e6b565b989192909516905216818b51160316895216816040890151160316604087015216818351160316905238808080808080612d83565b509697509394858094935080925060405197612ce789610ec6565b90928315159081612e42575b5015612e38577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830192831161126e576114c39261151c91610e7b565b6114c392506114f4565b606091506fffffffffffffffffffffffffffffffff918291015116906060840151161438612dfb565b9091600092600092838093630784ce0084018111600014612eb457505050505050506fffffffffffffffffffffffffffffffff9182825116926020816040850151169301511690565b9193959794965073ffffffffffffffffffffffffffffffffffffffff62093a808080950402840194168152602090600582526040908181205b84871115612efe5750505050505050565b90919293948698999a8197845282865284808520815190612f1e82610f2d565b54926bffffffffffffffffffffffff91828516928382528560601c1694858b83015260c01c9384910152019c019a0198019493929190959495612eed56fea164736f6c6343000813000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000155665467873566f74696e6744656c65676174696f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : veFxs (address): 0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0
Arg [1] : name (string): VeFxsVotingDelegation
Arg [2] : version (string): 1
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000c8418af6358ffdda74e09ca9cc3fe03ca6adc5b0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [4] : 5665467873566f74696e6744656c65676174696f6e0000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 3100000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.