Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x3669C421b77340B2979d1A00a792CC2ee0FcE737
Balance 0 ETH
Nonce 1
Code Size 9001 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9001 bytes
0x600436101561000d576116b0565b60046000601c376000513461232457636b441a408118610074576004358060a01c6123245760e05260005433186123245760e0516001557f2f56810a6bf40af059b96d3aea4db54081f378029a518390491093a7b67032e960e051610100526020610100a1005b636a1c05ae81186100ce5760005433186123245760015460e052600060e051146123245760e0516000557febee2d5739011062cb4f14113f3b36bf0ffe3da5c0568f64189d1012a118910560e051610100526020610100a1005b632a327fd78118610126576004358060a01c612324576101e0526101e05160e0526100fa6102006116b6565b61020080516102805260208101516102a05260408101516102c05260608101516102e052506080610280f35b633f9095b78118610187576004358060a01c6123245760e052633b9aca0760e05160a0526080526040608020546101005260006101005114612324576101005160018082038060801d81607f1d186123245790509050610120526020610120f35b6318dfe9218118610463576004358060a01c612324576102a0526024358060801d81607f1d18612324576102c0526000543318612324576000604435106123245760006102c05112156101db5760006101e4565b6004546102c051125b1561232457633b9aca076102a05160a052608052604060802054612324576005546102e0526102e05160018082018060801d81607f1d1861232457905090506005556102a05160016102e051633b9aca008110156123245702600701556102c05160018082018060801d81607f1d186123245790509050633b9aca076102a05160a0526080526040608020554262093a808181830110612324578082019050905062093a808082049050905062093a80808202821582848304141715612324579050905061030052600060443511156103cd576102c05160e0526102c96103406117cb565b61034051610320526102c05160e0526102e36103606118d1565b61036051610340526102f6610380611a87565b61038051610360526044356103405181818301106123245780820190509050633b9aca0e6102c05160a05260805260406080206103005160a0526080526040608020556103005160016102c051633b9aca008110156123245702633b9aca100155610360516103205160443580820282158284830414171561232457905090508181830110612324578082019050905063773594106103005160a05260805260406080205561030051637735941155604435633b9aca0b6102a05160a05260805260406080206103005160a0526080526040608020555b60016102c051633b9aca008110156123245702633b9aca10015461040a576103005160016102c051633b9aca008110156123245702633b9aca1001555b61030051633b9aca0d6102a05160a0526080526040608020557ffd55b3191f9c9dd92f4f134dd700e7d76f6a0c836a08687023d6d38f03ebd8776102a051610320526102c05161034052604435610360526060610320a1005b63c2c4c5c1811861047f576104796102a0611a87565b6102a050005b63615e523781186104c0576004358060a01c612324576102a0526102a05160e0526104ab6102c0611c70565b6102c0506104ba6102c0611a87565b6102c050005b636207d86681186104d557426101e0526104e8565b63d3078c948118610520576024356101e0525b6004358060a01c612324576101c0526101c05160e0526101e05161010052610511610200611e1c565b61020051610220526020610220f35b6395cfcec3811861053557426102c052610548565b636472eee181186105a5576024356102c0525b6004358060a01c612324576102a0526102a05160e0526105696102e0611c70565b6102e0506105786102e0611a87565b6102e0506102a05160e0526102c051610100526105966102e0611e1c565b6102e051610300526020610300f35b6392d0d23281186107145760043560040160408135116123245780803560200180826103e03750505060005433186123245760006024351061232457600454610440526103e08060066104405160a0526080526040608020602082510160c060006003818352015b8260c051602002111561061f5761063e565b60c05160200285015160c051850155815160010180835281141561060d575b5050505050506104405160018082018060801d81607f1d18612324579050905060045560006024351461071257610440516102a0526024356102c052610682611f4a565b7f6fbe76157c712f16b5a3c44ed48baa04e3450bc3fab0c020e848aca72bbccc84610460806040808252808301806103e080516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f8201039050905090508101905060208201915061044051825290509050610460a15b005b63db1ca2608118610755576004358060801d81607f1d18612324576103e0526000543318612324576103e0516102a0526024356102c052610753611f4a565b005b63d4d2646e8118610791576004358060a01c6123245761044052600054331861232457610440516102a0526024356102c05261078f6120dc565b005b63d713632881186110f6576004358060a01c612324576102a0523360e0526107ba6103406116b6565b61034080516102c05260208101516102e052604081015161030052606081015161032052506102e051610340526103005161036052600554610380524262093a808181830110612324578082019050905062093a808082049050905062093a8080820282158284830414171561232457905090506103a0526103a05161036051116108b65760206103c0527f596f757220746f6b656e206c6f636b206578706972657320746f6f20736f6f6e6103e0526103c0506103c051806103e001818260206001820306601f82010390500336823750506308c379a06103805260206103a0526103c05160206001820306601f820103905060440161039cfd5b600060243510156108c85760006108d1565b61271060243511155b61094c57601e6103c0527f596f75207573656420616c6c20796f757220766f74696e6720706f77657200006103e0526103c0506103c051806103e001818260206001820306601f82010390500336823750506308c379a06103805260206103a0526103c05160206001820306601f820103905060440161039cfd5b633b9aca0a3360a05260805260406080206102a05160a052608052604060802054620d2f00818183011061232457808201905090504210156109ff5760146103c0527f43616e6e6f7420766f746520736f206f6674656e0000000000000000000000006103e0526103c0506103c051806103e001818260206001820306601f82010390500336823750506308c379a06103805260206103a0526103c05160206001820306601f820103905060440161039cfd5b633b9aca076102a05160a05260805260406080205460018082038060801d81607f1d1861232457905090506103c05260006103c0511215610ab157600f6103e0527f4761756765206e6f742061646465640000000000000000000000000000000000610400526103e0506103e0518061040001818260206001820306601f82010390500336823750506308c379a06103a05260206103c0526103e05160206001820306601f82010390506044016103bcfd5b633b9aca083360a05260805260406080206102a05160a052608052604060802080546103e052600181015461040052600281015461042052506000610440526103a051610420511115610b1957610420516103a0518082106123245780820390509050610440525b6103e0516104405180820282158284830414171561232457905090506104605261034051602435808202821582848304141715612324579050905061271080820490509050610480526024356104a052610360516104c052610360516103a05180821061232457808203905090506104e052610480516104e051808202821582848304141715612324579050905061050052633b9aca093360a05260805260406080205461052052610520516104a051818183011061232457808201905090506104005180821061232457808203905090506105205261052051633b9aca093360a0526080526040608020556000610520511015610c18576000610c22565b6127106105205111155b610c9d576013610540527f5573656420746f6f206d75636820706f776572000000000000000000000000006105605261054050610540518061056001818260206001820306601f82010390500336823750506308c379a0610500526020610520526105405160206001820306601f820103905060440161051cfd5b6102a05160e052610caf610560611c70565b61056051610540526001633b9aca0b6102a05160a05260805260406080206103a05160a05260805260406080200154610560526103c05160e052610cf46105a06118d1565b6105a051610580526001633b9aca0e6103c05160a05260805260406080206103a05160a052608052604060802001546105a05261054051610500518181830110612324578082019050905061046051808210610d505781610d52565b805b90509050610460518082106123245780820390509050633b9aca0b6102a05160a05260805260406080206103a05160a05260805260406080205561058051610500518181830110612324578082019050905061046051808210610db55781610db7565b805b90509050610460518082106123245780820390509050633b9aca0e6103c05160a05260805260406080206103a05160a0526080526040608020556103a0516104205111610e81576001633b9aca0b6102a05160a05260805260406080206103a05160a052608052604060802001805461048051818183011061232457808201905090508155506001633b9aca0e6103c05160a05260805260406080206103a05160a05260805260406080200180546104805181818301106123245780820190509050815550610f52565b6105605161048051818183011061232457808201905090506103e051808210610eaa5781610eac565b805b905090506103e05180821061232457808203905090506001633b9aca0b6102a05160a05260805260406080206103a05160a052608052604060802001556105a05161048051818183011061232457808201905090506103e051808210610f125781610f14565b805b905090506103e05180821061232457808203905090506001633b9aca0e6103c05160a05260805260406080206103a05160a052608052604060802001555b42610420511115610fd257633b9aca0c6102a05160a05260805260406080206104205160a052608052604060802080546103e0518082106123245780820390509050815550633b9aca0f6103c05160a05260805260406080206104205160a052608052604060802080546103e05180821061232457808203905090508155505b633b9aca0c6102a05160a05260805260406080206104c05160a052608052604060802080546104805181818301106123245780820190509050815550633b9aca0f6103c05160a05260805260406080206104c05160a0526080526040608020805461048051818183011061232457808201905090508155506110556105c0611a87565b6105c050633b9aca083360a05260805260406080206102a05160a05260805260406080206104805181556104a05160018201556104c05160028201555042633b9aca0a3360a05260805260406080206102a05160a0526080526040608020557f45ca9a4c8d0119eb329e580d28fe689e484e1be230da8037ade9547d2d25cc91426105c052336105e0526102a051610600526024356106205260806105c0a1005b634e791a3a811861114d576004358060a01c6123245760e052633b9aca0b60e05160a0526080526040608020633b9aca0d60e05160a05260805260406080205460a052608052604060802054610100526020610100f35b6372fdccfa81186111ae576004358060801d81607f1d186123245760e052637735941260e05160a0526080526040608020600160e051633b9aca0081101561232457026377359413015460a052608052604060802054610100526020610100f35b636977ff9281186111d957637735941063773594115460a05260805260406080205460e052602060e0f35b636f214a6a811861123a576004358060801d81607f1d186123245760e052633b9aca0e60e05160a0526080526040608020600160e051633b9aca008110156123245702633b9aca10015460a052608052604060802054610100526020610100f35b6301c0821081186112595760005433186123245760043563b2d05e1355005b63f851a44081186112705760005460e052602060e0f35b6317f7182a81186112875760015460e052602060e0f35b63fc0c546a811861129e5760025460e052602060e0f35b63dfe0503181186112b55760035460e052602060e0f35b639fba03a181186112cc5760045460e052602060e0f35b63e93841d081186112e35760055460e052602060e0f35b63d958a8fc81186113ac576004358060801d81607f1d186123245760e052610100806020808252600660e05160a052608052604060802081840180828082602082540160c060006003818352015b8260c051602002111561134357611362565b60c05185015460c0516020028501528151600101808352811415611331575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f82010390509050905090508101905090509050610100f35b63b053918781186113d6576001600435633b9aca0081101561232457026007015460e052602060e0f35b630f467f988118611440576004358060a01c6123245760e0526024358060a01c6123245761010052633b9aca0860e05160a05260805260406080206101005160a0526080526040608020805461012052600181015461014052600281015461016052506060610120f35b63411e74b58118611478576004358060a01c6123245760e052633b9aca0960e05160a052608052604060802054610100526020610100f35b637e418fa081186114ce576004358060a01c6123245760e0526024358060a01c6123245761010052633b9aca0a60e05160a05260805260406080206101005160a052608052604060802054610120526020610120f35b63edba5273811861151f576004358060a01c6123245760e052633b9aca0b60e05160a052608052604060802060243560a0526080526040608020805461010052600181015461012052506040610100f35b63a4d7a2508118611557576004358060a01c6123245760e052633b9aca0d60e05160a052608052604060802054610100526020610100f35b63a9b48c0181186115ad576004358060801d81607f1d186123245760e052633b9aca0e60e05160a052608052604060802060243560a0526080526040608020805461010052600181015461012052506040610100f35b635a54915881186115da576001600435633b9aca008110156123245702633b9aca10015460e052602060e0f35b631142916b811861160257637735941060043560a05260805260406080205460e052602060e0f35b63513872bd811861161c5763773594115460e052602060e0f35b63afd2bb498118611667576004358060801d81607f1d186123245760e052637735941260e05160a052608052604060802060243560a052608052604060802054610100526020610100f35b6351ce6b598118611694576001600435633b9aca0081101561232457026377359413015460e052602060e0f35b630a3be75781186116ae5763b2d05e135460e052602060e0f35b505b60006000fd5b600354610100526370a082316101405260e051610160526020610140602461015c610100515afa6116ec573d600060003e3d6000fd5b601f3d111561232457610140516101205263cbf9fe5f6101805260e0516101a0526040610180602461019c610100515afa61172c573d600060003e3d6000fd5b603f3d11156123245761018080518060801d81607f1d1861232457610140526020810151610160525061016051610180526101405160008112612324576101a05260006101c052426101805111156117a7576101205161018051428082106123245780820390509050808015612324578204905090506101c0525b6101205181526101c05160208201526101805160408201526101a051606082015250565b600160e051633b9aca0081101561232457026377359413015461010052600061010051116118015760008152506118cf566118cf565b637735941260e05160a05260805260406080206101005160a0526080526040608020546101205261014060006101f4818352015b42610100511115611845576118c1565b610100805162093a808181830110612324578082019050905081525061012051637735941260e05160a05260805260406080206101005160a052608052604060802055426101005111156118b15761010051600160e051633b9aca008110156123245702637735941301555b8151600101808352811415611835575b5050610120518152506118cf565b565b600160e051633b9aca008110156123245702633b9aca1001546101005260006101005111611907576000815250611a8556611a85565b633b9aca0e60e05160a05260805260406080206101005160a05260805260406080208054610120526001810154610140525061016060006101f4818352015b4261010051111561195657611a77565b610100805162093a80818183011061232457808201905090508152506101405162093a808082028215828483041417156123245790509050610180526101805161012051116119b057600061012052600061014052611a0c565b6101208051610180518082106123245780820390509050815250633b9aca0f60e05160a05260805260406080206101005160a0526080526040608020546101a05261014080516101a05180821061232457808203905090508152505b633b9aca0e60e05160a05260805260406080206101005160a05260805260406080206101205181556101405160018201555042610100511115611a675761010051600160e051633b9aca008110156123245702633b9aca1001555b8151600101808352811415611946575b505061012051815250611a85565b565b6377359411546101c0526004546101e052426101c0511115611abe576101c0805162093a8080821061232457808203905090508152505b63773594106101c05160a0526080526040608020546102005261022060006064818352015b6101e0516102205118611af557611b31565b6102205160e052611b076102406118d1565b610240506102205160e052611b1d6102406117cb565b610240508151600101808352811415611ae3575b505061022060006101f4818352015b426101c0511115611b5057611c65565b6101c0805162093a808181830110612324578082019050905081525060006102005261024060006064818352015b6101e0516102405118611b9057611c24565b633b9aca0e6102405160a05260805260406080206101c05160a0526080526040608020546102605263773594126102405160a05260805260406080206101c05160a05260805260406080205461028052610200805161026051610280518082028215828483041417156123245790509050818183011061232457808201905090508152508151600101808352811415611b7e575b50506102005163773594106101c05160a052608052604060802055426101c0511115611c55576101c0516377359411555b8151600101808352811415611b40575b505061020051815250565b633b9aca0d60e05160a0526080526040608020546101005260006101005111611ca1576000815250611e1a56611e1a565b633b9aca0b60e05160a05260805260406080206101005160a05260805260406080208054610120526001810154610140525061016060006101f4818352015b42610100511115611cf057611e0c565b610100805162093a80818183011061232457808201905090508152506101405162093a80808202821582848304141715612324579050905061018052610180516101205111611d4a57600061012052600061014052611da6565b6101208051610180518082106123245780820390509050815250633b9aca0c60e05160a05260805260406080206101005160a0526080526040608020546101a05261014080516101a05180821061232457808203905090508152505b633b9aca0b60e05160a05260805260406080206101005160a05260805260406080206101205181556101405160018201555042610100511115611dfc5761010051633b9aca0d60e05160a0526080526040608020555b8151600101808352811415611ce0575b505061012051815250611e1a565b565b6101005162093a808082049050905062093a8080820282158284830414171561232457905090506101205263773594106101205160a0526080526040608020546101405260006101405111611e79576000815250611f4856611f48565b633b9aca0760e05160a05260805260406080205460018082038060801d81607f1d1861232457905090506101605263773594126101605160a05260805260406080206101205160a05260805260406080205461018052633b9aca0b60e05160a05260805260406080206101205160a0526080526040608020546101a052670de0b6b3a76400006101805180820282158284830414171561232457905090506101a05180820282158284830414171561232457905090506101405180801561232457820490509050815250611f48565b565b6102a05160e052611f5c6103006117cb565b610300516102e0526102a05160e052611f766103206118d1565b6103205161030052611f89610340611a87565b61034051610320524262093a808181830110612324578082019050905062093a808082049050905062093a8080820282158284830414171561232457905090506103405261032051610300516102c051808202821582848304141715612324579050905081818301106123245780820190509050610300516102e05180820282158284830414171561232457905090508082106123245780820390509050610320526103205163773594106103405160a0526080526040608020556102c05163773594126102a05160a05260805260406080206103405160a052608052604060802055610340516377359411556103405160016102a051633b9aca008110156123245702637735941301557e170bcdc909b6ac6e12d020fe8942256312cdcd555fb6d712899eba56d2f9016102a0516103605261034051610380526102c0516103a052610320516103c0526080610360a1565b633b9aca076102a05160a05260805260406080205460018082038060801d81607f1d1861232457905090506102e0526102a05160e05261211d610320611c70565b61032051610300526102e05160e0526121376103406117cb565b61034051610320526102e05160e0526121516103606118d1565b6103605161034052612164610380611a87565b61038051610360524262093a808181830110612324578082019050905062093a808082049050905062093a808082028215828483041417156123245790509050610380526102c051633b9aca0b6102a05160a05260805260406080206103805160a05260805260406080205561038051633b9aca0d6102a05160a052608052604060802055610340516102c051818183011061232457808201905090506103005180821061232457808203905090506103a0526103a051633b9aca0e6102e05160a05260805260406080206103805160a0526080526040608020556103805160016102e051633b9aca008110156123245702633b9aca100155610360516103a05161032051808202821582848304141715612324579050905081818301106123245780820190509050610340516103205180820282158284830414171561232457905090508082106123245780820390509050610360526103605163773594106103805160a052608052604060802055610380516377359411557f54c0cf3647e6cdb2fc0a7876e60ba77563fceedf2e06c01c597f8dccb9e6bd726102a0516103c052426103e0526102c05161040052610360516104205260806103c0a1565b600080fd

