Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Initialize | 19038377 | 397 days ago | IN | 0 ETH | 0.00462895 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Minimal Proxy Contract for 0x28ed637c5e3371c2678c2d346df04fb634ed832d
Contract Name:
Fundraising Gauge Fx
Compiler Version
vyper:0.3.1
Contract Source Code (Vyper language format)
# @version 0.3.1 """ @title Fundraising Gauge Fx @license MIT @author Aladdin DAO @notice Custom gauge directing emissions entirely to a specific address up to a maximum """ # Original idea and credit: # vefunder's Fundraising Gauge # https://github.com/vefunder/crvfunder/blob/main/contracts/FundraisingGaugeV1.vy # This contract is an almost-identical fork of the above contract # The address of CRV, GAUGE_CONTROLLER and MINTER are changed to corresponding one. interface CRV20: def rate() -> uint256: view def future_epoch_time_write() -> uint256: nonpayable interface GaugeController: def checkpoint_gauge(_gauge: address): nonpayable def gauge_relative_weight(_gauge: address, _time: uint256) -> uint256: view interface Minter: def minted(_user: address, _gauge: address) -> uint256: view event Checkpoint: _timestamp: uint256 _new_emissions: uint256 ADMIN: immutable(address) CRV: constant(address) = 0x365AccFCa291e7D3914637ABf1F7635dB165Bb09 GAUGE_CONTROLLER: constant(address) = 0xe60eB8098B34eD775ac44B1ddE864e098C6d7f37 MINTER: constant(address) = 0xC8b194925D55d5dE9555AD1db74c149329F71DeF WEEK: constant(uint256) = 604800 YEAR: constant(uint256) = 86400 * 365 # taken from CRV20 to allow calculating locally RATE_DENOMINATOR: constant(uint256) = 10 ** 18 RATE_REDUCTION_COEFFICIENT: constant(uint256) = 1111111111111111111 # 1/0.9 * 1e18 RATE_REDUCTION_TIME: constant(uint256) = YEAR # [uint216 inflation_rate][uint40 future_epoch_time] inflation_params: uint256 _is_killed: bool # _user => accumulated CRV integrate_fraction: public(HashMap[address, uint256]) last_checkpoint: public(uint256) receiver: public(address) max_emissions: public(uint256) @external def __init__(_admin: address): ADMIN = _admin # prevent initialization of the implementation contract self.last_checkpoint = MAX_UINT256 @internal def _user_checkpoint(_user: address) -> bool: # timestamp of the last checkpoint and start point for calculating new emissions prev_week_time: uint256 = self.last_checkpoint # if time has not advanced since the last checkpoint if block.timestamp == prev_week_time: return True # load the receiver receiver: address = self.receiver max_emissions: uint256 = self.max_emissions # initialize emission tracking variables receiver_emissions: uint256 = self.integrate_fraction[receiver] # if the maximum emissions has already been reached return early if receiver_emissions == max_emissions: return True # cache the receiver emissions var cached_receiver_emissions: uint256 = receiver_emissions # load and unpack inflation params inflation_params: uint256 = self.inflation_params rate: uint256 = shift(inflation_params, -40) future_epoch_time: uint256 = bitwise_and(inflation_params, 2 ** 40 - 1) # checkpoint the gauge filling in any missing gauge data across weeks GaugeController(GAUGE_CONTROLLER).checkpoint_gauge(self) # either the start of the next week or the current timestamp week_time: uint256 = min((prev_week_time + WEEK) / WEEK * WEEK, block.timestamp) # iterate 512 times at maximum for i in range(512): dt: uint256 = week_time - prev_week_time w: uint256 = GaugeController(GAUGE_CONTROLLER).gauge_relative_weight(self, prev_week_time / WEEK * WEEK) period_emissions: uint256 = 0 # if we cross over an inflation epoch, calculate the emissions using old and new rate if prev_week_time <= future_epoch_time and future_epoch_time < week_time: # calculate up to the epoch using the old rate period_emissions = rate * w * (future_epoch_time - prev_week_time) / 10 ** 18 # update the rate in memory rate = rate * RATE_DENOMINATOR / RATE_REDUCTION_COEFFICIENT # calculate using the new rate for the rest of the time period period_emissions += rate * w * (week_time - future_epoch_time) / 10 ** 18 # update the new future epoch time future_epoch_time += RATE_REDUCTION_TIME # update storage self.inflation_params = shift(rate, 40) + future_epoch_time else: period_emissions = rate * w * dt / 10 ** 18 # if adding period emissions is still below max emissions add to receiver if receiver_emissions + period_emissions <= max_emissions: receiver_emissions += period_emissions # else set received emissions at max and break else: receiver_emissions = max_emissions break if week_time == block.timestamp: break # update timestamps for tracking timedelta prev_week_time = week_time week_time = min(week_time + WEEK, block.timestamp) # this will only be the case if receiver got emissions if receiver_emissions != cached_receiver_emissions: self.integrate_fraction[receiver] = receiver_emissions self.last_checkpoint = block.timestamp log Checkpoint(block.timestamp, (receiver_emissions - cached_receiver_emissions)) return True @external def user_checkpoint(_user: address) -> bool: """ @notice Checkpoint the gauge updating total emissions @param _user The user to checkpoint and update accumulated emissions for """ return self._user_checkpoint(_user) @external def claimable_tokens_write(_user: address) -> uint256: """ @notice Get the number of claimable tokens per user @dev This function should be manually changed to "view" in the ABI @param _user The user to check claimable emissions of @return uint256 number of claimable tokens per user """ self._user_checkpoint(_user) return self.integrate_fraction[_user] - Minter(MINTER).minted(_user, self) @external def set_killed(_is_killed: bool): """ @notice Set the gauge status @dev Inflation params are modified accordingly to disable/enable emissions """ assert msg.sender == ADMIN if _is_killed: self._is_killed = True self.inflation_params = 0 else: self._is_killed = False self.inflation_params = shift(CRV20(CRV).rate(), 40) + CRV20(CRV).future_epoch_time_write() @view @external def is_killed() -> bool: """ @notice Get whether this gauge is killed and not receiving anymore emissions @dev This will return True if the max emissions has been reached or if set to killed by the ADMIN. """ return self.integrate_fraction[self.receiver] == self.max_emissions or self._is_killed @view @external def inflation_rate() -> uint256: """ @notice Get the locally stored inflation rate """ return shift(self.inflation_params, -40) @view @external def future_epoch_time() -> uint256: """ @notice Get the locally stored timestamp of the inflation rate epoch end """ return bitwise_and(self.inflation_params, 2 ** 40 - 1) @pure @external def admin() -> address: """ @notice Get the address of the admin which can kill this gauge """ return ADMIN @external def initialize(_receiver: address, _max_emissions: uint256): """ @notice Proxy initializer method @dev Placed last in the source file to save some gas, this fn is called only once. Additional checks should be made by the DAO before voting in this gauge, specifically to make sure that `_fund_recipient` is capable of collecting emissions. @param _receiver The address which will receive CRV emissions @param _max_emissions The maximum amount of emissions which `_receiver` will receive """ assert self.last_checkpoint == 0 # dev: already initialized self.receiver = _receiver self.max_emissions = _max_emissions self.last_checkpoint = block.timestamp future_epoch_time: uint256 = CRV20(CRV).future_epoch_time_write() self.inflation_params = shift(CRV20(CRV).rate(), 40) + future_epoch_time
[{"name":"Checkpoint","inputs":[{"name":"_timestamp","type":"uint256","indexed":false},{"name":"_new_emissions","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_admin","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"user_checkpoint","inputs":[{"name":"_user","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"claimable_tokens_write","inputs":[{"name":"_user","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"set_killed","inputs":[{"name":"_is_killed","type":"bool"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"is_killed","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"inflation_rate","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_epoch_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"pure","type":"function","name":"admin","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"nonpayable","type":"function","name":"initialize","inputs":[{"name":"_receiver","type":"address"},{"name":"_max_emissions","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"integrate_fraction","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_checkpoint","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"receiver","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"max_emissions","inputs":[],"outputs":[{"name":"","type":"uint256"}]}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 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.