Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
16834428 | 597 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Minimal Proxy Contract for 0x6adb68d8c15954ad673d8f129857b34dc2f08bf2
Contract Name:
Vyper_contract
Compiler Version
vyper:0.2.16
Contract Source Code (Vyper language format)
# @version 0.2.16 """ @title Liquidity Gauge v4 @author StakeDAO Protocol @license MIT """ # Original idea and credit: # Curve Finance's veCRV # https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/gauges/LiquidityGaugeV4.vy # Mostly forked from Curve, except that now there is no direct link between the gauge controller # and the gauges. In this implementation, SDT rewards are like any other token rewards. from vyper.interfaces import ERC20 interface VotingEscrow: def user_point_epoch(addr: address) -> uint256: view def user_point_history__ts(addr: address, epoch: uint256) -> uint256: view interface VotingEscrowBoost: def adjusted_balance_of(_account: address) -> uint256: view interface PoolRegistry: def vaultMap(_poolId: uint256, _owner : address) -> address: view event Deposit: provider: indexed(address) value: uint256 event Withdraw: provider: indexed(address) value: uint256 event UpdateLiquidityLimit: user: address original_balance: uint256 original_supply: uint256 working_balance: uint256 working_supply: uint256 event CommitOwnership: admin: address event ApplyOwnership: admin: address event RewardDataUpdate: _token: indexed(address) _amount: uint256 struct Reward: token: address distributor: address period_finish: uint256 rate: uint256 last_update: uint256 integral: uint256 MAX_REWARDS: constant(uint256) = 8 TOKENLESS_PRODUCTION: constant(uint256) = 40 WEEK: constant(uint256) = 604800 SDT: public(address) voting_escrow: public(address) veBoost_proxy: public(address) balanceOf: public(HashMap[address, uint256]) totalSupply: public(uint256) working_balances: public(HashMap[address, uint256]) working_supply: public(uint256) integrate_checkpoint_of: public(HashMap[address, uint256]) # For tracking external rewards reward_count: public(uint256) reward_tokens: public(address[MAX_REWARDS]) reward_data: public(HashMap[address, Reward]) # claimant -> default reward receiver rewards_receiver: public(HashMap[address, address]) # reward token -> claiming address -> integral reward_integral_for: public(HashMap[address, HashMap[address, uint256]]) # user -> [uint128 claimable amount][uint128 claimed amount] claim_data: HashMap[address, HashMap[address, uint256]] admin: public(address) future_admin: public(address) claimer: public(address) pool_registry: public(address) initialized: public(bool) pid: public(uint256) @external def __init__(): """ @notice Contract constructor @dev The contract has an initializer to prevent the take over of the implementation """ assert self.initialized == False #dev: contract is already initialized self.initialized = True @external def initialize(_admin: address, _SDT: address, _voting_escrow: address, _veBoost_proxy: address, _distributor: address, _pid: uint256, _pool_registry: address): """ @notice Contract initializer @param _admin Admin who can kill the gauge @param _SDT Address of the SDT token @param _voting_escrow Address of the veSDT contract @param _veBoost_proxy Address of the proxy contract used to query veSDT balances and taking into account potential delegations @param _distributor Address of the contract responsible for distributing SDT tokens to this gauge @param _pid pool id corresponding to this gauge @param _pool_registry Address of the pool registry contract """ assert self.initialized == False #dev: contract is already initialized self.initialized = True assert _admin != ZERO_ADDRESS assert _SDT != ZERO_ADDRESS assert _voting_escrow != ZERO_ADDRESS assert _veBoost_proxy != ZERO_ADDRESS assert _distributor != ZERO_ADDRESS self.admin = _admin self.SDT = _SDT self.voting_escrow = _voting_escrow self.veBoost_proxy = _veBoost_proxy self.pid = _pid self.pool_registry = _pool_registry # add in all liquidityGauge the SDT reward - the distribution could be null though self.reward_data[_SDT].distributor = _distributor self.reward_tokens[0] = _SDT self.reward_count = 1 @internal def _update_liquidity_limit(addr: address, l: uint256, L: uint256): """ @notice Calculate limits which depend on the amount of SDT token per-user. Effectively it calculates working balances to apply amplification of SDT production by SDT @param addr User address @param l User's amount of liquidity (LP tokens) @param L Total amount of liquidity (LP tokens) """ # To be called after totalSupply is updated voting_balance: uint256 = VotingEscrowBoost(self.veBoost_proxy).adjusted_balance_of(addr) voting_total: uint256 = ERC20(self.voting_escrow).totalSupply() lim: uint256 = l * TOKENLESS_PRODUCTION / 100 if voting_total > 0: lim += L * voting_balance / voting_total * (100 - TOKENLESS_PRODUCTION) / 100 lim = min(l, lim) old_bal: uint256 = self.working_balances[addr] self.working_balances[addr] = lim _working_supply: uint256 = self.working_supply + lim - old_bal self.working_supply = _working_supply log UpdateLiquidityLimit(addr, l, L, lim, _working_supply) @internal def _checkpoint_reward(_user: address, token: address, _total_supply: uint256, _user_balance: uint256, _claim: bool, receiver: address): """ @notice Claim pending rewards and checkpoint rewards for a user @param _user Account to checkpoint reward for @param token Token to checkpoint reward for @param _total_supply Amount total deposited in the contract @param _user_balance Amount total deposited in the contract for _user @param _claim Bool to claim (or not) reward during the checkpoint @param receiver Address to transfer the claimed reward """ total_supply: uint256 = _total_supply user_balance: uint256 = _user_balance if token == self.SDT : total_supply = self.working_supply user_balance = self.working_balances[_user] integral: uint256 = self.reward_data[token].integral last_update: uint256 = min(block.timestamp, self.reward_data[token].period_finish) duration: uint256 = last_update - self.reward_data[token].last_update if duration != 0: self.reward_data[token].last_update = last_update if total_supply != 0: integral += duration * self.reward_data[token].rate * 10**18 / total_supply self.reward_data[token].integral = integral if _user != ZERO_ADDRESS: integral_for: uint256 = self.reward_integral_for[token][_user] new_claimable: uint256 = 0 if integral_for < integral: self.reward_integral_for[token][_user] = integral new_claimable = user_balance * (integral - integral_for) / 10**18 claim_data: uint256 = self.claim_data[_user][token] total_claimable: uint256 = shift(claim_data, -128) + new_claimable if total_claimable > 0: total_claimed: uint256 = claim_data % 2**128 if _claim: response: Bytes[32] = raw_call( token, concat( method_id("transfer(address,uint256)"), convert(receiver, bytes32), convert(total_claimable, bytes32), ), max_outsize=32, ) if len(response) != 0: assert convert(response, bool) self.claim_data[_user][token] = total_claimed + total_claimable elif new_claimable > 0: self.claim_data[_user][token] = total_claimed + shift(total_claimable, 128) if token == self.SDT : self.integrate_checkpoint_of[_user] = block.timestamp @internal def _checkpoint_rewards(_user: address, _total_supply: uint256, _claim: bool, _receiver: address, _only_checkpoint:bool = False): """ @notice Claim pending rewards and checkpoint rewards for a user @param _user Account to checkpoint reward for @param _total_supply Amount total deposited in the contract @param _user_balance Amount total deposited in the contract for _user @param _claim Bool to claim (or not) reward during the checkpoint @param _receiver Address to transfer the claimed reward @param _only_checkpoint Bool to call only checkpoint reward """ receiver: address = _receiver user_balance: uint256 = 0 if _user != ZERO_ADDRESS: user_balance = self.balanceOf[_user] if _claim and _receiver == ZERO_ADDRESS: # if receiver is not explicitly declared, check if a default receiver is set receiver = self.rewards_receiver[_user] if receiver == ZERO_ADDRESS: # if no default receiver is set, direct claims to the user receiver = _user if _only_checkpoint: self._checkpoint_reward(_user, self.SDT, _total_supply, user_balance, False, receiver) else: reward_count: uint256 = self.reward_count for i in range(MAX_REWARDS): if i == reward_count: break token: address = self.reward_tokens[i] self._checkpoint_reward(_user, token, _total_supply, user_balance, _claim, receiver) @external def user_checkpoint(addr: address) -> bool: """ @notice Record a checkpoint for `addr` @param addr User address @return bool success """ assert msg.sender == addr # dev: unauthorized total_supply: uint256 = self.totalSupply self._checkpoint_rewards(addr, total_supply, False, ZERO_ADDRESS, True) self._update_liquidity_limit(addr, self.balanceOf[addr], total_supply) return True @view @external def claimed_reward(_addr: address, _token: address) -> uint256: """ @notice Get the number of already-claimed reward tokens for a user @param _addr Account to get reward amount for @param _token Token to get reward amount for @return uint256 Total amount of `_token` already claimed by `_addr` """ return self.claim_data[_addr][_token] % 2**128 @view @external def claimable_reward(_user: address, _reward_token: address) -> uint256: """ @notice Get the number of claimable reward tokens for a user @param _user Account to get reward amount for @param _reward_token Token to get reward amount for @return uint256 Claimable reward token amount """ integral: uint256 = self.reward_data[_reward_token].integral total_supply: uint256 = self.totalSupply user_balance: uint256 = self.balanceOf[_user] if _reward_token == self.SDT: total_supply = self.working_supply user_balance = self.working_balances[_user] if total_supply != 0: last_update: uint256 = min(block.timestamp, self.reward_data[_reward_token].period_finish) duration: uint256 = last_update - self.reward_data[_reward_token].last_update integral += (duration * self.reward_data[_reward_token].rate * 10**18 / total_supply) integral_for: uint256 = self.reward_integral_for[_reward_token][_user] new_claimable: uint256 = user_balance * (integral - integral_for) / 10**18 return shift(self.claim_data[_user][_reward_token], -128) + new_claimable @external def set_rewards_receiver(_receiver: address): """ @notice Set the default reward receiver for the caller. @dev When set to ZERO_ADDRESS, rewards are sent to the caller @param _receiver Receiver address for any rewards claimed via `claim_rewards` """ self.rewards_receiver[msg.sender] = _receiver @external @nonreentrant('lock') def claim_rewards(_addr: address = msg.sender, _receiver: address = ZERO_ADDRESS): """ @notice Claim available reward tokens for `_addr` @param _addr Address to claim for @param _receiver Address to transfer rewards to - if set to ZERO_ADDRESS, uses the default reward receiver for the caller """ if _receiver != ZERO_ADDRESS: assert _addr == msg.sender # dev: cannot redirect when claiming for another user self._checkpoint_rewards(_addr, self.totalSupply, True, _receiver) @external @nonreentrant('lock') def claim_rewards_for(_addr: address, _receiver: address): """ @notice Claim available reward tokens for `_addr` @param _addr Address to claim for @param _receiver Address to transfer rewards to - if set to ZERO_ADDRESS, uses the default reward receiver for the caller """ assert self.claimer == msg.sender # dev: only the claim contract can claim for other if _receiver != _addr: assert _receiver == self.claimer # dev: if the receiver is not the user it needs to be the claimer self._checkpoint_rewards(_addr, self.totalSupply, True, _receiver) @external def kick(addr: address): """ @notice Kick `addr` for abusing their boost @dev Only if either they had another voting event, or their voting escrow lock expired @param addr Address to kick """ t_last: uint256 = self.integrate_checkpoint_of[addr] t_ve: uint256 = VotingEscrow(self.voting_escrow).user_point_history__ts( addr, VotingEscrow(self.voting_escrow).user_point_epoch(addr) ) _balance: uint256 = self.balanceOf[addr] assert ERC20(self.voting_escrow).balanceOf(addr) == 0 or t_ve > t_last # dev: kick not allowed assert self.working_balances[addr] > _balance * TOKENLESS_PRODUCTION / 100 # dev: kick not needed total_supply: uint256 = self.totalSupply self._checkpoint_rewards(addr, total_supply, False, ZERO_ADDRESS, True) self._update_liquidity_limit(addr, self.balanceOf[addr], total_supply) @external @nonreentrant('lock') def deposit(_value: uint256, _addr: address , _claim_rewards: bool = False): """ @notice Deposit `_value` LP tokens @dev Depositting also claims pending reward tokens @param _value Number of tokens to deposit @param _addr Address to deposit for @param _claim_rewards Bool to claim reward on _checkpoint_rewards() """ #only personal vault can deposit assert PoolRegistry(self.pool_registry).vaultMap(self.pid, _addr) == msg.sender, "!only personal vault" total_supply: uint256 = self.totalSupply if _value != 0: is_rewards: bool = self.reward_count != 0 if is_rewards: self._checkpoint_rewards(_addr, total_supply, _claim_rewards, ZERO_ADDRESS) total_supply += _value new_balance: uint256 = self.balanceOf[_addr] + _value self.balanceOf[_addr] = new_balance self.totalSupply = total_supply self._update_liquidity_limit(_addr, new_balance, total_supply) else: self._checkpoint_rewards(_addr, total_supply, False, ZERO_ADDRESS, True) log Deposit(_addr, _value) @external @nonreentrant('lock') def withdraw(_value: uint256, _addr: address, _claim_rewards: bool = False): """ @notice Withdraw `_value` LP tokens @dev Withdrawing also claims pending reward tokens @param _value Number of tokens to withdraw @param _addr Address to withdraw for @param _claim_rewards Bool to claim reward on _checkpoint_rewards() """ assert PoolRegistry(self.pool_registry).vaultMap(self.pid, _addr) == msg.sender, "!only personal vault" total_supply: uint256 = self.totalSupply if _value != 0: is_rewards: bool = self.reward_count != 0 if is_rewards: self._checkpoint_rewards(_addr, total_supply, _claim_rewards, ZERO_ADDRESS) total_supply -= _value new_balance: uint256 = self.balanceOf[_addr] - _value self.balanceOf[_addr] = new_balance self.totalSupply = total_supply self._update_liquidity_limit(_addr, new_balance, total_supply) else: self._checkpoint_rewards(_addr, total_supply, False, ZERO_ADDRESS, True) log Withdraw(_addr, _value) @external def add_reward(_reward_token: address, _distributor: address): """ @notice Set the active reward contract @param _reward_token Address for new reward token @param _distributor Address of _reward_token distributor """ assert msg.sender == self.admin # dev: only owner reward_count: uint256 = self.reward_count assert reward_count < MAX_REWARDS assert self.reward_data[_reward_token].distributor == ZERO_ADDRESS self.reward_data[_reward_token].distributor = _distributor self.reward_tokens[reward_count] = _reward_token self.reward_count = reward_count + 1 @external def set_reward_distributor(_reward_token: address, _distributor: address): """ @notice Change address for a existring reward token distributor @param _reward_token Address of the reward token @param _distributor New address of the distributor """ current_distributor: address = self.reward_data[_reward_token].distributor assert msg.sender == current_distributor or msg.sender == self.admin assert current_distributor != ZERO_ADDRESS assert _distributor != ZERO_ADDRESS self.reward_data[_reward_token].distributor = _distributor @external def set_claimer(_claimer: address): """ @notice Change address for claimer @param _claimer New address for claimer """ assert msg.sender == self.admin assert _claimer != ZERO_ADDRESS self.claimer = _claimer @external @nonreentrant("lock") def deposit_reward_token(_reward_token: address, _amount: uint256): """ @notice Depositing new amount of reward token into this LGV4 @param _reward_token Address of the reward token @param _amount Amount of reward token to be deposited """ assert msg.sender == self.reward_data[_reward_token].distributor self._checkpoint_rewards(ZERO_ADDRESS, self.totalSupply, False, ZERO_ADDRESS) response: Bytes[32] = raw_call( _reward_token, concat( method_id("transferFrom(address,address,uint256)"), convert(msg.sender, bytes32), convert(self, bytes32), convert(_amount, bytes32), ), max_outsize=32, ) if len(response) != 0: assert convert(response, bool) period_finish: uint256 = self.reward_data[_reward_token].period_finish if block.timestamp >= period_finish: self.reward_data[_reward_token].rate = _amount / WEEK else: remaining: uint256 = period_finish - block.timestamp leftover: uint256 = remaining * self.reward_data[_reward_token].rate self.reward_data[_reward_token].rate = (_amount + leftover) / WEEK self.reward_data[_reward_token].last_update = block.timestamp self.reward_data[_reward_token].period_finish = block.timestamp + WEEK log RewardDataUpdate(_reward_token,_amount) @external def commit_transfer_ownership(addr: address): """ @notice Transfer ownership of Gauge to `addr` @param addr Address to have ownership transferred to """ assert msg.sender == self.admin # dev: admin only assert addr != ZERO_ADDRESS # dev: future admin cannot be the 0 address self.future_admin = addr log CommitOwnership(addr) @external def accept_transfer_ownership(): """ @notice Accept a pending ownership transfer """ _admin: address = self.future_admin assert msg.sender == _admin # dev: future admin only self.admin = _admin log ApplyOwnership(_admin)
[{"name":"Deposit","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Withdraw","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"UpdateLiquidityLimit","inputs":[{"name":"user","type":"address","indexed":false},{"name":"original_balance","type":"uint256","indexed":false},{"name":"original_supply","type":"uint256","indexed":false},{"name":"working_balance","type":"uint256","indexed":false},{"name":"working_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"CommitOwnership","inputs":[{"name":"admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"ApplyOwnership","inputs":[{"name":"admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"RewardDataUpdate","inputs":[{"name":"_token","type":"address","indexed":true},{"name":"_amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"initialize","inputs":[{"name":"_admin","type":"address"},{"name":"_SDT","type":"address"},{"name":"_voting_escrow","type":"address"},{"name":"_veBoost_proxy","type":"address"},{"name":"_distributor","type":"address"},{"name":"_pid","type":"uint256"},{"name":"_pool_registry","type":"address"}],"outputs":[],"gas":353724},{"stateMutability":"nonpayable","type":"function","name":"user_checkpoint","inputs":[{"name":"addr","type":"address"}],"outputs":[{"name":"","type":"bool"}],"gas":3493123},{"stateMutability":"view","type":"function","name":"claimed_reward","inputs":[{"name":"_addr","type":"address"},{"name":"_token","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"gas":2946},{"stateMutability":"view","type":"function","name":"claimable_reward","inputs":[{"name":"_user","type":"address"},{"name":"_reward_token","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"gas":26674},{"stateMutability":"nonpayable","type":"function","name":"set_rewards_receiver","inputs":[{"name":"_receiver","type":"address"}],"outputs":[],"gas":35583},{"stateMutability":"nonpayable","type":"function","name":"claim_rewards","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_rewards","inputs":[{"name":"_addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_rewards","inputs":[{"name":"_addr","type":"address"},{"name":"_receiver","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"claim_rewards_for","inputs":[{"name":"_addr","type":"address"},{"name":"_receiver","type":"address"}],"outputs":[],"gas":3463704},{"stateMutability":"nonpayable","type":"function","name":"kick","inputs":[{"name":"addr","type":"address"}],"outputs":[],"gas":3513917},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"_value","type":"uint256"},{"name":"_addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"_value","type":"uint256"},{"name":"_addr","type":"address"},{"name":"_claim_rewards","type":"bool"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"_value","type":"uint256"},{"name":"_addr","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"_value","type":"uint256"},{"name":"_addr","type":"address"},{"name":"_claim_rewards","type":"bool"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"add_reward","inputs":[{"name":"_reward_token","type":"address"},{"name":"_distributor","type":"address"}],"outputs":[],"gas":112823},{"stateMutability":"nonpayable","type":"function","name":"set_reward_distributor","inputs":[{"name":"_reward_token","type":"address"},{"name":"_distributor","type":"address"}],"outputs":[],"gas":40573},{"stateMutability":"nonpayable","type":"function","name":"set_claimer","inputs":[{"name":"_claimer","type":"address"}],"outputs":[],"gas":38002},{"stateMutability":"nonpayable","type":"function","name":"deposit_reward_token","inputs":[{"name":"_reward_token","type":"address"},{"name":"_amount","type":"uint256"}],"outputs":[],"gas":3584740},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"addr","type":"address"}],"outputs":[],"gas":39962},{"stateMutability":"nonpayable","type":"function","name":"accept_transfer_ownership","inputs":[],"outputs":[],"gas":39810},{"stateMutability":"view","type":"function","name":"SDT","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":2868},{"stateMutability":"view","type":"function","name":"voting_escrow","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":2898},{"stateMutability":"view","type":"function","name":"veBoost_proxy","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":2928},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"gas":3173},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":2988},{"stateMutability":"view","type":"function","name":"working_balances","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"gas":3233},{"stateMutability":"view","type":"function","name":"working_supply","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3048},{"stateMutability":"view","type":"function","name":"integrate_checkpoint_of","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"gas":3293},{"stateMutability":"view","type":"function","name":"reward_count","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3108},{"stateMutability":"view","type":"function","name":"reward_tokens","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"gas":3183},{"stateMutability":"view","type":"function","name":"reward_data","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"token","type":"address"},{"name":"distributor","type":"address"},{"name":"period_finish","type":"uint256"},{"name":"rate","type":"uint256"},{"name":"last_update","type":"uint256"},{"name":"integral","type":"uint256"}],"gas":14613},{"stateMutability":"view","type":"function","name":"rewards_receiver","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"address"}],"gas":3413},{"stateMutability":"view","type":"function","name":"reward_integral_for","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"gas":3658},{"stateMutability":"view","type":"function","name":"admin","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3258},{"stateMutability":"view","type":"function","name":"future_admin","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3288},{"stateMutability":"view","type":"function","name":"claimer","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3318},{"stateMutability":"view","type":"function","name":"pool_registry","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3348},{"stateMutability":"view","type":"function","name":"initialized","inputs":[],"outputs":[{"name":"","type":"bool"}],"gas":3378},{"stateMutability":"view","type":"function","name":"pid","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3408}]
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.