Verified Source Code Partial Match

Compiler: v0.3.1
Vyper_contract.vy 673 lines
# @version 0.3.1

"""
@title Gauge Controller
@author Curve Finance
@license MIT
@notice Controls liquidity gauges and the issuance of coins through the gauges
"""

# ====================================================================
# |     ______                   _______                             |
# |    / _____________ __  __   / ____(_____  ____ _____  ________   |
# |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
# |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
# | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
# |                                                                  |
# ====================================================================
# ======================= FraxGaugeControllerV2 ======================
# ====================================================================
# Frax Finance: https://github.com/FraxFinance

# Original idea and credit:
# Curve Finance's Gauge Controller
# https://resources.curve.fi/base-features/understanding-gauges
# https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/GaugeController.vy
# This contract is an almost-identical fork of Curve's contract
# veFXS is used instead of veCRV. 

# Frax Reviewer(s) / Contributor(s)
# Travis Moore: https://github.com/FortisFortuna
# Jason Huan: https://github.com/jasonhuan
# Sam Kazemian: https://github.com/samkazemian


# 7 * 86400 seconds - all future times are rounded by week
WEEK: constant(uint256) = 604800

# Cannot change weight votes more often than once in 10 days
WEIGHT_VOTE_DELAY: constant(uint256) = 10 * 86400


