Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
- Contract name:
- VotingEscrow
- Optimization enabled
- true
- Compiler version
- v0.8.4+commit.c7e474f2
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2021-11-11T14:19:57.752552Z
Constructor Arguments
000000000000000000000000428d561f82bbb9322e5a634490722f26714d4dca0000000000000000000000007593e8fc59cb7fb3839a2b4815576c68b3df23ff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012566f74652d657363726f77656420414d5054000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067665414d50540000000000000000000000000000000000000000000000000000
Arg [0] (address) : 0x428d561f82bbb9322e5a634490722f26714d4dca
Arg [1] (address) : 0x7593e8fc59cb7fb3839a2b4815576c68b3df23ff
Arg [2] (string) : Vote-escrowed AMPT
Arg [3] (string) : veAMPT
Contract source code
// SPDX-License-Identifier: MIT // File: contracts/utils/SmartWalletWhitelist.sol pragma solidity ^0.8.0; /** * @dev Interface for checking whether address belongs to a whitelisted type of a smart wallet. * When new types are added - the whole contract is changed * The check() method is modifying to be able to use caching * for individual wallet addresses */ interface SmartWalletChecker { function check(address) external view returns (bool); } contract SmartWalletWhitelist { address public admin; address public checker; mapping(address => bool) public wallets; event ApproveWallet(address); event RevokeWallet(address); event CheckerChanged(address oldChecker, address newChecker); constructor() { admin = msg.sender; } modifier onlyAdmin() { require(msg.sender == admin); _; } function setChecker(address _checker) external onlyAdmin { address currentChecker = checker; require(_checker == address(0), "Can't set zero address"); emit CheckerChanged(currentChecker, checker); checker = _checker; } function approveWallet(address _wallet) external onlyAdmin { require(_wallet != address(0), "Can't approve zero address"); wallets[_wallet] = true; emit ApproveWallet(_wallet); } function revokeWallet(address _wallet) external onlyAdmin { require(_wallet != address(0), "Can't revoke zero address"); wallets[_wallet] = false; emit RevokeWallet(_wallet); } function check(address _wallet) external view returns (bool) { if (wallets[_wallet]) { return true; } else if (checker != address(0)) { return SmartWalletChecker(checker).check(_wallet); } return false; } } // File: contracts/Governance/IAMPT.sol pragma solidity ^0.8.0; interface IAMPT { function balanceOf(address account) external view returns (uint256); function totalSupply() external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } // File: contracts/Governance/VotingEscrow.sol pragma solidity 0.8.4; /* # Voting escrow to have time-weighted votes # Votes have a weight depending on time, so that users are committed # to the future of (whatever they are voting for). # The weight in this implementation is linear, and lock cannot be more than maxtime: # w ^ # 1 + / # | / # | / # | / # |/ # 0 +--------+------> time # maxtime (4 years?) */ contract VotingEscrow { struct Point { int256 bias; int256 slope; uint256 ts; uint256 block; } struct Balance { uint256 amount; uint256 end; } enum Action { DEPOSIT_FOR_TYPE, CREATE_LOCK_TYPE, INCREASE_LOCK_AMOUNT, INCREASE_UNLOCK_TIME } /// @notice EIP-20 token name for this token string private _name; /// @notice EIP-20 token symbol for this token string private _symbol; bool private _entered; address public admin; IAMPT public amptToken; SmartWalletChecker public smartWalletChecker; mapping(address => Balance) private _lockedBalances; mapping(address => Balance) private _operationBalances; uint256 private _totalSupply; uint256 public epoch; mapping(uint256 => Point) public pointHistory; /// @dev A record of each account's delegate mapping (address => address) public delegates; /// @notice A record of states for signing / validating signatures mapping (address => uint256) public nonces; /// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); /// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); uint256 internal constant WEEK = 604800; // 7 * 24 * 3600; uint256 internal constant MAXCAP = 126144000; // 4 * 365 * 24 * 3600; mapping(address => mapping(uint256 => Point)) public userPointHistory; mapping(address => uint256) public userPointEpoch; mapping(uint256 => int256) public slopeChanges; event Deposited(address indexed provider, uint256 value, uint256 indexed lockTime, uint256 actionType); event Withdrawn(address indexed provider, uint256 value); /// @notice An event that's emitted when an account changes their delegate event DelegateChanged(address indexed delegator, address indexed toDelegate); /// @notice An event that's emitted when an smart wallet Checker is changed event SmartWalletCheckedChanged(address oldChecked, address newChecker); /** * @notice Contract constructor * @param amptToken_ `AMPT` token address * @param smartWalletChecker_ SmartWalletChecker contract address * @param name_ Token name * @param symbol_ Token symbol */ constructor(IAMPT amptToken_, SmartWalletChecker smartWalletChecker_, string memory name_, string memory symbol_) { amptToken = amptToken_; _name = name_; _symbol = symbol_; admin = msg.sender; smartWalletChecker = smartWalletChecker_; pointHistory[0].block = getBlockNumber(); pointHistory[0].ts = getBlockTimestamp(); _entered = false; } modifier onlyAllowed(address addr) { if (addr != tx.origin) { require(smartWalletChecker.check(addr), "Smart contract depositors not allowed"); } _; } modifier nonReentrant() { require(!_entered, "reentrant call"); _entered = true; _; _entered = false; } /** * @dev Returns the name of the token. */ function name() external view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external pure returns (uint8) { return 18; } /** * @dev Returns the amount of locked tokens in existence. */ function totalSupply() external view returns (uint256) { return _totalSupply; } /** * @notice Calculate total voting power * @return Total voting power */ function votePower() external view returns (uint256) { return _supplyAt(getBlockTimestamp()); } /** * @notice Calculate total voting power at some point in the past * @param block_ Block to calculate the total voting power at * @return Total voting power ar `block` */ function votePowerAt(uint256 block_) external view returns (uint256) { uint256 currentTimestamp = getBlockTimestamp(); uint256 currentBlock = getBlockNumber(); require(currentBlock >= block_, "Block must be in the past"); uint256 _targetEpoch = findBlockEpoch(block_, epoch); Point memory point = pointHistory[_targetEpoch]; uint256 dt = 0; if (epoch > _targetEpoch) { Point memory nextPoint = pointHistory[_targetEpoch + 1]; if (point.block != nextPoint.block) { dt = (block_ - point.block) * (nextPoint.ts - point.ts) / (nextPoint.block - point.block); } } else if (point.block != currentBlock) { dt = (block_ - point.block) * (currentTimestamp - point.ts) / (currentBlock - point.block); } return _supplyAt(point.ts + dt); } /** * @notice Calculate total voting power at some point in the past * @param timestamp Time to calculate the total voting power at * @return Total voting power at that time */ function _supplyAt(uint256 timestamp) internal view returns (uint256) { Point memory point = pointHistory[epoch]; uint256 timeIndex = point.ts * WEEK / WEEK; for(int i=0; i <= 255; i++) { timeIndex += WEEK; int256 dSlope = 0; if (timeIndex > timestamp) { timeIndex = timestamp; } else { dSlope = slopeChanges[timeIndex]; } point.bias -= point.slope * int256(timeIndex - point.ts); if (timeIndex == timestamp) { break; } point.slope += dSlope; point.ts = timeIndex; } if (point.bias < 0) { point.bias = 0; } return uint256(point.bias); } /** * @notice Binary search to estimate timestamp for block number * @param block_ Block to find * @param epoch_ Don't go beyond this epoch * @return Approximate timestamp for block */ function findBlockEpoch(uint256 block_, uint256 epoch_) internal view returns (uint256) { uint256 _min = 0; uint256 _max = epoch_; for(int i=0; i <= 128; i++) { if (_min >= _max) break; uint256 _mid = (_min + _max + 1) / 2; if (pointHistory[_mid].block <= block_) { _min = _mid; } else { _max = _mid - 1; } } return _min; } /** * @notice Record global data to checkpoint */ function checkpoint() external { _checkpoint(address(0), Balance(0,0), Balance(0,0)); } /** * @notice Get the current voting power for `msg.sender` * @param addr User wallet address * @return User voting power */ function balanceOf(address addr) external view returns (uint256) { uint256 _epoch = userPointEpoch[addr]; uint256 currentTimestamp = getBlockTimestamp(); if (_epoch == 0) { return 0; } else { Point memory lastPoint = userPointHistory[addr][_epoch]; lastPoint.bias -= lastPoint.slope * int256(currentTimestamp - lastPoint.ts); if (lastPoint.bias < 0) { lastPoint.bias = 0; } return uint256(lastPoint.bias); } } /** * @dev Returns the amount of tokens owner by `addr`. */ function locked(address addr) external view returns (Balance memory) { return _lockedBalances[addr]; } /** * @dev Returns the amount of tokens owner by `addr` used for calculating vote power. */ function operationLocked(address addr) external view returns (Balance memory) { return _operationBalances[addr]; } function changeSmartWalletChecker(SmartWalletChecker newSmartWalletChecker) external { SmartWalletChecker currentWalletChecker = smartWalletChecker; require(msg.sender == admin, "Only admin can change smart wallet checker"); require(newSmartWalletChecker != currentWalletChecker, "New smart wallet checker is the same as the old one"); smartWalletChecker = newSmartWalletChecker; emit SmartWalletCheckedChanged(address(currentWalletChecker), address(newSmartWalletChecker)); } /** * @notice Deposit `value` tokens for `msg.sender` and lock until `unlockTime` * @param value Amount to deposit * @param unlockTime Epoch time when tokens unlock, rounded down to whole weeks */ function createLock(uint256 value, uint256 unlockTime) external nonReentrant onlyAllowed(msg.sender) { require(value > 0, "Value must be greater than 0"); Balance storage balance = _lockedBalances[msg.sender]; require(balance.amount == 0, "Withdraw old tokens first"); uint currentTimestamp = getBlockTimestamp(); require(unlockTime > currentTimestamp, "Unlock time must be in the future"); require(currentTimestamp + MAXCAP >= unlockTime, "Voting lock can be 4 years max"); _depositFor(msg.sender, value, unlockTime, uint256(Action.CREATE_LOCK_TYPE)); } /** * @notice Deposit `value` additional tokens for `msg.sender` without modifying the unlock time * @param value Amount of tokens to deposit and add to the lock */ function increaseLockAmount(uint256 value) external nonReentrant onlyAllowed(msg.sender) { require(value > 0, "Value must be greater than 0"); Balance storage balance = _lockedBalances[msg.sender]; require(balance.amount > 0, "No existing lock found"); require(balance.end > getBlockTimestamp(), "Cannot add to expired lock. Withdraw"); _depositFor(msg.sender, value, 0, uint256(Action.INCREASE_LOCK_AMOUNT)); } /** * @notice Extend the unlock time for `msg.sender` to `unlockTime` * @param newLockTime New epoch time for unlocking */ function increaseLockTime(uint256 newLockTime) external nonReentrant onlyAllowed(msg.sender) { uint256 currentTimestamp = getBlockTimestamp(); require(currentTimestamp + MAXCAP >= newLockTime, "Voting lock can be 4 years max"); Balance storage balance = _lockedBalances[msg.sender]; require(balance.amount > 0, "Nothing is locked"); require(newLockTime > balance.end, "Lock time must be greater"); require(balance.end > currentTimestamp, "Lock expired"); _depositFor(msg.sender, 0, newLockTime, uint256(Action.INCREASE_UNLOCK_TIME)); } /** * @notice Withdraw all tokens for `msg.sender` * @dev Only possible if the lock has expired */ function withdraw() external nonReentrant { Balance storage _locked = _lockedBalances[msg.sender]; Balance storage _operationLocked = _operationBalances[msg.sender]; require(getBlockTimestamp() >= _locked.end, "Cannot withdraw before lock expires"); uint256 value = _locked.amount; Balance memory _oldOperationLocked = _operationLocked; _totalSupply -= value; _locked.amount = 0; _operationLocked.amount = 0; _locked.end = 0; _operationLocked.end = 0; _checkpoint(msg.sender, _oldOperationLocked, _operationLocked); emit Withdrawn(msg.sender, value); assert(amptToken.transfer(msg.sender, value)); } /** * @notice Deposit `value` tokens for `depositer` and add to the lock * @dev Anyone (even a smart contract) can deposit for someone else, but cannot extend their locktime and deposit for a brand new use * @param depositer User's wallet address * @param value Amount to add to user's lock */ function depositFor(address depositer, uint256 value) external nonReentrant { Balance storage _locked = _lockedBalances[depositer]; require(value > 0, "Value must be greater than 0"); require(_locked.amount > 0, "No existing lock found"); require(_locked.end > getBlockTimestamp(), "Cannot add to expired lock. Withdraw"); _depositFor(depositer, value, 0, uint256(Action.DEPOSIT_FOR_TYPE)); } /** * @notice Delegate votes from `msg.sender` to `delegatee` * @param delegatee The address to delegate votes to */ function delegate(address delegatee) external onlyAllowed(msg.sender) { require(msg.sender != delegatee, "Cannot delegate to self"); require(msg.sender != address(0), "Cannot delegate from the zero address"); require(delegatee != address(0), "Cannot delegate to the zero address"); _delegate(msg.sender, delegatee); } /** * @notice Delegates votes from signatory to `delegatee` * @param delegatee The address to delegate votes to * @param nonce The contract state required to match the signature * @param expiry The time at which to expire the signature * @param v The recovery byte of the signature * @param r Half of the ECDSA signature pair * @param s Half of the ECDSA signature pair */ function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external { bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(_name)), getChainId(), address(this))); bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "delegateBySig: invalid signature"); require(signatory != msg.sender, "delegateBySig: cannot delegate to self"); require(nonce == nonces[signatory], "delegateBySig: invalid nonce"); nonces[signatory]++; require(getBlockTimestamp() <= expiry, "delegateBySig: signature expired"); _delegate(signatory, delegatee); } /** * @notice Deposit and lock tokens for a user * @param depositer User's wallet address * @param value Amount to add to user's lock * @param unlockTime New time when to unlock the tokens, or 0 if unchanged * @param actionType Type of action to log */ function _depositFor(address depositer, uint256 value, uint256 unlockTime, uint256 actionType) internal { Balance storage _locked = _lockedBalances[depositer]; Balance storage _operationLocked = _operationBalances[depositer]; Balance memory _oldOperationLocked = _operationLocked; _totalSupply += value; _locked.amount += value; if (unlockTime != 0) { _locked.end = unlockTime; } _operationLocked.amount += value; if (unlockTime != 0) { _operationLocked.end = unlockTime; } _checkpoint(depositer, _oldOperationLocked, _operationLocked); emit Deposited(depositer, value, _locked.end, actionType); if(value != 0) { assert(amptToken.transferFrom(depositer, address(this), value)); } } function _delegate(address delegator, address delegatee) internal { Balance storage _sourceBalance = _operationBalances[delegator]; Balance memory _oldSourceBalance = _sourceBalance; require(_sourceBalance.amount > 0, "No existing lock found"); Balance storage _destinationBalance = _operationBalances[delegatee]; Balance memory _oldDestinationBalance = _destinationBalance; delegates[delegator] = delegatee; emit DelegateChanged(delegator, delegatee); _sourceBalance.amount = 0; /// @dev The balance.end should be intact for the future deposits _checkpoint(delegator, _oldSourceBalance, _sourceBalance); _destinationBalance.amount += _oldSourceBalance.amount; if(_oldDestinationBalance.end == 0) { _destinationBalance.end = _oldSourceBalance.end; } _checkpoint(delegatee, _oldDestinationBalance, _destinationBalance); } struct CheckPointVars { int256 oldDslope; int256 newDslope; uint256 currentEpoch; uint256 currentBlock; uint256 currentTimestamp; uint256 currentUserEpoch; } /** * @notice Record global and per-user data to checkpoint * @param addr User's wallet address. No user checkpoint if 0x0 * @param oldLocked Previous locked amount / end lock time for the user * @param newLocked New locked amount / end lock time for the user */ function _checkpoint(address addr, Balance memory oldLocked, Balance memory newLocked) internal { Point memory _userPointOld = Point(0, 0, 0, 0); Point memory _userPointNew = Point(0, 0, 0, 0); CheckPointVars memory _checkpointVars = CheckPointVars( 0, 0, epoch, getBlockNumber(), getBlockTimestamp(), userPointEpoch[addr] ); if (addr != address(0)) { if (oldLocked.end > _checkpointVars.currentTimestamp && oldLocked.amount > 0) { _userPointOld.slope = int256(oldLocked.amount / MAXCAP); _userPointOld.bias = _userPointOld.slope * int256(oldLocked.end - _checkpointVars.currentTimestamp); } if (newLocked.end > _checkpointVars.currentTimestamp && newLocked.amount > 0) { _userPointNew.slope = int256(newLocked.amount / MAXCAP); _userPointNew.bias = _userPointNew.slope * int256(newLocked.end - _checkpointVars.currentTimestamp); } _checkpointVars.oldDslope = slopeChanges[oldLocked.end]; if (newLocked.end != 0) { if (newLocked.end == oldLocked.end) { _checkpointVars.newDslope = _checkpointVars.oldDslope; } else { _checkpointVars.newDslope = slopeChanges[newLocked.end]; } } } Point memory lastPoint = Point(0, 0, _checkpointVars.currentTimestamp, _checkpointVars.currentBlock); if (_checkpointVars.currentEpoch > 0) { lastPoint = pointHistory[_checkpointVars.currentEpoch]; } uint lastCheckpoint = lastPoint.ts; Point memory initialLastPoint = lastPoint; uint256 blockSlope = 0; if (_checkpointVars.currentTimestamp > lastPoint.ts) { blockSlope = 1e18 * (_checkpointVars.currentBlock - lastPoint.block) / (_checkpointVars.currentTimestamp - lastPoint.ts); } uint256 timeIndex = lastCheckpoint * WEEK / WEEK; for (int256 i=0; i <= 255; i++) { timeIndex += WEEK; int256 dSlope = 0; if (timeIndex > _checkpointVars.currentTimestamp) { timeIndex = _checkpointVars.currentTimestamp; } else { dSlope = slopeChanges[timeIndex]; } lastPoint.bias -= lastPoint.slope * int256(timeIndex - lastCheckpoint); lastPoint.slope += dSlope; if (lastPoint.bias < 0) { lastPoint.bias = 0; } if (lastPoint.slope < 0) { lastPoint.slope = 0; } lastCheckpoint = timeIndex; lastPoint.ts = timeIndex; lastPoint.block = initialLastPoint.block + blockSlope * (timeIndex - initialLastPoint.ts) / 1e18; _checkpointVars.currentEpoch += 1; if (timeIndex == _checkpointVars.currentTimestamp) { lastPoint.block = _checkpointVars.currentBlock; break; } else { pointHistory[_checkpointVars.currentEpoch] = lastPoint; } } epoch = _checkpointVars.currentEpoch; if (addr != address(0)) { lastPoint.slope += (_userPointNew.slope - _userPointOld.slope); lastPoint.bias += (_userPointNew.bias - _userPointOld.bias); if (lastPoint.slope < 0) { lastPoint.slope = 0; } if (lastPoint.bias < 0) { lastPoint.bias = 0; } } pointHistory[_checkpointVars.currentEpoch] = lastPoint; if (addr != address(0)) { if (oldLocked.end > _checkpointVars.currentTimestamp) { _checkpointVars.oldDslope += _userPointOld.slope; if (newLocked.end == oldLocked.end) { _checkpointVars.oldDslope -= _userPointNew.slope; } slopeChanges[oldLocked.end] = _checkpointVars.oldDslope; } if (newLocked.end > _checkpointVars.currentTimestamp) { if (newLocked.end > oldLocked.end) { _checkpointVars.newDslope -= _userPointNew.slope; slopeChanges[newLocked.end] = _checkpointVars.newDslope; } } userPointEpoch[addr]++; _userPointNew.ts = _checkpointVars.currentTimestamp; _userPointNew.block = _checkpointVars.currentBlock; userPointHistory[addr][_checkpointVars.currentUserEpoch + 1] = _userPointNew; } } function getBlockNumber() public virtual view returns (uint256) { return block.number; } function getBlockTimestamp() public virtual view returns (uint256) { return block.timestamp; } function getChainId() internal view returns (uint256) { uint256 chainId; assembly { chainId := chainid() } return chainId; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"amptToken_","internalType":"contract IAMPT"},{"type":"address","name":"smartWalletChecker_","internalType":"contract SmartWalletChecker"},{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"}]},{"type":"event","name":"DelegateChanged","inputs":[{"type":"address","name":"delegator","internalType":"address","indexed":true},{"type":"address","name":"toDelegate","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Deposited","inputs":[{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"lockTime","internalType":"uint256","indexed":true},{"type":"uint256","name":"actionType","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SmartWalletCheckedChanged","inputs":[{"type":"address","name":"oldChecked","internalType":"address","indexed":false},{"type":"address","name":"newChecker","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Withdrawn","inputs":[{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DELEGATION_TYPEHASH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DOMAIN_TYPEHASH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"admin","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IAMPT"}],"name":"amptToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeSmartWalletChecker","inputs":[{"type":"address","name":"newSmartWalletChecker","internalType":"contract SmartWalletChecker"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"checkpoint","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createLock","inputs":[{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"unlockTime","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"delegate","inputs":[{"type":"address","name":"delegatee","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"delegateBySig","inputs":[{"type":"address","name":"delegatee","internalType":"address"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"uint256","name":"expiry","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"delegates","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"depositFor","inputs":[{"type":"address","name":"depositer","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"epoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBlockNumber","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBlockTimestamp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"increaseLockAmount","inputs":[{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"increaseLockTime","inputs":[{"type":"uint256","name":"newLockTime","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct VotingEscrow.Balance","components":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"end","internalType":"uint256"}]}],"name":"locked","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nonces","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct VotingEscrow.Balance","components":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"end","internalType":"uint256"}]}],"name":"operationLocked","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"bias","internalType":"int256"},{"type":"int256","name":"slope","internalType":"int256"},{"type":"uint256","name":"ts","internalType":"uint256"},{"type":"uint256","name":"block","internalType":"uint256"}],"name":"pointHistory","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"slopeChanges","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract SmartWalletChecker"}],"name":"smartWalletChecker","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"userPointEpoch","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"bias","internalType":"int256"},{"type":"int256","name":"slope","internalType":"int256"},{"type":"uint256","name":"ts","internalType":"uint256"},{"type":"uint256","name":"block","internalType":"uint256"}],"name":"userPointHistory","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"votePower","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"votePowerAt","inputs":[{"type":"uint256","name":"block_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]}]
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101f05760003560e01c8063796b89b91161010f578063b52c05fe116100a2578063e7a324dc11610071578063e7a324dc14610536578063f17c9d761461055d578063f52a36f714610565578063f851a4401461058557600080fd5b8063b52c05fe146104b3578063c2c4c5c1146104c6578063c3cda520146104ce578063cbf9fe5f146104e157600080fd5b806381fc83bb116100de57806381fc83bb1461044d5780638ad4c4471461046d578063900cf0cf146104a257806395d89b41146104ab57600080fd5b8063796b89b91461040157806379af55e4146104075780637df148541461041a5780637ecebe001461042d57600080fd5b80633e548fb111610187578063587cde1e11610156578063587cde1e146103875780635c19a95c146103c857806366e80391146103db57806370a08231146103ee57600080fd5b80633e548fb1146102eb578063403f44471461035b57806342cbb15c1461036e57806352ff9c691461037457600080fd5b80632f4f21e2116101c35780632f4f21e214610261578063313ce5671461027457806334d901a4146102835780633ccfd60b146102e357600080fd5b806306fdde03146101f55780630f7d84771461021357806318160ddd1461022857806320606b701461023a575b600080fd5b6101fd61059d565b60405161020a9190612485565b60405180910390f35b6102266102213660046122e3565b61062f565b005b6007545b60405190815260200161020a565b61022c7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b61022661026f366004612306565b61078b565b6040516012815260200161020a565b6102c3610291366004612306565b600c60209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b60408051948552602085019390935291830152606082015260800161020a565b61022661084d565b6103406102f93660046122e3565b6040805180820190915260008082526020820152506001600160a01b0316600090815260066020908152604091829020825180840190935280548352600101549082015290565b6040805182518152602092830151928101929092520161020a565b6102266103693660046123b1565b610a50565b4361022c565b61022c6103823660046123b1565b610ba1565b6103b06103953660046122e3565b600a602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161020a565b6102266103d63660046122e3565b610d77565b6003546103b0906001600160a01b031681565b61022c6103fc3660046122e3565b610f3e565b4261022c565b6102266104153660046123b1565b610ffb565b6004546103b0906001600160a01b031681565b61022c61043b3660046122e3565b600b6020526000908152604090205481565b61022c61045b3660046122e3565b600d6020526000908152604090205481565b6102c361047b3660046123b1565b60096020526000908152604090208054600182015460028301546003909301549192909184565b61022c60085481565b6101fd611220565b6102266104c13660046123c9565b61122f565b610226611455565b6102266104dc366004612331565b61148f565b6103406104ef3660046122e3565b6040805180820190915260008082526020820152506001600160a01b0316600090815260056020908152604091829020825180840190935280548352600101549082015290565b61022c7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b61022c6117c3565b61022c6105733660046123b1565b600e6020526000908152604090205481565b6002546103b09061010090046001600160a01b031681565b6060600080546105ac90612761565b80601f01602080910402602001604051908101604052809291908181526020018280546105d890612761565b80156106255780601f106105fa57610100808354040283529160200191610625565b820191906000526020600020905b81548152906001019060200180831161060857829003601f168201915b5050505050905090565b6004546002546001600160a01b03918216913361010090920416146106ae5760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c792061646d696e2063616e206368616e676520736d6172742077616c6c60448201526932ba1031b432b1b5b2b960b11b60648201526084015b60405180910390fd5b806001600160a01b0316826001600160a01b0316141561072c5760405162461bcd60e51b815260206004820152603360248201527f4e657720736d6172742077616c6c657420636865636b6572206973207468652060448201527273616d6520617320746865206f6c64206f6e6560681b60648201526084016106a5565b600480546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f1b0671b188e3268797d7e11abc653043fa932164a023cb5b6098a26f930fc64b910160405180910390a15050565b60025460ff16156107ae5760405162461bcd60e51b81526004016106a590612598565b6002805460ff191660011790556001600160a01b0382166000908152600560205260409020816107f05760405162461bcd60e51b81526004016106a590612561565b805461080e5760405162461bcd60e51b81526004016106a5906125c0565b428160010154116108315760405162461bcd60e51b81526004016106a59061251d565b61083e83836000806117d3565b50506002805460ff1916905550565b60025460ff16156108705760405162461bcd60e51b81526004016106a590612598565b6002805460ff191660019081179091553360009081526005602090815260408083206006909252909120918101549091906108a84290565b10156109025760405162461bcd60e51b815260206004820152602360248201527f43616e6e6f74207769746864726177206265666f7265206c6f636b206578706960448201526272657360e81b60648201526084016106a5565b81546040805180820190915282548152600183015460208201526007805483919060009061093190849061274a565b909155505060008085558084556001808601829055840181905560408051808201909152818152602081019190915261096d9033908390611996565b60405182815233907f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d59060200160405180910390a260035460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb90604401602060405180830381600087803b1580156109ee57600080fd5b505af1158015610a02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a269190612391565b610a4057634e487b7160e01b600052600160045260246000fd5b50506002805460ff191690555050565b60025460ff1615610a735760405162461bcd60e51b81526004016106a590612598565b6002805460ff1916600117905533328114610b235760048054604051631846d2f560e31b81526001600160a01b038481169382019390935291169063c23697a89060240160206040518083038186803b158015610acf57600080fd5b505afa158015610ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b079190612391565b610b235760405162461bcd60e51b81526004016106a5906124d8565b60008211610b435760405162461bcd60e51b81526004016106a590612561565b3360009081526005602052604090208054610b705760405162461bcd60e51b81526004016106a5906125c0565b42816001015411610b935760405162461bcd60e51b81526004016106a59061251d565b61083e3384600060026117d3565b6000424383811015610bf55760405162461bcd60e51b815260206004820152601960248201527f426c6f636b206d75737420626520696e2074686520706173740000000000000060448201526064016106a5565b6000610c0385600854611feb565b600081815260096020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015260085492935091831015610d05576000600981610c5f866001612631565b815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090508060600151836060015114610cff5782606001518160600151610cc5919061274a565b83604001518260400151610cd9919061274a565b6060850151610ce8908b61274a565b610cf291906126ec565b610cfc9190612649565b91505b50610d54565b83826060015114610d54576060820151610d1f908561274a565b6040830151610d2e908761274a565b6060840151610d3d908a61274a565b610d4791906126ec565b610d519190612649565b90505b610d6c818360400151610d679190612631565b612076565b979650505050505050565b33328114610e1a5760048054604051631846d2f560e31b81526001600160a01b038481169382019390935291169063c23697a89060240160206040518083038186803b158015610dc657600080fd5b505afa158015610dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfe9190612391565b610e1a5760405162461bcd60e51b81526004016106a5906124d8565b336001600160a01b0383161415610e735760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f742064656c656761746520746f2073656c6600000000000000000060448201526064016106a5565b33610ece5760405162461bcd60e51b815260206004820152602560248201527f43616e6e6f742064656c65676174652066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016106a5565b6001600160a01b038216610f305760405162461bcd60e51b815260206004820152602360248201527f43616e6e6f742064656c656761746520746f20746865207a65726f206164647260448201526265737360e81b60648201526084016106a5565b610f3a3383612196565b5050565b6001600160a01b0381166000908152600d60205260408120544281610f67575060009392505050565b6001600160a01b0384166000908152600c60209081526040808320858452825291829020825160808101845281548152600182015492810192909252600281015492820183905260030154606082015290610fc2908361274a565b8160200151610fd19190612669565b81518290610fe090839061270b565b905250805160001315610ff257600081525b51949350505050565b60025460ff161561101e5760405162461bcd60e51b81526004016106a590612598565b6002805460ff19166001179055333281146110ce5760048054604051631846d2f560e31b81526001600160a01b038481169382019390935291169063c23697a89060240160206040518083038186803b15801561107a57600080fd5b505afa15801561108e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b29190612391565b6110ce5760405162461bcd60e51b81526004016106a5906124d8565b42826110de630784ce0083612631565b101561112c5760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d6178000060448201526064016106a5565b336000908152600560205260409020805461117d5760405162461bcd60e51b8152602060048201526011602482015270139bdd1a1a5b99c81a5cc81b1bd8dad959607a1b60448201526064016106a5565b806001015484116111d05760405162461bcd60e51b815260206004820152601960248201527f4c6f636b2074696d65206d75737420626520677265617465720000000000000060448201526064016106a5565b818160010154116112125760405162461bcd60e51b815260206004820152600c60248201526b131bd8dac8195e1c1a5c995960a21b60448201526064016106a5565b610a403360008660036117d3565b6060600180546105ac90612761565b60025460ff16156112525760405162461bcd60e51b81526004016106a590612598565b6002805460ff19166001179055333281146113025760048054604051631846d2f560e31b81526001600160a01b038481169382019390935291169063c23697a89060240160206040518083038186803b1580156112ae57600080fd5b505afa1580156112c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e69190612391565b6113025760405162461bcd60e51b81526004016106a5906124d8565b600083116113225760405162461bcd60e51b81526004016106a590612561565b3360009081526005602052604090208054156113805760405162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e732066697273740000000000000060448201526064016106a5565b428084116113da5760405162461bcd60e51b815260206004820152602160248201527f556e6c6f636b2074696d65206d75737420626520696e207468652066757475726044820152606560f81b60648201526084016106a5565b836113e9630784ce0083612631565b10156114375760405162461bcd60e51b815260206004820152601e60248201527f566f74696e67206c6f636b2063616e2062652034207965617273206d6178000060448201526064016106a5565b61144433868660016117d3565b50506002805460ff19169055505050565b61148d600060405180604001604052806000815260200160008152506040518060400160405280600081526020016000815250611996565b565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86660006040516114c191906123ea565b60405180910390206114d04690565b60408051602080820195909552808201939093526060830191909152306080808401919091528151808403909101815260a0830182528051908401207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c08401526001600160a01b038b1660e084015261010083018a90526101208084018a90528251808503909101815261014084019092528151919093012061190160f01b610160830152610162820183905261018282018190529192506000906101a20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa1580156115fc573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661165f5760405162461bcd60e51b815260206004820181905260248201527f64656c656761746542795369673a20696e76616c6964207369676e617475726560448201526064016106a5565b6001600160a01b0381163314156116c75760405162461bcd60e51b815260206004820152602660248201527f64656c656761746542795369673a2063616e6e6f742064656c65676174652074604482015265379039b2b63360d11b60648201526084016106a5565b6001600160a01b0381166000908152600b6020526040902054891461172e5760405162461bcd60e51b815260206004820152601c60248201527f64656c656761746542795369673a20696e76616c6964206e6f6e63650000000060448201526064016106a5565b6001600160a01b0381166000908152600b60205260408120805491611752836127bc565b91905055508761175f4290565b11156117ad5760405162461bcd60e51b815260206004820181905260248201527f64656c656761746542795369673a207369676e6174757265206578706972656460448201526064016106a5565b6117b7818b612196565b50505050505050505050565b60006117ce42612076565b905090565b6001600160a01b0384166000908152600560209081526040808320600683528184208251808401909352805483526001810154938301939093526007805491948892611820908490612631565b9091555050825486908490600090611839908490612631565b9091555050841561184c57600183018590555b858260000160008282546118609190612631565b9091555050841561187357600182018590555b6040805180820190915282548152600183015460208201526118989088908390611996565b600183015460408051888152602081018790526001600160a01b038a16917f91ede45f04a37a7c170f5c1207df3b6bc748dc1e04ad5e917a241d0f52feada3910160405180910390a3851561198d576003546040516323b872dd60e01b81526001600160a01b03898116600483015230602483015260448201899052909116906323b872dd90606401602060405180830381600087803b15801561193b57600080fd5b505af115801561194f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119739190612391565b61198d57634e487b7160e01b600052600160045260246000fd5b50505050505050565b6000604051806080016040528060008152602001600081526020016000815260200160008152509050600060405180608001604052806000815260200160008152602001600081526020016000815250905060006040518060c0016040528060008152602001600081526020016008548152602001611a124390565b81526020014281526001600160a01b0388166000818152600d602090815260409091205492019190915290915015611b4f5780608001518560200151118015611a5b5750845115155b15611aa0578451611a7190630784ce0090612649565b83602001818152505080608001518560200151611a8e919061274a565b8360200151611a9d9190612669565b83525b80608001518460200151118015611ab75750835115155b15611afc578351611acd90630784ce0090612649565b82602001818152505080608001518460200151611aea919061274a565b8260200151611af99190612669565b82525b6020808601516000908152600e82526040902054825284015115611b4f57846020015184602001511415611b365780516020820152611b4f565b6020808501516000908152600e82526040902054908201525b60408051608080820183526000808352602083015283015181830152606080840151908201529082015115611bcb57600960008360400151815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090505b604081015160808301518290600090831015611c285783604001518560800151611bf5919061274a565b84606001518660600151611c09919061274a565b611c1b90670de0b6b3a76400006126ec565b611c259190612649565b90505b600062093a80611c3881866126ec565b611c429190612649565b905060005b60ff8113611db957611c5c62093a8083612631565b915060008760800151831115611c785787608001519250611c89565b506000828152600e60205260409020545b611c93868461274a565b8760200151611ca29190612669565b87518890611cb190839061270b565b905250602087018051829190611cc89083906125f0565b905250865160001315611cda57600087525b600087602001511215611cef57600060208801525b60408088018490528501519295508592670de0b6b3a764000090611d13908561274a565b611d1d90866126ec565b611d279190612649565b8560600151611d369190612631565b606088015260408801805160019190611d50908390612631565b9052506080880151831415611d6f575060608088015190870152611db9565b604080890151600090815260096020908152908290208951815590890151600182015590880151600282015560608801516003909101555080611db18161279c565b915050611c47565b5060408601516008556001600160a01b038b1615611e3d5787602001518760200151611de5919061270b565b85602001818151611df691906125f0565b90525087518751611e07919061270b565b85518690611e169083906125f0565b905250602085015160001315611e2e57600060208601525b845160001315611e3d57600085525b604080870151600090815260096020908152908290208751815590870151600182015590860151600282015560608601516003909101556001600160a01b038b1615611fde5785608001518a602001511115611eea57602088015186518790611ea79083906125f0565b9052506020808b0151908a01511415611ed257602087015186518790611ece90839061270b565b9052505b85516020808c01516000908152600e90915260409020555b856080015189602001511115611f3e57896020015189602001511115611f3e57866020015186602001818151611f20919061270b565b9052506020808701518a8201516000908152600e9092526040909120555b6001600160a01b038b166000908152600d60205260408120805491611f62836127bc565b90915550506080860151604080890191909152606080880151908901526001600160a01b038c166000908152600c60205290812060a0880151899290611fa9906001612631565b815260208082019290925260409081016000208351815591830151600183015582015160028201556060909101516003909101555b5050505050505050505050565b60008082815b6080811361206c578183106120055761206c565b600060026120138486612631565b61201e906001612631565b6120289190612649565b600081815260096020526040902060030154909150871061204b57809350612059565b61205660018261274a565b92505b50806120648161279c565b915050611ff1565b5090949350505050565b60085460009081526009602090815260408083208151608081018352815481526001820154938101939093526002810154918301829052600301546060830152829062093a80906120c89082906126ec565b6120d29190612649565b905060005b60ff811361217e576120ec62093a8083612631565b915060008583111561210057859250612111565b506000828152600e60205260409020545b6040840151612120908461274a565b846020015161212f9190612669565b8451859061213e90839061270b565b9052508286141561214f575061217e565b808460200181815161216191906125f0565b9052505060408301829052806121768161279c565b9150506120d7565b5081516000131561218e57600082525b505192915050565b6001600160a01b0382166000908152600660209081526040918290208251808401909352805480845260018201549284019290925291906121e95760405162461bcd60e51b81526004016106a5906125c0565b6001600160a01b0380841660008181526006602090815260408083208151808301835281548152600182015481850152958a16808552600a90935281842080546001600160a01b031916861790559051909493927fef9fc1dee6010109e6e3b21e51d44028e246dbad8a5a71ea192a30b19e1f457f91a3600080855560408051808201909152908152600185015460208201526122899087908590611996565b82518254839060009061229d908490612631565b909155505060208101516122b657602083015160018301555b6040805180820190915282548152600183015460208201526122db9086908390611996565b505050505050565b6000602082840312156122f4578081fd5b81356122ff816127e2565b9392505050565b60008060408385031215612318578081fd5b8235612323816127e2565b946020939093013593505050565b60008060008060008060c08789031215612349578182fd5b8635612354816127e2565b95506020870135945060408701359350606087013560ff81168114612377578283fd5b9598949750929560808101359460a0909101359350915050565b6000602082840312156123a2578081fd5b815180151581146122ff578182fd5b6000602082840312156123c2578081fd5b5035919050565b600080604083850312156123db578182fd5b50508035926020909101359150565b600080835482600182811c91508083168061240657607f831692505b602080841082141561242657634e487b7160e01b87526022600452602487fd5b81801561243a576001811461244b57612477565b60ff19861689528489019650612477565b60008a815260209020885b8681101561246f5781548b820152908501908301612456565b505084890196505b509498975050505050505050565b6000602080835283518082850152825b818110156124b157858101830151858201604001528201612495565b818111156124c25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526025908201527f536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c6040820152641b1bddd95960da1b606082015260800190565b60208082526024908201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686040820152636472617760e01b606082015260800190565b6020808252601c908201527f56616c7565206d7573742062652067726561746572207468616e203000000000604082015260600190565b6020808252600e908201526d1c99595b9d1c985b9d0818d85b1b60921b604082015260600190565b602080825260169082015275139bc8195e1a5cdd1a5b99c81b1bd8dac8199bdd5b9960521b604082015260600190565b600080821280156001600160ff1b0384900385131615612612576126126127cc565b600160ff1b839003841281161561262b5761262b6127cc565b50500190565b60008219821115612644576126446127cc565b500190565b60008261266457634e487b7160e01b81526012600452602481fd5b500490565b60006001600160ff1b038184138284138082168684048611161561268f5761268f6127cc565b600160ff1b848712828116878305891216156126ad576126ad6127cc565b8587129250878205871284841616156126c8576126c86127cc565b878505871281841616156126de576126de6127cc565b505050929093029392505050565b6000816000190483118215151615612706576127066127cc565b500290565b60008083128015600160ff1b850184121615612729576127296127cc565b6001600160ff1b0384018313811615612744576127446127cc565b50500390565b60008282101561275c5761275c6127cc565b500390565b600181811c9082168061277557607f821691505b6020821081141561279657634e487b7160e01b600052602260045260246000fd5b50919050565b60006001600160ff1b038214156127b5576127b56127cc565b5060010190565b60006000198214156127b5576127b55b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146127f757600080fd5b5056fea264697066735822122059c998ce0904b57ba0eaf8e4884620d0bfa6c1235f4610d86b5a64c379a36c4664736f6c63430008040033