Address Contract Partially Verified
Address
0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0
Balance
0 ETH
Nonce
1
Code Size
12873 bytes
Creator
0xa448833b...6eDf at tx 0x32671769...6c8b90
Indexed Transactions
0
Contract Bytecode
12873 bytes
0x341561000a57600080fd5b600436101561001857613243565b600035601c526f7fffffffffffffffffffffffffffffff604052636b441a4060005114156100945760043560a01c1561005057600080fd5b601154331461005e57600080fd5b600435601255600435610140527f2f56810a6bf40af059b96d3aea4db54081f378029a518390491093a7b67032e96020610140a1005b636a1c05ae60005114156100ff5760115433146100b057600080fd5b60125461014052600061014051186100c757600080fd5b6101405160115561014051610160527febee2d5739011062cb4f14113f3b36bf0ffe3da5c0568f64189d1012a11891056020610160a1005b6357f901e260005114156101335760043560a01c1561011d57600080fd5b601154331461012b57600080fd5b600435600f55005b638e5b490f600051141561015757601154331461014f57600080fd5b600f54601055005b6388c2b3e3600051141561017c57601154331461017357600080fd5b600a5415600a55005b638980f11f60005114156101ff5760043560a01c1561019a57600080fd5b60115433146101a857600080fd5b600054600435186101b857600080fd5b60206101e0604463a9059cbb61014052601154610160526024356101805261015c60006004355af16101e957600080fd5b601f3d116101f657600080fd5b6000506101e050005b6000156102e9575b6101605261014052326101405118156102e357601054610180526000610180511815610279576020610220602463c23697a86101a052610140516101c0526101bc6000610180515af161025957600080fd5b601f3d1161026657600080fd5b60005061022051156102785761016051565b5b6308c379a06101a05260206101c05260256101e0527f536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c610200527f6c6f776564000000000000000000000000000000000000000000000000000000610220526101e05060846101bcfd5b61016051565b637c74a17460005114156103605760043560a01c1561030757600080fd5b600660043560e05260c052604060c0205461014052600161014051633b9aca00811061033257600080fd5b600560043560e05260c052604060c02060c052602060c0200160c052602060c020015460005260206000f350005b63da020a1860005114156103c15760043560a01c1561037e57600080fd5b6002602435633b9aca00811061039357600080fd5b600560043560e05260c052604060c02060c052602060c0200160c052602060c020015460005260206000f350005b63adc6358960005114156104065760043560a01c156103df57600080fd5b6001600260043560e05260c052604060c02060c052602060c020015460005260206000f350005b600015610d7c575b6101e0526101405261016052610180526101a0526101c05261018036610200376003546103805260006101405118156105dd5742610180511115610458576000610160511361045b565b60005b156104e45761016051630784ce008082058080600081121561047957195b607f1c1561048657600080fd5b90509050905061022052610220516101805142808210156104a657600080fd5b808203905090506040518111156104bc57600080fd5b808202808060008112156104cc57195b607f1c156104d957600080fd5b905090509050610200525b426101c05111156104fb5760006101a051136104fe565b60005b15610587576101a051630784ce008082058080600081121561051c57195b607f1c1561052957600080fd5b9050905090506102c0526102c0516101c051428082101561054957600080fd5b8082039050905060405181111561055f57600080fd5b8082028080600081121561056f57195b607f1c1561057c57600080fd5b9050905090506102a0525b60076101805160e05260c052604060c020546103405260006101c05118156105dc57610180516101c05114156105c45761034051610360526105db565b60076101c05160e05260c052604060c02054610360525b5b5b6103a0600081526000816020015242816040015243816060015260008160800152506000610380511115610691576103a0610380516c01431e0fae6d7217caa0000000811061062b57600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c0200154826080015250506106d0565b60206104c060246370a0823161044052306104605261045c6000545afa6106b757600080fd5b601f3d116106c457600080fd5b6000506104c051610420525b6103e051610440526104606103a0805182528060200151826020015280604001518260400152806060015182606001528060800151826080015250506000610500526103e05142111561078957670de0b6b3a764000043610400518082101561073857600080fd5b80820390509050808202821582848304141761075357600080fd5b80905090509050426103e0518082101561076c57600080fd5b80820390509050808061077e57600080fd5b820490509050610500525b6104405162093a808082049050905062093a8080820282158284830414176107b057600080fd5b8090509050905061052052610540600060ff818352015b610520805162093a808181830110156107df57600080fd5b808201905090508152506000610560524261052051111561080457426105205261081b565b60076105205160e05260c052604060c02054610560525b6103a080516103c05161052051610440518082101561083957600080fd5b8082039050905060405181111561084f57600080fd5b8082028080600081121561085f57195b607f1c1561086c57600080fd5b9050905090508082038080600081121561088257195b607f1c1561088f57600080fd5b9050905090508152506103c0805161056051808201808060008112156108b157195b607f1c156108be57600080fd5b90509050905081525060006103a05112156108da5760006103a0525b60006103c05112156108ed5760006103c0525b6105205161044052610520516103e0526104c05161050051610520516104a0518082101561091a57600080fd5b80820390509050808202821582848304141761093557600080fd5b80905090509050670de0b6b3a76400008082049050905081818301101561095b57600080fd5b80820190509050610400526103808051600181818301101561097c57600080fd5b80820190509050815250426105205114156109dd574361040052602061060060246370a0823161058052306105a05261059c6000545afa6109bc57600080fd5b601f3d116109c957600080fd5b6000506106005161042052610a5056610a3f565b610380516c01431e0fae6d7217caa000000081106109fa57600080fd5b600460c052602060c0200160c052602060c0206103a0805182558060200151600183015580604001516002830155806060015160038301558060800151600483015550505b5b81516001018083528114156107c7575b5050610380516003556000610140511815610b38576103c080516102c0516102205180820380806000811215610a8257195b607f1c15610a8f57600080fd5b90509050905080820180806000811215610aa557195b607f1c15610ab257600080fd5b9050905090508152506103a080516102a0516102005180820380806000811215610ad857195b607f1c15610ae557600080fd5b90509050905080820180806000811215610afb57195b607f1c15610b0857600080fd5b90509050905081525060006103c0511215610b245760006103c0525b60006103a0511215610b375760006103a0525b5b610380516c01431e0fae6d7217caa00000008110610b5557600080fd5b600460c052602060c0200160c052602060c0206103a0805182558060200151600183015580604001516002830155806060015160038301558060800151600483015550506000610140511815610d765742610180511115610c345761034080516102205180820180806000811215610bc957195b607f1c15610bd657600080fd5b905090509050815250610180516101c0511415610c1d5761034080516102c05180820380806000811215610c0657195b607f1c15610c1357600080fd5b9050905090508152505b6103405160076101805160e05260c052604060c020555b426101c0511115610c9457610180516101c0511115610c935761036080516102c05180820380806000811215610c6657195b607f1c15610c7357600080fd5b9050905090508152506103605160076101c05160e05260c052604060c020555b5b60066101405160e05260c052604060c020546001818183011015610cb757600080fd5b80820190509050610540526105405160066101405160e05260c052604060c02055426102e052436103005260026101405160e05260c052604060c02060c052602060c020546000811215610d0a57600080fd5b6103205261054051633b9aca008110610d2257600080fd5b60056101405160e05260c052604060c02060c052602060c0200160c052602060c0206102a0805182558060200151600183015580604001516002830155806060015160038301558060800151600483015550505b6101e051565b600015611024575b610200526101405261016052610180526101a0526101c0526101e0526102206101a080518252806020015182602001525050600154610260526102605161016051818183011015610dd457600080fd5b8082019050905060015561028061022080518252806020015182602001525050610220805161016051604051811115610e0c57600080fd5b80820180806000811215610e1c57195b607f1c15610e2957600080fd5b9050905090508152506000610180511815610e475761018051610240525b60026101405160e05260c052604060c02060c052602060c020610220805182558060200151600183015550506101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a051610140516102c0526102e061028080518252806020015182602001525050610320610220805182528060200151826020015250506103405161032051610300516102e0516102c0516006580161040e565b6102a05261028052610260526102405261022052610200526101e0526101c0526101a0526101805261016052610140526000506000610160511815610f8957602061038060646323b872dd6102c052610140516102e052306103005261016051610320526102dc60006000545af1610f6b57600080fd5b601f3d11610f7857600080fd5b60005061038051610f8857600080fd5b5b610160516102c0526101e0516102e052426103005261024051610140517f4566dfc29f6f11d13a418c26a02bef7c28bae749d4de47e4e6a7cddea6730d5960606102c0a3610260516102c0526102605161016051818183011015610fec57600080fd5b808201905090506102e0527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c60406102c0a161020051565b63c2c4c5c160005114156110b45760403661014037604036610180376101405161016051610180516101a05160006101c0526101e061014080518252806020015182602001525050610220610180805182528060200151826020015250506102405161022051610200516101e0516101c0516006580161040e565b6101a052610180526101605261014052600050005b633a46273e600051141561127c5762ffffff54156110d157600080fd5b600162ffffff5560043560a01c156110e857600080fd5b610140600260043560e05260c052604060c0208060c052602060c02054825260018160c052602060c02001548260200152505060006024351161112a57600080fd5b60006101405113151561117c576308c379a06101805260206101a05260166101c0527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006101e0526101c050606461019cfd5b42610160511115156111f2576308c379a06101805260206101a05260246101c0527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686101e0527f6472617700000000000000000000000000000000000000000000000000000000610200526101c050608461019cfd5b6101405161016051600435610180526024356101a05260006101c0526101e0600260043560e05260c052604060c0208060c052602060c02054825260018160c052602060c02001548260200152505060006102205261022051610200516101e0516101c0516101a0516101805160065801610d84565b6101605261014052600050600062ffffff55005b6365fc387360005114156114ce5762ffffff541561129957600080fd5b600162ffffff5533610140526101405160065801610207565b60005060243562093a808082049050905062093a8080820282158284830414176112db57600080fd5b809050905090506101405261016060023360e05260c052604060c0208060c052602060c02054825260018160c052602060c02001548260200152505060006004351161132657600080fd5b61016051151515611376576308c379a06101a05260206101c05260196101e0527f5769746864726177206f6c6420746f6b656e7320666972737400000000000000610200526101e05060646101bcfd5b42610140511115156113ec576308c379a06101a05260206101c05260266101e0527f43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e2074686520610200527f6675747572650000000000000000000000000000000000000000000000000000610220526101e05060846101bcfd5b42630784ce0081818301101561140157600080fd5b808201905090506101405111151515611459576308c379a06101a05260206101c052601e6101e0527f566f74696e67206c6f636b2063616e2062652034207965617273206d61780000610200526101e05060646101bcfd5b610140516101605161018051336101a0526004356101c052610140516101e052610200610160805182528060200151826020015250506001610240526102405161022051610200516101e0516101c0516101a05160065801610d84565b610180526101605261014052600050600062ffffff55005b634957677c600051141561167a5762ffffff54156114eb57600080fd5b600162ffffff5533610140526101405160065801610207565b60005061014060023360e05260c052604060c0208060c052602060c02054825260018160c052602060c02001548260200152505060006004351161154757600080fd5b600061014051131515611599576308c379a06101805260206101a05260166101c0527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006101e0526101c050606461019cfd5b426101605111151561160f576308c379a06101805260206101a05260246101c0527f43616e6e6f742061646420746f2065787069726564206c6f636b2e20576974686101e0527f6472617700000000000000000000000000000000000000000000000000000000610200526101c050608461019cfd5b610140516101605133610180526004356101a05260006101c0526101e06101408051825280602001518260200152505060026102205261022051610200516101e0516101c0516101a0516101805160065801610d84565b6101605261014052600050600062ffffff55005b63eff7a61260005114156118ed5762ffffff541561169757600080fd5b600162ffffff5533610140526101405160065801610207565b60005061014060023360e05260c052604060c0208060c052602060c02054825260018160c052602060c02001548260200152505060043562093a808082049050905062093a80808202821582848304141761170a57600080fd5b80905090509050610180524261016051111515611766576308c379a06101a05260206101c052600c6101e0527f4c6f636b20657870697265640000000000000000000000000000000000000000610200526101e05060646101bcfd5b6000610140511315156117b8576308c379a06101a05260206101c05260116101e0527f4e6f7468696e67206973206c6f636b6564000000000000000000000000000000610200526101e05060646101bcfd5b610160516101805111151561180c576308c379a06101a05260206101c052601f6101e0527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e00610200526101e05060646101bcfd5b42630784ce0081818301101561182157600080fd5b808201905090506101805111151515611879576308c379a06101a05260206101c052601e6101e0527f566f74696e67206c6f636b2063616e2062652034207965617273206d61780000610200526101e05060646101bcfd5b610140516101605161018051336101a05260006101c052610180516101e052610200610140805182528060200151826020015250506003610240526102405161022051610200516101e0516101c0516101a05160065801610d84565b610180526101605261014052600050600062ffffff55005b633ccfd60b6000511415611b875762ffffff541561190a57600080fd5b600162ffffff5561014060023360e05260c052604060c0208060c052602060c02054825260018160c052602060c0200154826020015250506101605142101515611955576001611959565b600a545b5b15156119a5576308c379a06101805260206101a05260166101c0527f546865206c6f636b206469646e277420657870697265000000000000000000006101e0526101c050606461019cfd5b6101405160008112156119b757600080fd5b610180526101a06101408051825280602001518260200152505060006101605260006101405260023360e05260c052604060c02060c052602060c020610140805182558060200151600183015550506001546101e0526101e0516101805180821015611a2257600080fd5b808203905090506001556101405161016051610180516101a0516101c0516101e05133610200526102206101a0805182528060200151826020015250506102606101408051825280602001518260200152505061028051610260516102405161022051610200516006580161040e565b6101e0526101c0526101a05261018052610160526101405260005060206102a0604463a9059cbb610200523361022052610180516102405261021c60006000545af1611add57600080fd5b601f3d11611aea57600080fd5b6000506102a051611afa57600080fd5b61018051610200524261022052337ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5686040610200a26101e051610200526101e0516101805180821015611b4c57600080fd5b80820390509050610220527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c6040610200a1600062ffffff55005b600015611c9c575b61018052610140526101605260006101a052610160516101c0526101e060006080818352015b6101c0516101a051101515611bc957611c88565b6101a0516101c051818183011015611be057600080fd5b808201905090506001818183011015611bf857600080fd5b8082019050905060028082049050905061020052610140516003610200516c01431e0fae6d7217caa00000008110611c2f57600080fd5b600460c052602060c0200160c052602060c0200154111515611c5857610200516101a052611c77565b61020051600180821015611c6b57600080fd5b808203905090506101c0525b5b8151600101808352811415611bb5575b50506101a051600052600051610180515650005b6370a082316000511415611cb4574261014052611cd9565b62fdd58e6000511415611cd1576020602461014037600050611cd9565b600015611e93575b60043560a01c15611ce957600080fd5b600660043560e05260c052604060c0205461016052610160511515611d1857600060005260206000f350611e91565b61018061016051633b9aca008110611d2f57600080fd5b600560043560e05260c052604060c02060c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c02001548260800152505061018080516101a051610140516101c05180821015611dbc57600080fd5b80820390509050604051811115611dd257600080fd5b80820280806000811215611de257195b607f1c15611def57600080fd5b90509050905080820380806000811215611e0557195b607f1c15611e1257600080fd5b9050905090508152506000610180511215611e2e576000610180525b610180516000811215611e4057600080fd5b61022052610200516003610220518082028215828483041417611e6257600080fd5b80905090509050818183011015611e7857600080fd5b80820190509050610240526102405160005260206000f3505b005b634ee2cd7e60005114156124075760043560a01c15611eb157600080fd5b436024351115611ec057600080fd5b600061014052600660043560e05260c052604060c020546101605261018060006080818352015b6101605161014051101515611efb57611fbe565b6101405161016051818183011015611f1257600080fd5b808201905090506001818183011015611f2a57600080fd5b808201905090506002808204905090506101a05260243560036101a051633b9aca008110611f5757600080fd5b600560043560e05260c052604060c02060c052602060c0200160c052602060c0200154111515611f8e576101a05161014052611fad565b6101a051600180821015611fa157600080fd5b80820390509050610160525b5b8151600101808352811415611ee7575b505061018061014051633b9aca008110611fd757600080fd5b600560043560e05260c052604060c02060c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c020015482608001525050600354610220526101405161016051610180516101a0516101c0516101e051610200516102205161024051602435610260526102205161028052610280516102605160065801611b8f565b6102e0526102405261022052610200526101e0526101c0526101a0526101805261016052610140526102e05161024052610260610240516c01431e0fae6d7217caa000000081106120e157600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c02001548260800152505060403661030037610220516102405110156122355761034061024051600181818301101561216f57600080fd5b808201905090506c01431e0fae6d7217caa0000000811061218f57600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c0200154826080015250506103a0516102c0518082101561220557600080fd5b8082039050905061030052610380516102a0518082101561222557600080fd5b8082039050905061032052612270565b436102c0518082101561224757600080fd5b8082039050905061030052426102a0518082101561226457600080fd5b80820390509050610320525b6102a0516103405260006103005118156122f2576103408051610320516024356102c051808210156122a157600080fd5b8082039050905080820282158284830414176122bc57600080fd5b809050905090506103005180806122d257600080fd5b8204905090508181830110156122e757600080fd5b808201905090508152505b61018080516101a051610340516101c0518082101561231057600080fd5b8082039050905060405181111561232657600080fd5b8082028080600081121561233657195b607f1c1561234357600080fd5b9050905090508082038080600081121561235957195b607f1c1561236657600080fd5b90509050905081525061018051600081121561238157600080fd5b610360526102005160036103605180820282158284830414176123a357600080fd5b809050905090508181830110156123b957600080fd5b80820190509050610380526000610180511215156123d85760016123e1565b60006102005110155b5b156123f9576103805160005260206000f350612405565b600060005260206000f3505b005b60001561264b575b610200526101405261016052610180526101a0526101c0526101e052610220610140805182528060200151826020015280604001518260400152806060015182606001528060800151826080015250506102605162093a808082049050905062093a80808202821582848304141761248657600080fd5b809050905090506102c0526102e0600060ff818352015b6102c0805162093a808181830110156124b557600080fd5b808201905090508152506000610300526101e0516102c05111156124e0576101e0516102c0526124f7565b60076102c05160e05260c052604060c02054610300525b6102208051610240516102c051610260518082101561251557600080fd5b8082039050905060405181111561252b57600080fd5b8082028080600081121561253b57195b607f1c1561254857600080fd5b9050905090508082038080600081121561255e57195b607f1c1561256b57600080fd5b9050905090508152506101e0516102c0511415612587576125cf565b610240805161030051808201808060008112156125a057195b607f1c156125ad57600080fd5b9050905090508152506102c051610260525b815160010180835281141561249d575b505060006102205112156125e4576000610220525b6102205160008112156125f657600080fd5b6102e0526102a05160036102e051808202821582848304141761261857600080fd5b8090509050905081818301101561262e57600080fd5b808201905090506103005261030051600052600051610200515650005b6318160ddd6000511415612663574261014052612689565b63bd85b0396000511415612681576020600461014037600050612689565b6000156127b9575b60035461016052610180610160516c01431e0fae6d7217caa000000081106126b057600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c0200154826080015250506101405161016051610180516101a0516101c0516101e0516102005161022061018080518252806020015182602001528060400151826040015280606001518260600152806080015182608001525050610140516102c0526102c0516102a051610280516102605161024051610220516006580161240f565b61032052610200526101e0526101c0526101a0526101805261016052610140526103205160005260206000f350005b63981b24d06000511415612b32574360043511156127d657600080fd5b60035461014052610140516101605160043561018052610140516101a0526101a0516101805160065801611b8f565b6102005261016052610140526102005161016052610180610160516c01431e0fae6d7217caa0000000811061283957600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c020015482608001525050600061022052610140516101605110156129de576102406101605160018181830110156128c657600080fd5b808201905090506c01431e0fae6d7217caa000000081106128e657600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c0200154826080015250506102a0516101e05118156129d9576004356101e0518082101561296957600080fd5b80820390509050610280516101c0518082101561298557600080fd5b8082039050905080820282158284830414176129a057600080fd5b809050905090506102a0516101e051808210156129bc57600080fd5b8082039050905080806129ce57600080fd5b820490509050610220525b612a68565b436101e0511815612a67576004356101e051808210156129fd57600080fd5b80820390509050426101c05180821015612a1657600080fd5b808203905090508082028215828483041417612a3157600080fd5b80905090509050436101e05180821015612a4a57600080fd5b808203905090508080612a5c57600080fd5b820490509050610220525b5b6101405161016051610180516101a0516101c0516101e0516102005161022051610240610180805182528060200151826020015280604001518260400152806060015182606001528060800151826080015250506101c05161022051818183011015612ad357600080fd5b808201905090506102e0526102e0516102c0516102a0516102805161026051610240516006580161240f565b6103405261022052610200526101e0526101c0526101a0526101805261016052610140526103405160005260206000f350005b63c3ad89566000511415612b855760206101c060246370a0823161014052306101605261015c6000545afa612b6657600080fd5b601f3d11612b7357600080fd5b6000506101c05160005260206000f350005b634f8ab24f6000511415612c7557436004351115612ba257600080fd5b60035461014052610140516101605160043561018052610140516101a0526101a0516101805160065801611b8f565b6102005261016052610140526102005161016052610180610160516c01431e0fae6d7217caa00000008110612c0557600080fd5b600460c052602060c020018060c052602060c02054825260018160c052602060c0200154826020015260028160c052602060c0200154826040015260038160c052602060c0200154826060015260048160c052602060c0200154826080015250506102005160005260206000f350005b633cebb8236000511415612ca95760043560a01c15612c9357600080fd5b6008543314612ca157600080fd5b600435600855005b63fc0c546a6000511415612cc55760005460005260206000f350005b63047fc9aa6000511415612ce15760015460005260206000f350005b63cbf9fe5f6000511415612d505760043560a01c15612cff57600080fd5b600260043560e05260c052604060c0206101408080808460c052602060c0205481525050602081019050808060018560c052602060c02001548152505060409050905060c05260c051610140f39050005b63900cf0cf6000511415612d6c5760035460005260206000f350005b63d1febfb96000511415612e2d576004356c01431e0fae6d7217caa00000008110612d9657600080fd5b600460c052602060c020016101408080808460c052602060c0205481525050602081019050808060018560c052602060c020015481525050602081019050808060028560c052602060c020015481525050602081019050808060038560c052602060c020015481525050602081019050808060048560c052602060c02001548152505060a09050905060c05260c051610140f39050005b6328d09d476000511415612f035760043560a01c15612e4b57600080fd5b602435633b9aca008110612e5e57600080fd5b600560043560e05260c052604060c02060c052602060c020016101408080808460c052602060c0205481525050602081019050808060018560c052602060c020015481525050602081019050808060028560c052602060c020015481525050602081019050808060038560c052602060c020015481525050602081019050808060048560c052602060c02001548152505060a09050905060c05260c051610140f39050005b63010ae7576000511415612f3d5760043560a01c15612f2157600080fd5b600660043560e05260c052604060c0205460005260206000f350005b63711974846000511415612f6757600760043560e05260c052604060c0205460005260206000f350005b63f77c47916000511415612f835760085460005260206000f350005b63bef97c876000511415612f9f5760095460005260206000f350005b63f89464856000511415612fbb57600a5460005260206000f350005b6306fdde03600051141561306457600b8060c052602060c020610180602082540161012060006003818352015b82610120516020021115612ffb5761301d565b61012051850154610120516020028501525b8151600101808352811415612fe8575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b6395d89b41600051141561310d57600c8060c052602060c020610180602082540161012060006002818352015b826101205160200211156130a4576130c6565b61012051850154610120516020028501525b8151600101808352811415613091575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b6354fd4d5060005114156131b657600d8060c052602060c020610180602082540161012060006002818352015b8261012051602002111561314d5761316f565b61012051850154610120516020028501525b815160010180835281141561313a575b50505050505061018051806101a001818260206001820306601f82010390500336823750506020610160526040610180510160206001820306601f8201039050610160f350005b63313ce56760005114156131d257600e5460005260206000f350005b638ff36fd160005114156131ee57600f5460005260206000f350005b637175d4f7600051141561320a5760105460005260206000f350005b63f851a44060005114156132265760115460005260206000f350005b6317f7182a60005114156132425760125460005260206000f350005b5b60006000fd
Verified Source Code Partial Match
Compiler: v0.2.8+commit.069936f
Vyper_contract.vy 756 lines
# @version 0.2.8
"""
@title Voting Escrow
@author Curve Finance
@license MIT
@notice Votes have a weight depending on time, so that users are
committed to the future of (whatever they are voting for)
@dev Vote weight decays linearly over time. Lock time cannot be
more than `MAXTIME` (4 years).
"""
# ====================================================================
# | ______ _______ |
# | / _____________ __ __ / ____(_____ ____ _____ ________ |
# | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
# | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
# | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
# | |
# ====================================================================
# =============================== veFXS ==============================
# ====================================================================
# Frax Finance: https://github.com/FraxFinance
# Original idea and credit:
# Curve Finance's veCRV
# https://resources.curve.fi/faq/vote-locking-boost
# https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy
# veFXS is basically a fork, with the key difference that 1 FXS locked for 1 second would be ~ 1 veFXS,
# As opposed to ~ 0 veFXS (as it is with veCRV)
# Frax Reviewer(s) / Contributor(s)
# Travis Moore: https://github.com/FortisFortuna
# Jason Huan: https://github.com/jasonhuan
# Sam Kazemian: https://github.com/samkazemian
# Voting escrow to have time-weighted votes
# Votes have a weight depending on time, so that users are committed
# to the future of (whatever they are voting for).
# The weight in this implementation is linear, and lock cannot be more than maxtime:
# w ^
# 1 + /
# | /
# | /
# | /
# |/
# 0 +--------+------> time
# maxtime (4 years?)
struct Point:
bias: int128
slope: int128 # - dweight / dt
ts: uint256
blk: uint256 # block
fxs_amt: uint256
# We cannot really do block numbers per se b/c slope is per time, not per block
# and per block could be fairly bad b/c Ethereum changes blocktimes.
# What we can do is to extrapolate ***At functions
struct LockedBalance:
amount: int128
end: uint256
interface ERC20:
def decimals() -> uint256: view
def balanceOf(addr: address) -> uint256: view
def name() -> String[64]: view
def symbol() -> String[32]: view
def transfer(to: address, amount: uint256) -> bool: nonpayable
def transferFrom(spender: address, to: address, amount: uint256) -> bool: nonpayable
# Interface for checking whether address belongs to a whitelisted
# type of a smart wallet.
# When new types are added - the whole contract is changed
# The check() method is modifying to be able to use caching
# for individual wallet addresses
interface SmartWalletChecker:
def check(addr: address) -> bool: nonpayable
DEPOSIT_FOR_TYPE: constant(int128) = 0
CREATE_LOCK_TYPE: constant(int128) = 1
INCREASE_LOCK_AMOUNT: constant(int128) = 2
INCREASE_UNLOCK_TIME: constant(int128) = 3
event CommitOwnership:
admin: address
event ApplyOwnership:
admin: address
event Deposit:
provider: indexed(address)
value: uint256
locktime: indexed(uint256)
type: int128
ts: uint256
event Withdraw:
provider: indexed(address)
value: uint256
ts: uint256
event Supply:
prevSupply: uint256
supply: uint256
WEEK: constant(uint256) = 7 * 86400 # all future times are rounded by week
MAXTIME: constant(uint256) = 4 * 365 * 86400 # 4 years
MULTIPLIER: constant(uint256) = 10 ** 18
VOTE_WEIGHT_MULTIPLIER: constant(uint256) = 4 - 1 # 4x gives 300% boost at 4 years
token: public(address)
supply: public(uint256)
locked: public(HashMap[address, LockedBalance])
epoch: public(uint256)
point_history: public(Point[100000000000000000000000000000]) # epoch -> unsigned point
user_point_history: public(HashMap[address, Point[1000000000]]) # user -> Point[user_epoch]
user_point_epoch: public(HashMap[address, uint256])
slope_changes: public(HashMap[uint256, int128]) # time -> signed slope change
# Aragon's view methods for compatibility
controller: public(address)
transfersEnabled: public(bool)
# Emergency Unlock
emergencyUnlockActive: public(bool)
# ERC20 related
name: public(String[64])
symbol: public(String[32])
version: public(String[32])
decimals: public(uint256)
# Checker for whitelisted (smart contract) wallets which are allowed to deposit
# The goal is to prevent tokenizing the escrow
future_smart_wallet_checker: public(address)
smart_wallet_checker: public(address)
admin: public(address) # Can and will be a smart contract
future_admin: public(address)
@external
def __init__(token_addr: address, _name: String[64], _symbol: String[32], _version: String[32]):
"""
@notice Contract constructor
@param token_addr `ERC20CRV` token address
@param _name Token name
@param _symbol Token symbol
@param _version Contract version - required for Aragon compatibility
"""
self.admin = msg.sender
self.token = token_addr
self.point_history[0].blk = block.number
self.point_history[0].ts = block.timestamp
self.point_history[0].fxs_amt = 0
self.controller = msg.sender
self.transfersEnabled = True
_decimals: uint256 = ERC20(token_addr).decimals()
assert _decimals <= 255
self.decimals = _decimals
self.name = _name
self.symbol = _symbol
self.version = _version
@external
def commit_transfer_ownership(addr: address):
"""
@notice Transfer ownership of VotingEscrow contract 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 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)
@external
def commit_smart_wallet_checker(addr: address):
"""
@notice Set an external contract to check for approved smart contract wallets
@param addr Address of Smart contract checker
"""
assert msg.sender == self.admin
self.future_smart_wallet_checker = addr
@external
def apply_smart_wallet_checker():
"""
@notice Apply setting external contract to check approved smart contract wallets
"""
assert msg.sender == self.admin
self.smart_wallet_checker = self.future_smart_wallet_checker
@external
def toggleEmergencyUnlock():
"""
@dev Used to allow early withdrawals of veFXS back into FXS, in case of an emergency
"""
assert msg.sender == self.admin # dev: admin only
self.emergencyUnlockActive = not (self.emergencyUnlockActive)
@external
def recoverERC20(token_addr: address, amount: uint256):
"""
@dev Used to recover non-FXS ERC20 tokens
"""
assert msg.sender == self.admin # dev: admin only
assert token_addr != self.token # Cannot recover FXS. Use toggleEmergencyUnlock instead and have users pull theirs out individually
ERC20(token_addr).transfer(self.admin, amount)
@internal
def assert_not_contract(addr: address):
"""
@notice Check if the call is from a whitelisted smart contract, revert if not
@param addr Address to be checked
"""
if addr != tx.origin:
checker: address = self.smart_wallet_checker
if checker != ZERO_ADDRESS:
if SmartWalletChecker(checker).check(addr):
return
raise "Smart contract depositors not allowed"
@external
@view
def get_last_user_slope(addr: address) -> int128:
"""
@notice Get the most recently recorded rate of voting power decrease for `addr`
@param addr Address of the user wallet
@return Value of the slope
"""
uepoch: uint256 = self.user_point_epoch[addr]
return self.user_point_history[addr][uepoch].slope
@external
@view
def user_point_history__ts(_addr: address, _idx: uint256) -> uint256:
"""
@notice Get the timestamp for checkpoint `_idx` for `_addr`
@param _addr User wallet address
@param _idx User epoch number
@return Epoch time of the checkpoint
"""
return self.user_point_history[_addr][_idx].ts
@external
@view
def locked__end(_addr: address) -> uint256:
"""
@notice Get timestamp when `_addr`'s lock finishes
@param _addr User wallet
@return Epoch time of the lock end
"""
return self.locked[_addr].end
@internal
def _checkpoint(addr: address, old_locked: LockedBalance, new_locked: LockedBalance):
"""
@notice Record global and per-user data to checkpoint
@param addr User's wallet address. No user checkpoint if 0x0
@param old_locked Pevious locked amount / end lock time for the user
@param new_locked New locked amount / end lock time for the user
"""
u_old: Point = empty(Point)
u_new: Point = empty(Point)
old_dslope: int128 = 0
new_dslope: int128 = 0
_epoch: uint256 = self.epoch
if addr != ZERO_ADDRESS:
# Calculate slopes and biases
# Kept at zero when they have to
if old_locked.end > block.timestamp and old_locked.amount > 0:
u_old.slope = old_locked.amount / MAXTIME
u_old.bias = u_old.slope * convert(old_locked.end - block.timestamp, int128)
if new_locked.end > block.timestamp and new_locked.amount > 0:
u_new.slope = new_locked.amount / MAXTIME
u_new.bias = u_new.slope * convert(new_locked.end - block.timestamp, int128)
# Read values of scheduled changes in the slope
# old_locked.end can be in the past and in the future
# new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros
old_dslope = self.slope_changes[old_locked.end]
if new_locked.end != 0:
if new_locked.end == old_locked.end:
new_dslope = old_dslope
else:
new_dslope = self.slope_changes[new_locked.end]
last_point: Point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number, fxs_amt: 0})
if _epoch > 0:
last_point = self.point_history[_epoch]
else:
last_point.fxs_amt = ERC20(self.token).balanceOf(self) # saves gas by only calling once
last_checkpoint: uint256 = last_point.ts
# initial_last_point is used for extrapolation to calculate block number
# (approximately, for *At methods) and save them
# as we cannot figure that out exactly from inside the contract
initial_last_point: Point = last_point
block_slope: uint256 = 0 # dblock/dt
if block.timestamp > last_point.ts:
block_slope = MULTIPLIER * (block.number - last_point.blk) / (block.timestamp - last_point.ts)
# If last point is already recorded in this block, slope=0
# But that's ok b/c we know the block in such case
# Go over weeks to fill history and calculate what the current point is
t_i: uint256 = (last_checkpoint / WEEK) * WEEK
for i in range(255):
# Hopefully it won't happen that this won't get used in 5 years!
# If it does, users will be able to withdraw but vote weight will be broken
t_i += WEEK
d_slope: int128 = 0
if t_i > block.timestamp:
t_i = block.timestamp
else:
d_slope = self.slope_changes[t_i]
last_point.bias -= last_point.slope * convert(t_i - last_checkpoint, int128)
last_point.slope += d_slope
if last_point.bias < 0: # This can happen
last_point.bias = 0
if last_point.slope < 0: # This cannot happen - just in case
last_point.slope = 0
last_checkpoint = t_i
last_point.ts = t_i
last_point.blk = initial_last_point.blk + block_slope * (t_i - initial_last_point.ts) / MULTIPLIER
_epoch += 1
# Fill for the current block, if applicable
if t_i == block.timestamp:
last_point.blk = block.number
last_point.fxs_amt = ERC20(self.token).balanceOf(self)
break
else:
self.point_history[_epoch] = last_point
self.epoch = _epoch
# Now point_history is filled until t=now
if addr != ZERO_ADDRESS:
# If last point was in this block, the slope change has been applied already
# But in such case we have 0 slope(s)
last_point.slope += (u_new.slope - u_old.slope)
last_point.bias += (u_new.bias - u_old.bias)
if last_point.slope < 0:
last_point.slope = 0
if last_point.bias < 0:
last_point.bias = 0
# Record the changed point into history
self.point_history[_epoch] = last_point
if addr != ZERO_ADDRESS:
# Schedule the slope changes (slope is going down)
# We subtract new_user_slope from [new_locked.end]
# and add old_user_slope to [old_locked.end]
if old_locked.end > block.timestamp:
# old_dslope was <something> - u_old.slope, so we cancel that
old_dslope += u_old.slope
if new_locked.end == old_locked.end:
old_dslope -= u_new.slope # It was a new deposit, not extension
self.slope_changes[old_locked.end] = old_dslope
if new_locked.end > block.timestamp:
if new_locked.end > old_locked.end:
new_dslope -= u_new.slope # old slope disappeared at this point
self.slope_changes[new_locked.end] = new_dslope
# else: we recorded it already in old_dslope
# Now handle user history
user_epoch: uint256 = self.user_point_epoch[addr] + 1
self.user_point_epoch[addr] = user_epoch
u_new.ts = block.timestamp
u_new.blk = block.number
u_new.fxs_amt = convert(self.locked[addr].amount, uint256)
self.user_point_history[addr][user_epoch] = u_new
@internal
def _deposit_for(_addr: address, _value: uint256, unlock_time: uint256, locked_balance: LockedBalance, type: int128):
"""
@notice Deposit and lock tokens for a user
@param _addr User's wallet address
@param _value Amount to deposit
@param unlock_time New time when to unlock the tokens, or 0 if unchanged
@param locked_balance Previous locked amount / timestamp
"""
_locked: LockedBalance = locked_balance
supply_before: uint256 = self.supply
self.supply = supply_before + _value
old_locked: LockedBalance = _locked
# Adding to existing lock, or if a lock is expired - creating a new one
_locked.amount += convert(_value, int128)
if unlock_time != 0:
_locked.end = unlock_time
self.locked[_addr] = _locked
# Possibilities:
# Both old_locked.end could be current or expired (>/< block.timestamp)
# value == 0 (extend lock) or value > 0 (add to lock or extend lock)
# _locked.end > block.timestamp (always)
self._checkpoint(_addr, old_locked, _locked)
if _value != 0:
assert ERC20(self.token).transferFrom(_addr, self, _value)
log Deposit(_addr, _value, _locked.end, type, block.timestamp)
log Supply(supply_before, supply_before + _value)
@external
def checkpoint():
"""
@notice Record global data to checkpoint
"""
self._checkpoint(ZERO_ADDRESS, empty(LockedBalance), empty(LockedBalance))
@external
@nonreentrant('lock')
def deposit_for(_addr: address, _value: uint256):
"""
@notice Deposit `_value` tokens for `_addr` and add to the lock
@dev Anyone (even a smart contract) can deposit for someone else, but
cannot extend their locktime and deposit for a brand new user
@param _addr User's wallet address
@param _value Amount to add to user's lock
"""
_locked: LockedBalance = self.locked[_addr]
assert _value > 0 # dev: need non-zero value
assert _locked.amount > 0, "No existing lock found"
assert _locked.end > block.timestamp, "Cannot add to expired lock. Withdraw"
self._deposit_for(_addr, _value, 0, self.locked[_addr], DEPOSIT_FOR_TYPE)
@external
@nonreentrant('lock')
def create_lock(_value: uint256, _unlock_time: uint256):
"""
@notice Deposit `_value` tokens for `msg.sender` and lock until `_unlock_time`
@param _value Amount to deposit
@param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
"""
self.assert_not_contract(msg.sender)
unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks
_locked: LockedBalance = self.locked[msg.sender]
assert _value > 0 # dev: need non-zero value
assert _locked.amount == 0, "Withdraw old tokens first"
assert unlock_time > block.timestamp, "Can only lock until time in the future"
assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 4 years max"
self._deposit_for(msg.sender, _value, unlock_time, _locked, CREATE_LOCK_TYPE)
@external
@nonreentrant('lock')
def increase_amount(_value: uint256):
"""
@notice Deposit `_value` additional tokens for `msg.sender`
without modifying the unlock time
@param _value Amount of tokens to deposit and add to the lock
"""
self.assert_not_contract(msg.sender)
_locked: LockedBalance = self.locked[msg.sender]
assert _value > 0 # dev: need non-zero value
assert _locked.amount > 0, "No existing lock found"
assert _locked.end > block.timestamp, "Cannot add to expired lock. Withdraw"
self._deposit_for(msg.sender, _value, 0, _locked, INCREASE_LOCK_AMOUNT)
@external
@nonreentrant('lock')
def increase_unlock_time(_unlock_time: uint256):
"""
@notice Extend the unlock time for `msg.sender` to `_unlock_time`
@param _unlock_time New epoch time for unlocking
"""
self.assert_not_contract(msg.sender)
_locked: LockedBalance = self.locked[msg.sender]
unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks
assert _locked.end > block.timestamp, "Lock expired"
assert _locked.amount > 0, "Nothing is locked"
assert unlock_time > _locked.end, "Can only increase lock duration"
assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 4 years max"
self._deposit_for(msg.sender, 0, unlock_time, _locked, INCREASE_UNLOCK_TIME)
@external
@nonreentrant('lock')
def withdraw():
"""
@notice Withdraw all tokens for `msg.sender`
@dev Only possible if the lock has expired
"""
_locked: LockedBalance = self.locked[msg.sender]
assert ((block.timestamp >= _locked.end) or (self.emergencyUnlockActive)), "The lock didn't expire"
value: uint256 = convert(_locked.amount, uint256)
old_locked: LockedBalance = _locked
_locked.end = 0
_locked.amount = 0
self.locked[msg.sender] = _locked
supply_before: uint256 = self.supply
self.supply = supply_before - value
# old_locked can have either expired <= timestamp or zero end
# _locked has only 0 end
# Both can have >= 0 amount
self._checkpoint(msg.sender, old_locked, _locked)
assert ERC20(self.token).transfer(msg.sender, value)
log Withdraw(msg.sender, value, block.timestamp)
log Supply(supply_before, supply_before - value)
# The following ERC20/minime-compatible methods are not real balanceOf and supply!
# They measure the weights for the purpose of voting, so they don't represent
# real coins.
# FRAX adds minimal 1-1 FXS/veFXS, as well as a voting multiplier
@internal
@view
def find_block_epoch(_block: uint256, max_epoch: uint256) -> uint256:
"""
@notice Binary search to estimate timestamp for block number
@param _block Block to find
@param max_epoch Don't go beyond this epoch
@return Approximate timestamp for block
"""
# Binary search
_min: uint256 = 0
_max: uint256 = max_epoch
for i in range(128): # Will be always enough for 128-bit numbers
if _min >= _max:
break
_mid: uint256 = (_min + _max + 1) / 2
if self.point_history[_mid].blk <= _block:
_min = _mid
else:
_max = _mid - 1
return _min
@external
@view
def balanceOf(addr: address, _t: uint256 = block.timestamp) -> uint256:
"""
@notice Get the current voting power for `msg.sender`
@dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility
@param addr User wallet address
@param _t Epoch time to return voting power at
@return User voting power
"""
_epoch: uint256 = self.user_point_epoch[addr]
if _epoch == 0:
return 0
else:
last_point: Point = self.user_point_history[addr][_epoch]
last_point.bias -= last_point.slope * convert(_t - last_point.ts, int128)
if last_point.bias < 0:
last_point.bias = 0
unweighted_supply: uint256 = convert(last_point.bias, uint256) # Original from veCRV
weighted_supply: uint256 = last_point.fxs_amt + (VOTE_WEIGHT_MULTIPLIER * unweighted_supply)
return weighted_supply
@external
@view
def balanceOfAt(addr: address, _block: uint256) -> uint256:
"""
@notice Measure voting power of `addr` at block height `_block`
@dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime
@param addr User's wallet address
@param _block Block to calculate the voting power at
@return Voting power
"""
# Copying and pasting totalSupply code because Vyper cannot pass by
# reference yet
assert _block <= block.number
# Binary search
_min: uint256 = 0
_max: uint256 = self.user_point_epoch[addr]
for i in range(128): # Will be always enough for 128-bit numbers
if _min >= _max:
break
_mid: uint256 = (_min + _max + 1) / 2
if self.user_point_history[addr][_mid].blk <= _block:
_min = _mid
else:
_max = _mid - 1
upoint: Point = self.user_point_history[addr][_min]
max_epoch: uint256 = self.epoch
_epoch: uint256 = self.find_block_epoch(_block, max_epoch)
point_0: Point = self.point_history[_epoch]
d_block: uint256 = 0
d_t: uint256 = 0
if _epoch < max_epoch:
point_1: Point = self.point_history[_epoch + 1]
d_block = point_1.blk - point_0.blk
d_t = point_1.ts - point_0.ts
else:
d_block = block.number - point_0.blk
d_t = block.timestamp - point_0.ts
block_time: uint256 = point_0.ts
if d_block != 0:
block_time += d_t * (_block - point_0.blk) / d_block
upoint.bias -= upoint.slope * convert(block_time - upoint.ts, int128)
unweighted_supply: uint256 = convert(upoint.bias, uint256) # Original from veCRV
weighted_supply: uint256 = upoint.fxs_amt + (VOTE_WEIGHT_MULTIPLIER * unweighted_supply)
if ((upoint.bias >= 0) or (upoint.fxs_amt >= 0)):
return weighted_supply
else:
return 0
@internal
@view
def supply_at(point: Point, t: uint256) -> uint256:
"""
@notice Calculate total voting power at some point in the past
@param point The point (bias/slope) to start search from
@param t Time to calculate the total voting power at
@return Total voting power at that time
"""
last_point: Point = point
t_i: uint256 = (last_point.ts / WEEK) * WEEK
for i in range(255):
t_i += WEEK
d_slope: int128 = 0
if t_i > t:
t_i = t
else:
d_slope = self.slope_changes[t_i]
last_point.bias -= last_point.slope * convert(t_i - last_point.ts, int128)
if t_i == t:
break
last_point.slope += d_slope
last_point.ts = t_i
if last_point.bias < 0:
last_point.bias = 0
unweighted_supply: uint256 = convert(last_point.bias, uint256) # Original from veCRV
weighted_supply: uint256 = last_point.fxs_amt + (VOTE_WEIGHT_MULTIPLIER * unweighted_supply)
return weighted_supply
@external
@view
def totalSupply(t: uint256 = block.timestamp) -> uint256:
"""
@notice Calculate total voting power
@dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility
@return Total voting power
"""
_epoch: uint256 = self.epoch
last_point: Point = self.point_history[_epoch]
return self.supply_at(last_point, t)
@external
@view
def totalSupplyAt(_block: uint256) -> uint256:
"""
@notice Calculate total voting power at some point in the past
@param _block Block to calculate the total voting power at
@return Total voting power at `_block`
"""
assert _block <= block.number
_epoch: uint256 = self.epoch
target_epoch: uint256 = self.find_block_epoch(_block, _epoch)
point: Point = self.point_history[target_epoch]
dt: uint256 = 0
if target_epoch < _epoch:
point_next: Point = self.point_history[target_epoch + 1]
if point.blk != point_next.blk:
dt = (_block - point.blk) * (point_next.ts - point.ts) / (point_next.blk - point.blk)
else:
if point.blk != block.number:
dt = (_block - point.blk) * (block.timestamp - point.ts) / (block.number - point.blk)
# Now dt contains info on how far are we beyond point
return self.supply_at(point, point.ts + dt)
# Dummy methods for compatibility with Aragon
@external
@view
def totalFXSSupply() -> uint256:
"""
@notice Calculate FXS supply
@dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility
@return Total FXS supply
"""
return ERC20(self.token).balanceOf(self)
@external
@view
def totalFXSSupplyAt(_block: uint256) -> uint256:
"""
@notice Calculate total FXS at some point in the past
@param _block Block to calculate the total voting power at
@return Total FXS supply at `_block`
"""
assert _block <= block.number
_epoch: uint256 = self.epoch
target_epoch: uint256 = self.find_block_epoch(_block, _epoch)
point: Point = self.point_history[target_epoch]
return point.fxs_amt
@external
def changeController(_newController: address):
"""
@dev Dummy method required for Aragon compatibility
"""
assert msg.sender == self.controller
self.controller = _newController
Read Contract
admin 0xf851a440 → address
balanceOf 0x70a08231 → uint256
balanceOf 0x00fdd58e → uint256
balanceOfAt 0x4ee2cd7e → uint256
controller 0xf77c4791 → address
decimals 0x313ce567 → uint256
emergencyUnlockActive 0xf8946485 → bool
epoch 0x900cf0cf → uint256
future_admin 0x17f7182a → address
future_smart_wallet_checker 0x8ff36fd1 → address
get_last_user_slope 0x7c74a174 → int128
locked 0xcbf9fe5f → int128, uint256
locked__end 0xadc63589 → uint256
name 0x06fdde03 → string
point_history 0xd1febfb9 → int128, int128, uint256, uint256, uint256
slope_changes 0x71197484 → int128
smart_wallet_checker 0x7175d4f7 → address
supply 0x047fc9aa → uint256
symbol 0x95d89b41 → string
token 0xfc0c546a → address
totalFXSSupply 0xc3ad8956 → uint256
totalFXSSupplyAt 0x4f8ab24f → uint256
totalSupply 0x18160ddd → uint256
totalSupply 0xbd85b039 → uint256
totalSupplyAt 0x981b24d0 → uint256
transfersEnabled 0xbef97c87 → bool
user_point_epoch 0x010ae757 → uint256
user_point_history 0x28d09d47 → int128, int128, uint256, uint256, uint256
user_point_history__ts 0xda020a18 → uint256
version 0x54fd4d50 → string
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
apply_smart_wallet_checker 0x8e5b490f
No parameters
apply_transfer_ownership 0x6a1c05ae
No parameters
changeController 0x3cebb823
address _newController
checkpoint 0xc2c4c5c1
No parameters
commit_smart_wallet_checker 0x57f901e2
address addr
commit_transfer_ownership 0x6b441a40
address addr
create_lock 0x65fc3873
uint256 _value
uint256 _unlock_time
deposit_for 0x3a46273e
address _addr
uint256 _value
increase_amount 0x4957677c
uint256 _value
increase_unlock_time 0xeff7a612
uint256 _unlock_time
recoverERC20 0x8980f11f
address token_addr
uint256 amount
toggleEmergencyUnlock 0x88c2b3e3
No parameters
withdraw 0x3ccfd60b
No parameters
Recent Transactions
No transactions found for this address