struct Point:
    bias: uint256
    slope: uint256

struct CorrectedPoint:
    bias: uint256
    slope: uint256
    lock_end: uint256
    fxs_amount: uint256

struct VotedSlope:
    slope: uint256
    power: uint256
    end: uint256

struct LockedBalance:
    amount: int128
    end: uint256

interface VotingEscrow:
    def balanceOf(addr: address,) -> uint256: view
    def get_last_user_slope(addr: address) -> int128: view
    def locked__end(addr: address) -> uint256: view
    def locked(addr: address,) -> LockedBalance: view


event CommitOwnership:
    admin: address

event ApplyOwnership:
    admin: address

event AddType:
    name: String[64]
    type_id: int128

event NewTypeWeight:
    type_id: int128
    time: uint256
    weight: uint256
    total_weight: uint256

event NewGaugeWeight:
    gauge_address: address
    time: uint256
    weight: uint256
    total_weight: uint256

event VoteForGauge:
    time: uint256
    user: address
    gauge_addr: address
    weight: uint256

event NewGauge:
    addr: address
    gauge_type: int128
    weight: uint256


MULTIPLIER: constant(uint256) = 10 ** 18

admin: public(address)  # Can and will be a smart contract
future_admin: public(address)  # Can and will be a smart contract

token: public(address)  # CRV token
voting_escrow: public(address)  # Voting escrow

