ChildChainGaugeFactory
The ChildGaugeFactory
is used to claim CRV emissions from. The RootChainGaugeFactory
on Ethereum and ChildGaugeFactory
on the according chain share the same contract address.
Contract Source & Deployment
All contract deployments can be found here.
Source code available on Github.
Contract Info Methods¶
is_valid_gauge
¶
ChildGaugeFactory.is_valid_gauge(_gauge: address) -> bool:
Getter method to check if _gauge
is a valid gauge. A gauge is valid if
Returns: true or flase (bool
).
Input | Type | Description |
---|---|---|
_gauge | address | gauge address |
Source code
is_mirrored
¶
ChildGaugeFactory.is_mirrored(_gauge: address) -> bool:
Getter method to check if the gauge is mirrored on Ethereum. If true, a RootGauge with the same contract address as the ChildGauge exists on Ethereum.
Returns: true or false (bool
).
Input | Type | Description |
---|---|---|
_gauge | address | gauge address |
Source code
set_mirrored
¶
ChildGaugeFactory.set_mirrored(_gauge: address, _mirrored: bool):
Guarded Method
This function is only callable by the admin
of the contract.
Function to set the mirrored bit of the gauge data for _gauge
Emits: UpdateMirrored
Input | Type | Description |
---|---|---|
_gauge | address | gauge address |
_mirrored | bool | bool determin whether to set the mirrored but to True/False |
Source code
event UpdateMirrored:
_gauge: indexed(address)
_mirrored: bool
# [last_request][has_counterpart][is_valid_gauge]
gauge_data: public(HashMap[address, uint256])
@external
def set_mirrored(_gauge: address, _mirrored: bool):
"""
@notice Set the mirrored bit of the gauge data for `_gauge`
@param _gauge The gauge of interest
@param _mirrored Boolean deteremining whether to set the mirrored bit to True/False
"""
gauge_data: uint256 = self.gauge_data[_gauge]
assert gauge_data != 0 # dev: invalid gauge
assert msg.sender == self.owner # dev: only owner
gauge_data = shift(shift(gauge_data, -2), 2) + 1 # set is_valid_gauge = True
if _mirrored:
gauge_data += 2 # set is_mirrored = True
self.gauge_data[_gauge] = gauge_data
log UpdateMirrored(_gauge, _mirrored)
last_request
¶
ChildGaugeFactory.last_request(_gauge: address) -> bool:
Getter for the last timestamp of the last cross chain request for emissions.
Returns: timestamp (uint256
).
Input | Type | Description |
---|---|---|
_gauge | address | gauge address |
Source code
gauge_data
¶
ChildGaugeFactory.gauge_data() -> address: view
todo
Returns: todo
Input | Type | Description |
---|---|---|
_gauge | address | gauge address |
get_gauge_from_lp_token
¶
ChildGaugeFactory.minted(arg0: address) -> address: view
Getter for the gauge of LP token arg0
.
Returns: gauge (address
).
Input | Type | Description |
---|---|---|
arg0 | address | lp token |
Source code
get_gauge_from_lp_token: public(HashMap[address, address])
@external
def deploy_gauge(_lp_token: address, _salt: bytes32, _manager: address = msg.sender) -> address:
"""
@notice Deploy a liquidity gauge
@param _lp_token The token to deposit in the gauge
@param _manager The address to set as manager of the gauge
@param _salt A value to deterministically deploy a gauge
"""
if self.get_gauge_from_lp_token[_lp_token] != ZERO_ADDRESS:
# overwriting lp_token -> gauge mapping requires
assert msg.sender == self.owner # dev: only owner
gauge_data: uint256 = 1 # set is_valid_gauge = True
implementation: address = self.get_implementation
gauge: address = create_forwarder_to(
implementation, salt=keccak256(_abi_encode(chain.id, msg.sender, _salt))
)
if msg.sender == self.call_proxy:
gauge_data += 2 # set mirrored = True
log UpdateMirrored(gauge, True)
# issue a call to the root chain to deploy a root gauge
CallProxy(self.call_proxy).anyCall(
self,
_abi_encode(chain.id, _salt, method_id=method_id("deploy_gauge(uint256,bytes32)")),
ZERO_ADDRESS,
1
)
self.gauge_data[gauge] = gauge_data
idx: uint256 = self.get_gauge_count
self.get_gauge[idx] = gauge
self.get_gauge_count = idx + 1
self.get_gauge_from_lp_token[_lp_token] = gauge
ChildGauge(gauge).initialize(_lp_token, _manager)
log DeployedGauge(implementation, _lp_token, msg.sender, _salt, gauge)
return gauge
get_gauge_count
¶
ChildGaugeFactory.get_gauge_count() -> uint256: view
Getter for the number of gauges deployed. Increments by one when deploying a new gauge.
Returns: total number of gauges deployed (uint256
).
Source code
get_gauge_count: public(uint256)
@external
def deploy_gauge(_lp_token: address, _salt: bytes32, _manager: address = msg.sender) -> address:
"""
@notice Deploy a liquidity gauge
@param _lp_token The token to deposit in the gauge
@param _manager The address to set as manager of the gauge
@param _salt A value to deterministically deploy a gauge
"""
if self.get_gauge_from_lp_token[_lp_token] != ZERO_ADDRESS:
# overwriting lp_token -> gauge mapping requires
assert msg.sender == self.owner # dev: only owner
gauge_data: uint256 = 1 # set is_valid_gauge = True
implementation: address = self.get_implementation
gauge: address = create_forwarder_to(
implementation, salt=keccak256(_abi_encode(chain.id, msg.sender, _salt))
)
if msg.sender == self.call_proxy:
gauge_data += 2 # set mirrored = True
log UpdateMirrored(gauge, True)
# issue a call to the root chain to deploy a root gauge
CallProxy(self.call_proxy).anyCall(
self,
_abi_encode(chain.id, _salt, method_id=method_id("deploy_gauge(uint256,bytes32)")),
ZERO_ADDRESS,
1
)
self.gauge_data[gauge] = gauge_data
idx: uint256 = self.get_gauge_count
self.get_gauge[idx] = gauge
self.get_gauge_count = idx + 1
self.get_gauge_from_lp_token[_lp_token] = gauge
ChildGauge(gauge).initialize(_lp_token, _manager)
log DeployedGauge(implementation, _lp_token, msg.sender, _salt, gauge)
return gauge
get_gauge
¶
ChildGaugeFactory.get_gauge(arg0: address) -> address: view
Getter for the gauge at index arg0
.
Returns: gauge (address
).
Input | Type | Description |
---|---|---|
arg0 | address | user address |
Mint Emissions¶
mint
¶
ChildGaugeFactory.mint(_gauge: address):
Function to mint CRV emission rewards for msg.sender
and transfer it to them.
Emits: Minted
Input | Type | Description |
---|---|---|
_gauge | address | gauge address to mint from |
Source code
event Minted:
_user: indexed(address)
_gauge: indexed(address)
_new_total: uint256
@external
@nonreentrant("lock")
def mint(_gauge: address):
"""
@notice Mint everything which belongs to `msg.sender` and send to them
@param _gauge `LiquidityGauge` address to get mintable amount from
"""
self._psuedo_mint(_gauge, msg.sender)
@internal
def _psuedo_mint(_gauge: address, _user: address):
gauge_data: uint256 = self.gauge_data[_gauge]
assert gauge_data != 0 # dev: invalid gauge
# if is_mirrored and last_request != this week
if bitwise_and(gauge_data, 2) != 0 and shift(gauge_data, -2) / WEEK != block.timestamp / WEEK:
CallProxy(self.call_proxy).anyCall(
self,
_abi_encode(_gauge, method_id=method_id("transmit_emissions(address)")),
ZERO_ADDRESS,
1,
)
# update last request time
self.gauge_data[_gauge] = shift(block.timestamp, 2) + 3
assert ChildGauge(_gauge).user_checkpoint(_user)
total_mint: uint256 = ChildGauge(_gauge).integrate_fraction(_user)
to_mint: uint256 = total_mint - self.minted[_user][_gauge]
if to_mint != 0:
# transfer tokens to user
response: Bytes[32] = raw_call(
CRV,
_abi_encode(_user, to_mint, method_id=method_id("transfer(address,uint256)")),
max_outsize=32,
)
if len(response) != 0:
assert convert(response, bool)
self.minted[_user][_gauge] = total_mint
log Minted(_user, _gauge, total_mint)
mint_many
¶
ChildGaugeFactory.mint(_gauge: address[32]):
Function to mint CRV emission rewards from multiple gauges for msg.sender
and transfer it to them. This function supports claim of up to 32 gauges in one transcations.
Emits: Minted
Input | Type | Description |
---|---|---|
_gauge | address[32] | gauge addresses to mint from |
Source code
event Minted:
_user: indexed(address)
_gauge: indexed(address)
_new_total: uint256
@external
@nonreentrant("lock")
def mint_many(_gauges: address[32]):
"""
@notice Mint everything which belongs to `msg.sender` across multiple gauges
@param _gauges List of `LiquidityGauge` addresses
"""
for i in range(32):
if _gauges[i] == ZERO_ADDRESS:
pass
self._psuedo_mint(_gauges[i], msg.sender)
@internal
def _psuedo_mint(_gauge: address, _user: address):
gauge_data: uint256 = self.gauge_data[_gauge]
assert gauge_data != 0 # dev: invalid gauge
# if is_mirrored and last_request != this week
if bitwise_and(gauge_data, 2) != 0 and shift(gauge_data, -2) / WEEK != block.timestamp / WEEK:
CallProxy(self.call_proxy).anyCall(
self,
_abi_encode(_gauge, method_id=method_id("transmit_emissions(address)")),
ZERO_ADDRESS,
1,
)
# update last request time
self.gauge_data[_gauge] = shift(block.timestamp, 2) + 3
assert ChildGauge(_gauge).user_checkpoint(_user)
total_mint: uint256 = ChildGauge(_gauge).integrate_fraction(_user)
to_mint: uint256 = total_mint - self.minted[_user][_gauge]
if to_mint != 0:
# transfer tokens to user
response: Bytes[32] = raw_call(
CRV,
_abi_encode(_user, to_mint, method_id=method_id("transfer(address,uint256)")),
max_outsize=32,
)
if len(response) != 0:
assert convert(response, bool)
self.minted[_user][_gauge] = total_mint
log Minted(_user, _gauge, total_mint)
minted
¶
ChildGaugeFactory.minted(arg0: address, arg1: address) -> uint256: view
Getter for the total minted CRV of address arg0
from gauge arg1
.
Returns: total minted CRV (uint256
).
Input | Type | Description |
---|---|---|
arg0 | address | user address |
arg1 | address | gauge address |
Source code
# user -> gauge -> value
minted: public(HashMap[address, HashMap[address, uint256]])
@external
@nonreentrant("lock")
def mint(_gauge: address):
"""
@notice Mint everything which belongs to `msg.sender` and send to them
@param _gauge `LiquidityGauge` address to get mintable amount from
"""
self._psuedo_mint(_gauge, msg.sender)
@internal
def _psuedo_mint(_gauge: address, _user: address):
gauge_data: uint256 = self.gauge_data[_gauge]
assert gauge_data != 0 # dev: invalid gauge
# if is_mirrored and last_request != this week
if bitwise_and(gauge_data, 2) != 0 and shift(gauge_data, -2) / WEEK != block.timestamp / WEEK:
CallProxy(self.call_proxy).anyCall(
self,
_abi_encode(_gauge, method_id=method_id("transmit_emissions(address)")),
ZERO_ADDRESS,
1,
)
# update last request time
self.gauge_data[_gauge] = shift(block.timestamp, 2) + 3
assert ChildGauge(_gauge).user_checkpoint(_user)
total_mint: uint256 = ChildGauge(_gauge).integrate_fraction(_user)
to_mint: uint256 = total_mint - self.minted[_user][_gauge]
if to_mint != 0:
# transfer tokens to user
response: Bytes[32] = raw_call(
CRV,
_abi_encode(_user, to_mint, method_id=method_id("transfer(address,uint256)")),
max_outsize=32,
)
if len(response) != 0:
assert convert(response, bool)
self.minted[_user][_gauge] = total_mint
log Minted(_user, _gauge, total_mint)
Deploying Gauges¶
deploy_gauge
¶
ChildGaugeFactory.deploy_gauge(_lp_token: address, _salt: bytes32, _manager: address = msg.sender) -> address:
Function to deploy a ChildLiquidityGauge and initialize it.
Returns: gauge (address
).
Emits: DeployedGauge
and possibly UpdateMirrored
Input | Type | Description |
---|---|---|
_lp_token | address | lp token to deploy the gauge for |
_salt | bytes32 | salt |
_manager | address | gauge manager address; defaults to msg.sender |
Source code
event DeployedGauge:
_implementation: indexed(address)
_lp_token: indexed(address)
_deployer: indexed(address)
_salt: bytes32
_gauge: address
event UpdateMirrored:
_gauge: indexed(address)
_mirrored: bool
@external
def deploy_gauge(_lp_token: address, _salt: bytes32, _manager: address = msg.sender) -> address:
"""
@notice Deploy a liquidity gauge
@param _lp_token The token to deposit in the gauge
@param _manager The address to set as manager of the gauge
@param _salt A value to deterministically deploy a gauge
"""
if self.get_gauge_from_lp_token[_lp_token] != ZERO_ADDRESS:
# overwriting lp_token -> gauge mapping requires
assert msg.sender == self.owner # dev: only owner
gauge_data: uint256 = 1 # set is_valid_gauge = True
implementation: address = self.get_implementation
gauge: address = create_forwarder_to(
implementation, salt=keccak256(_abi_encode(chain.id, msg.sender, _salt))
)
if msg.sender == self.call_proxy:
gauge_data += 2 # set mirrored = True
log UpdateMirrored(gauge, True)
# issue a call to the root chain to deploy a root gauge
CallProxy(self.call_proxy).anyCall(
self,
_abi_encode(chain.id, _salt, method_id=method_id("deploy_gauge(uint256,bytes32)")),
ZERO_ADDRESS,
1
)
self.gauge_data[gauge] = gauge_data
idx: uint256 = self.get_gauge_count
self.get_gauge[idx] = gauge
self.get_gauge_count = idx + 1
self.get_gauge_from_lp_token[_lp_token] = gauge
ChildGauge(gauge).initialize(_lp_token, _manager)
log DeployedGauge(implementation, _lp_token, msg.sender, _salt, gauge)
return gauge
Voting-Escrow and Implementation¶
voting_escrow
¶
ChildGaugeFactory.voting_escrow() -> address: view
Getter for the Voting-Escrow contract on Arbitrum. This contract is needed to apply user boosts for gauges.
Returns: voting escrow (address
).
set_voting_escrow
¶
ChildGaugeFactory.set_voting_escrow(_voting_escrow: address):
Guarded Method
This function is only callable by the owner
of the contract.
Function to set the voting escrow contract.
Emits: UpdateVotingEscrow
Input | Type | Description |
---|---|---|
_voting_escrow | address | voting escorw oracle contract |
Source code
event UpdateVotingEscrow:
_old_voting_escrow: address
_new_voting_escrow: address
voting_escrow: public(address)
@external
def set_voting_escrow(_voting_escrow: address):
"""
@notice Update the voting escrow contract
@param _voting_escrow Contract to use as the voting escrow oracle
"""
assert msg.sender == self.owner # dev: only owner
log UpdateVotingEscrow(self.voting_escrow, _voting_escrow)
self.voting_escrow = _voting_escrow
get_implementation
¶
ChildGaugeFactory.is_mirrored(_gauge: address) -> bool:
Getter for the ChildLiquidityGauge implementation from which the ChildGauges are created from.
Returns: implementation contract (address
).
set_implementation
¶
ChildGaugeFactory.set_implementation(_implementation: address):
Guarded Method
This function is only callable by the owner
of the contract.
Function to set the gauge implementation contract.
Emits: UpdateImplementation
Input | Type | Description |
---|---|---|
_implementation | address | implementation contract |
Source code
event UpdateImplementation:
_old_implementation: address
_new_implementation: address
get_implementation: public(address)
@external
def set_implementation(_implementation: address):
"""
@notice Set the implementation
@param _implementation The address of the implementation to use
"""
assert msg.sender == self.owner # dev: only owner
log UpdateImplementation(self.get_implementation, _implementation)
self.get_implementation = _implementation
Admin Ownership¶
owner
¶
ChildGaugeFactory.owner() -> address: view
Getter for the owner of the ChildGaugeFactory contract.
Returns: owner (address
).
future_owner
¶
ChildGaugeFactory.future_owner() -> address: view
Getter for the owner of the ChildGaugeFactory contract.
Returns: owner (address
).
commit_transfer_ownership
¶
ChildGaugeFactory.commit_transfer_ownership(_future_owner: address):
Guarded Method
This function is only callable by the owner
of the contract.
Function to commit the transfer of contract ownership to _future_owner
.
Input | Type | Description |
---|---|---|
_future_owner | address | future owner |
Source code
owner: public(address)
future_owner: public(address)
@external
def commit_transfer_ownership(_future_owner: address):
"""
@notice Transfer ownership to `_future_owner`
@param _future_owner The account to commit as the future owner
"""
assert msg.sender == self.owner # dev: only owner
self.future_owner = _future_owner
accept_transfer_ownership
¶
ChildGaugeFactory.accept_transfer_ownership():
Guarded Method
This function is only callable by the future_owner
of the contract.
Function to accept the transfer of ownership.
Emits: TransferOwnership
Source code
event TransferOwnership:
_old_owner: address
_new_owner: address
owner: public(address)
future_owner: public(address)
@external
def accept_transfer_ownership():
"""
@notice Accept the transfer of ownership
@dev Only the committed future owner can call this function
"""
assert msg.sender == self.future_owner # dev: only future owner
log TransferOwnership(self.owner, msg.sender)
self.owner = msg.sender