# Gauge parameters
# All numbers are "fixed point" on the basis of 1e18
n_gauge_types: public(int128)
n_gauges: public(int128)
gauge_type_names: public(HashMap[int128, String[64]])

# Needed for enumeration
gauges: public(address[1000000000])

# we increment values by 1 prior to storing them here so we can rely on a value
# of zero as meaning the gauge has not been set
gauge_types_: HashMap[address, int128]

vote_user_slopes: public(HashMap[address, HashMap[address, VotedSlope]])  # user -> gauge_addr -> VotedSlope
vote_user_power: public(HashMap[address, uint256])  # Total vote power used by user
last_user_vote: public(HashMap[address, HashMap[address, uint256]])  # Last user vote's timestamp for each gauge address

# Past and scheduled points for gauge weight, sum of weights per type, total weight
# Point is for bias+slope
# changes_* are for changes in slope
# time_* are for the last change timestamp
# timestamps are rounded to whole weeks

points_weight: public(HashMap[address, HashMap[uint256, Point]])  # gauge_addr -> time -> Point
changes_weight: HashMap[address, HashMap[uint256, uint256]]  # gauge_addr -> time -> slope
time_weight: public(HashMap[address, uint256])  # gauge_addr -> last scheduled time (next week)

points_sum: public(HashMap[int128, HashMap[uint256, Point]])  # type_id -> time -> Point
changes_sum: HashMap[int128, HashMap[uint256, uint256]]  # type_id -> time -> slope
time_sum: public(uint256[1000000000])  # type_id -> last scheduled time (next week)

points_total: public(HashMap[uint256, uint256])  # time -> total weight
time_total: public(uint256)  # last scheduled time

points_type_weight: public(HashMap[int128, HashMap[uint256, uint256]])  # type_id -> time -> type weight
time_type_weight: public(uint256[1000000000])  # type_id -> last scheduled time (next week)

global_emission_rate: public(uint256)  # inflation rate

@external
def __init__(_token: address, _voting_escrow: address):
    """
    @notice Contract constructor
    @param _token `ERC-20 FXS` contract address
    @param _voting_escrow `VotingEscrow` contract address
    """
    assert _token != ZERO_ADDRESS
    assert _voting_escrow != ZERO_ADDRESS

    self.admin = msg.sender
    self.token = _token
    self.voting_escrow = _voting_escrow
    self.time_total = block.timestamp / WEEK * WEEK


@external
def commit_transfer_ownership(addr: address):
    """
    @notice Transfer ownership of GaugeController to `addr`
    @param addr Address to have ownership transferred to
    """
    assert msg.sender == self.admin  # dev: admin only
    self.future_admin = addr
    log CommitOwnership(addr)


@external
def apply_transfer_ownership():
    """
    @notice Apply pending ownership transfer
    """
    assert msg.sender == self.admin  # dev: admin only
    _admin: address = self.future_admin
    assert _admin != ZERO_ADDRESS  # dev: admin not set
    self.admin = _admin
    log ApplyOwnership(_admin)

@internal
@view
def _get_corrected_info(addr: address) -> CorrectedPoint:
    """
    @notice Get the most recently recorded rate of voting power decrease for `addr`.
            Corrected by VOTE_WEIGHT_MULTIPLIER (veFXS).
    @param addr Address of the user wallet
    @return CorrectedPoint
    """
    escrow: address = self.voting_escrow
    vefxs_balance: uint256 = VotingEscrow(escrow).balanceOf(addr)
    locked_balance: LockedBalance = VotingEscrow(escrow).locked(addr)
    locked_end: uint256 = locked_balance.end
    locked_fxs: uint256 = convert(locked_balance.amount, uint256)

    corrected_slope: uint256 = 0

    # Decay to 0. Decaying to 1 veFXS <> 1 FXS gives wrong expected results
    if (locked_end > block.timestamp):
        corrected_slope = vefxs_balance / (locked_end - block.timestamp)

    return CorrectedPoint({bias: vefxs_balance, slope: corrected_slope, lock_end: locked_end, fxs_amount: locked_fxs})

@view
@external
def get_corrected_info(addr: address) -> CorrectedPoint:
    return self._get_corrected_info(addr)

@external
@view
def gauge_types(_addr: address) -> int128:
    """
    @notice Get gauge type for address
    @param _addr Gauge address
    @return Gauge type id
    """
    gauge_type: int128 = self.gauge_types_[_addr]
    assert gauge_type != 0

    return gauge_type - 1


@internal
def _get_type_weight(gauge_type: int128) -> uint256:
    """
    @notice Fill historic type weights week-over-week for missed checkins
            and return the type weight for the future week
    @param gauge_type Gauge type id
    @return Type weight
    """
    t: uint256 = self.time_type_weight[gauge_type]
    if t > 0:
        w: uint256 = self.points_type_weight[gauge_type][t]
        for i in range(500):
            if t > block.timestamp:
                break
            t += WEEK
            self.points_type_weight[gauge_type][t] = w
            if t > block.timestamp:
                self.time_type_weight[gauge_type] = t
        return w
    else:
        return 0


@internal
def _get_sum(gauge_type: int128) -> uint256:
    """
    @notice Fill sum of gauge weights for the same type week-over-week for
            missed checkins and return the sum for the future week
    @param gauge_type Gauge type id
    @return Sum of weights
    """
    t: uint256 = self.time_sum[gauge_type]
    if t > 0:
        pt: Point = self.points_sum[gauge_type][t]
        for i in range(500):
            if t > block.timestamp:
                break
            t += WEEK
            d_bias: uint256 = pt.slope * WEEK
            if pt.bias > d_bias:
                pt.bias -= d_bias
                d_slope: uint256 = self.changes_sum[gauge_type][t]
                pt.slope -= d_slope
            else:
                pt.bias = 0
                pt.slope = 0
            self.points_sum[gauge_type][t] = pt
            if t > block.timestamp:
                self.time_sum[gauge_type] = t
        return pt.bias
    else:
        return 0


@internal
def _get_total() -> uint256:
    """
    @notice Fill historic total weights week-over-week for missed checkins
            and return the total for the future week
    @return Total weight
    """
    t: uint256 = self.time_total
    _n_gauge_types: int128 = self.n_gauge_types
    if t > block.timestamp:
        # If we have already checkpointed - still need to change the value
        t -= WEEK
    pt: uint256 = self.points_total[t]

    for gauge_type in range(100):
        if gauge_type == _n_gauge_types:
            break
        self._get_sum(gauge_type)
        self._get_type_weight(gauge_type)

    for i in range(500):
        if t > block.timestamp:
            break
        t += WEEK
        pt = 0
        # Scales as n_types * n_unchecked_weeks (hopefully 1 at most)
        for gauge_type in range(100):
            if gauge_type == _n_gauge_types:
                break
            type_sum: uint256 = self.points_sum[gauge_type][t].bias
            type_weight: uint256 = self.points_type_weight[gauge_type][t]
            pt += type_sum * type_weight
        self.points_total[t] = pt

        if t > block.timestamp:
            self.time_total = t
    return pt


@internal
def _get_weight(gauge_addr: address) -> uint256:
    """
    @notice Fill historic gauge weights week-over-week for missed checkins
            and return the total for the future week
    @param gauge_addr Address of the gauge
    @return Gauge weight
    """
    t: uint256 = self.time_weight[gauge_addr]
    if t > 0:
        pt: Point = self.points_weight[gauge_addr][t]
        for i in range(500):
            if t > block.timestamp:
                break
            t += WEEK
            d_bias: uint256 = pt.slope * WEEK
            if pt.bias > d_bias:
                pt.bias -= d_bias
                d_slope: uint256 = self.changes_weight[gauge_addr][t]
                pt.slope -= d_slope
            else:
                pt.bias = 0
                pt.slope = 0
            self.points_weight[gauge_addr][t] = pt
            if t > block.timestamp:
                self.time_weight[gauge_addr] = t
        return pt.bias
    else:
        return 0

@external
def add_gauge(addr: address, gauge_type: int128, weight: uint256):
    """
    @notice Add gauge `addr` of type `gauge_type` with weight `weight`
    @param addr Gauge address
    @param gauge_type Gauge type
    @param weight Gauge weight
    """
    assert msg.sender == self.admin
    assert weight >= 0
    assert (gauge_type >= 0) and (gauge_type < self.n_gauge_types)
    assert self.gauge_types_[addr] == 0  # dev: cannot add the same gauge twice

    n: int128 = self.n_gauges
    self.n_gauges = n + 1
    self.gauges[n] = addr

    self.gauge_types_[addr] = gauge_type + 1
    next_time: uint256 = (block.timestamp + WEEK) / WEEK * WEEK

    if weight > 0:
        _type_weight: uint256 = self._get_type_weight(gauge_type)
        _old_sum: uint256 = self._get_sum(gauge_type)
        _old_total: uint256 = self._get_total()

        self.points_sum[gauge_type][next_time].bias = weight + _old_sum
        self.time_sum[gauge_type] = next_time
        self.points_total[next_time] = _old_total + _type_weight * weight
        self.time_total = next_time

        self.points_weight[addr][next_time].bias = weight

    if self.time_sum[gauge_type] == 0:
        self.time_sum[gauge_type] = next_time
    self.time_weight[addr] = next_time

    log NewGauge(addr, gauge_type, weight)


@external
def checkpoint():
    """
    @notice Checkpoint to fill data common for all gauges
    """
    self._get_total()


@external
def checkpoint_gauge(addr: address):
    """
    @notice Checkpoint to fill data for both a specific gauge and common for all gauges
    @param addr Gauge address
    """
    self._get_weight(addr)
    self._get_total()


@internal
@view
def _gauge_relative_weight(addr: address, time: uint256) -> uint256:
    """
    @notice Get Gauge relative weight (not more than 1.0) normalized to 1e18
            (e.g. 1.0 == 1e18). Inflation which will be received by it is
            global_emission_rate * relative_weight / 1e18
    @param addr Gauge address
    @param time Relative weight at the specified timestamp in the past or present
    @return Value of relative weight normalized to 1e18
    """
    t: uint256 = time / WEEK * WEEK
    _total_weight: uint256 = self.points_total[t]

    if _total_weight > 0:
        gauge_type: int128 = self.gauge_types_[addr] - 1
        _type_weight: uint256 = self.points_type_weight[gauge_type][t]
        _gauge_weight: uint256 = self.points_weight[addr][t].bias
        return MULTIPLIER * _type_weight * _gauge_weight / _total_weight

    else:
        return 0


@external
@view
def gauge_relative_weight(addr: address, time: uint256 = block.timestamp) -> uint256:
    """
    @notice Get Gauge relative weight (not more than 1.0) normalized to 1e18
            (e.g. 1.0 == 1e18). Inflation which will be received by it is
            global_emission_rate * relative_weight / 1e18
    @param addr Gauge address
    @param time Relative weight at the specified timestamp in the past or present
    @return Value of relative weight normalized to 1e18
    """
    return self._gauge_relative_weight(addr, time)


@external
def gauge_relative_weight_write(addr: address, time: uint256 = block.timestamp) -> uint256:
    """
    @notice Get gauge weight normalized to 1e18 and also fill all the unfilled
            values for type and gauge records
    @dev Any address can call, however nothing is recorded if the values are filled already
    @param addr Gauge address
    @param time Relative weight at the specified timestamp in the past or present
    @return Value of relative weight normalized to 1e18
    """
    self._get_weight(addr)
    self._get_total()  # Also calculates get_sum
    return self._gauge_relative_weight(addr, time)


@internal
def _change_type_weight(type_id: int128, weight: uint256):
    """
    @notice Change type weight
    @param type_id Type id
    @param weight New type weight
    """
    old_weight: uint256 = self._get_type_weight(type_id)
    old_sum: uint256 = self._get_sum(type_id)
    _total_weight: uint256 = self._get_total()
    next_time: uint256 = (block.timestamp + WEEK) / WEEK * WEEK

    _total_weight = _total_weight + old_sum * weight - old_sum * old_weight
    self.points_total[next_time] = _total_weight
    self.points_type_weight[type_id][next_time] = weight
    self.time_total = next_time
    self.time_type_weight[type_id] = next_time

    log NewTypeWeight(type_id, next_time, weight, _total_weight)


@external
def add_type(_name: String[64], weight: uint256):
    """
    @notice Add gauge type with name `_name` and weight `weight`
    @param _name Name of gauge type
    @param weight Weight of gauge type
    """
    assert msg.sender == self.admin
    assert weight >= 0
    type_id: int128 = self.n_gauge_types
    self.gauge_type_names[type_id] = _name
    self.n_gauge_types = type_id + 1
    if weight != 0:
        self._change_type_weight(type_id, weight)
        log AddType(_name, type_id)


@external
def change_type_weight(type_id: int128, weight: uint256):
    """
    @notice Change gauge type `type_id` weight to `weight`
    @param type_id Gauge type id
    @param weight New Gauge weight
    """
    assert msg.sender == self.admin
    self._change_type_weight(type_id, weight)


@internal
def _change_gauge_weight(addr: address, weight: uint256):
    # Change gauge weight
    # Only needed when testing in reality
    gauge_type: int128 = self.gauge_types_[addr] - 1
    old_gauge_weight: uint256 = self._get_weight(addr)
    type_weight: uint256 = self._get_type_weight(gauge_type)
    old_sum: uint256 = self._get_sum(gauge_type)
    _total_weight: uint256 = self._get_total()
    next_time: uint256 = (block.timestamp + WEEK) / WEEK * WEEK

    self.points_weight[addr][next_time].bias = weight
    self.time_weight[addr] = next_time

    new_sum: uint256 = old_sum + weight - old_gauge_weight
    self.points_sum[gauge_type][next_time].bias = new_sum
    self.time_sum[gauge_type] = next_time

    _total_weight = _total_weight + new_sum * type_weight - old_sum * type_weight
    self.points_total[next_time] = _total_weight
    self.time_total = next_time

    log NewGaugeWeight(addr, block.timestamp, weight, _total_weight)


@external
def change_gauge_weight(addr: address, weight: uint256):
    """
    @notice Change weight of gauge `addr` to `weight`
    @param addr `GaugeController` contract address
    @param weight New Gauge weight
    """
    assert msg.sender == self.admin
    self._change_gauge_weight(addr, weight)


@external
def vote_for_gauge_weights(_gauge_addr: address, _user_weight: uint256):
    """
    @notice Allocate voting power for changing pool weights
    @param _gauge_addr Gauge which `msg.sender` votes for
    @param _user_weight Weight for a gauge in bps (units of 0.01%). Minimal is 0.01%. Ignored if 0
    """
    # escrow: address = self.voting_escrow
    # slope: uint256 = convert(VotingEscrow(escrow).get_last_user_slope(msg.sender), uint256)
    # lock_end: uint256 = VotingEscrow(escrow).locked__end(msg.sender)

    corrected_point: CorrectedPoint = self._get_corrected_info(msg.sender)
    slope: uint256 = corrected_point.slope
    lock_end: uint256 = corrected_point.lock_end

    _n_gauges: int128 = self.n_gauges
    next_time: uint256 = (block.timestamp + WEEK) / WEEK * WEEK
    assert lock_end > next_time, "Your token lock expires too soon"
    assert (_user_weight >= 0) and (_user_weight <= 10000), "You used all your voting power"
    assert block.timestamp >= self.last_user_vote[msg.sender][_gauge_addr] + WEIGHT_VOTE_DELAY, "Cannot vote so often"

    gauge_type: int128 = self.gauge_types_[_gauge_addr] - 1
    assert gauge_type >= 0, "Gauge not added"
    # Prepare slopes and biases in memory
    old_slope: VotedSlope = self.vote_user_slopes[msg.sender][_gauge_addr]
    old_dt: uint256 = 0
    if old_slope.end > next_time:
        old_dt = old_slope.end - next_time
    old_bias: uint256 = old_slope.slope * old_dt
    new_slope: VotedSlope = VotedSlope({
        slope: slope * _user_weight / 10000,
        end: lock_end,
        power: _user_weight
    })
    new_dt: uint256 = lock_end - next_time  # dev: raises when expired
    new_bias: uint256 = new_slope.slope * new_dt

    # Check and update powers (weights) used
    power_used: uint256 = self.vote_user_power[msg.sender]
    power_used = power_used + new_slope.power - old_slope.power
    self.vote_user_power[msg.sender] = power_used
    assert (power_used >= 0) and (power_used <= 10000), 'Used too much power'

    ## Remove old and schedule new slope changes
    # Remove slope changes for old slopes
    # Schedule recording of initial slope for next_time
    old_weight_bias: uint256 = self._get_weight(_gauge_addr)
    old_weight_slope: uint256 = self.points_weight[_gauge_addr][next_time].slope
    old_sum_bias: uint256 = self._get_sum(gauge_type)
    old_sum_slope: uint256 = self.points_sum[gauge_type][next_time].slope

    self.points_weight[_gauge_addr][next_time].bias = max(old_weight_bias + new_bias, old_bias) - old_bias
    self.points_sum[gauge_type][next_time].bias = max(old_sum_bias + new_bias, old_bias) - old_bias
    if old_slope.end > next_time:
        self.points_weight[_gauge_addr][next_time].slope = max(old_weight_slope + new_slope.slope, old_slope.slope) - old_slope.slope
        self.points_sum[gauge_type][next_time].slope = max(old_sum_slope + new_slope.slope, old_slope.slope) - old_slope.slope
    else:
        self.points_weight[_gauge_addr][next_time].slope += new_slope.slope
        self.points_sum[gauge_type][next_time].slope += new_slope.slope
    if old_slope.end > block.timestamp:
        # Cancel old slope changes if they still didn't happen
        self.changes_weight[_gauge_addr][old_slope.end] -= old_slope.slope
        self.changes_sum[gauge_type][old_slope.end] -= old_slope.slope
    # Add slope changes for new slopes
    self.changes_weight[_gauge_addr][new_slope.end] += new_slope.slope
    self.changes_sum[gauge_type][new_slope.end] += new_slope.slope

    self._get_total()

    self.vote_user_slopes[msg.sender][_gauge_addr] = new_slope

    # Record last action time
    self.last_user_vote[msg.sender][_gauge_addr] = block.timestamp

    log VoteForGauge(block.timestamp, msg.sender, _gauge_addr, _user_weight)


@external
@view
def get_gauge_weight(addr: address) -> uint256:
    """
    @notice Get current gauge weight
    @param addr Gauge address
    @return Gauge weight
    """
    return self.points_weight[addr][self.time_weight[addr]].bias


@external
@view
def get_type_weight(type_id: int128) -> uint256:
    """
    @notice Get current type weight
    @param type_id Type id
    @return Type weight
    """
    return self.points_type_weight[type_id][self.time_type_weight[type_id]]


@external
@view
def get_total_weight() -> uint256:
    """
    @notice Get current total (type-weighted) weight
    @return Total weight
    """
    return self.points_total[self.time_total]


@external
@view
def get_weights_sum_per_type(type_id: int128) -> uint256:
    """
    @notice Get sum of gauge weights per type
    @param type_id Type id
    @return Sum of gauge weights
    """
    return self.points_sum[type_id][self.time_sum[type_id]].bias

@external
def change_global_emission_rate(new_rate: uint256):
    """
    @notice Change FXS emission rate
    @param new_rate new emission rate (FXS per second)
    """
    assert msg.sender == self.admin
    self.global_emission_rate = new_rate

Read Contract

admin 0xf851a440 → address
future_admin 0x17f7182a → address
gauge_relative_weight 0x6207d866 → uint256
gauge_relative_weight 0xd3078c94 → uint256
gauge_type_names 0xd958a8fc → string
gauge_types 0x3f9095b7 → int128
gauges 0xb0539187 → address
get_corrected_info 0x2a327fd7 → tuple
get_gauge_weight 0x4e791a3a → uint256
get_total_weight 0x6977ff92 → uint256
get_type_weight 0x72fdccfa → uint256
get_weights_sum_per_type 0x6f214a6a → uint256
global_emission_rate 0x0a3be757 → uint256
last_user_vote 0x7e418fa0 → uint256
n_gauge_types 0x9fba03a1 → int128
n_gauges 0xe93841d0 → int128
points_sum 0xa9b48c01 → tuple
points_total 0x1142916b → uint256
points_type_weight 0xafd2bb49 → uint256
points_weight 0xedba5273 → tuple
time_sum 0x5a549158 → uint256
time_total 0x513872bd → uint256
time_type_weight 0x51ce6b59 → uint256
time_weight 0xa4d7a250 → uint256
token 0xfc0c546a → address
vote_user_power 0x411e74b5 → uint256
vote_user_slopes 0x0f467f98 → tuple
voting_escrow 0xdfe05031 → address

Write Contract 12 functions

These functions modify contract state and require a wallet transaction to execute.

add_gauge 0x18dfe921
address addr
int128 gauge_type
uint256 weight
add_type 0x92d0d232
string _name
uint256 weight
apply_transfer_ownership 0x6a1c05ae
No parameters
change_gauge_weight 0xd4d2646e
address addr
uint256 weight
change_global_emission_rate 0x01c08210
uint256 new_rate
change_type_weight 0xdb1ca260
int128 type_id
uint256 weight
checkpoint 0xc2c4c5c1
No parameters
checkpoint_gauge 0x615e5237
address addr
commit_transfer_ownership 0x6b441a40
address addr
gauge_relative_weight_write 0x95cfcec3
address addr
returns: uint256
gauge_relative_weight_write 0x6472eee1
address addr
uint256 time
returns: uint256
vote_for_gauge_weights 0xd7136328
address _gauge_addr
uint256 _user_weight

Recent Transactions

No transactions found for this address