Address Contract Partially Verified
Address
0xaade9230AA9161880E13a38C83400d3D1995267b
Balance
0 ETH
Nonce
1
Code Size
22080 bytes
Creator
0x5AE28c91...0FEF at tx 0xcc5e471d...ac0f39
Indexed Transactions
0
Contract Bytecode
22080 bytes
0x5f3560e01c60026035820660011b61547601601e395f51565b635457ff7b811861005357602436103417615472576004358060a01c6154725760405260026040516020525f5260405f205460605260206060f35b635449b9cb81186100775734615472576801000000000000000a5460405260206040f35b631b1800e381186130ba57346154725760206155805f395f5163095a0fc6606052602060606004607c845afa6100af573d5f5f3e3d5ffd5b60203d1061547257606090505160405260035460605260045460805260605160405180820281158383830414171561547257905090506080518015615472578082049050905068010000000000000007548082018281106154725790509050606052680100000000000000065460a05260a05160605160a051808281188284110218905090500360c052602060c0f36130ba565b63e1ec3c688118610177576024361034176154725760043567fffffffffffffffe8111615472576005015460405260206040f35b6322c7145381186107345760a43610341761547257608435610340525b6004358060a01c61547257610300526064358060011c61547257610320525f546002146154725760206155805f395f5163b461100d6103a052610300516103c05260406103a060246103bc845afa6101ee573d5f5f3e3d5ffd5b60403d10615472576103a09050805161036052602081015161038052506103005160405261021d6103c061349e565b6103c0518060ff1c615472576103a052610340516103c0525f6103e0526103a0511561027b576002610300516020525f5260405f20548060ff1c615472576103e0526001610360516103805103015f8112615472576103c0526102b8565b68010000000000000009548060ff1c615472576103e0527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610360525b606036610400376103a0516044358082018281125f83121861547257905090506103a05260016103a051121561034d576011610460527f4e6f6e2d706f73697469766520646562740000000000000000000000000000006104805261046050610460518061048001601f825f031636823750506308c379a061042052602061044052601f19601f61046051011660440161043cfd5b60206155805f395f5163c16ef264610480526020610480600461049c845afa610378573d5f5f3e3d5ffd5b60203d10615472576104809050516104605261046051610360511361041857610360516104005260206155805f395f516362ca4b1861048052610300516104a0526020610480602461049c845afa6103d2573d5f5f3e3d5ffd5b60203d106154725761048090505160206155605f395f51670de0b6b3a76400000280820281158383830414171561547257905090508060ff1c61547257610440526104f5565b60206155805f395f5163544fb5c161048052610300516104a0526040610480602461049c845afa61044b573d5f5f3e3d5ffd5b60403d10615472576104809050602081019050518060ff1c615472576024358082018281125f831218615472579050905061042052610420515f811261547257610160526103a0515f811261547257610180526103c0516101a0526104b161048061368d565b61048051610400526104205160206155205f395f518060ff1c6154725780820281191515600160ff1b84141517821584848405141716156154725790509050610420525b6103a05160206155605f395f518060ff1c6154725780820281191515600160ff1b841415178215848484051417161561547257905090506103a05260206155805f395f51632eb858e76104a052610400516104c05260206104a060246104bc845afa610563573d5f5f3e3d5ffd5b60203d10615472576104a09050518060ff1c6154725761048052610460516103605113156105e657610420515f8112615472576040526103c0516060525f6080526105af6104a0613594565b6104a0518060ff1c615472576104805180820281191515600160ff1b84141517821584848405141716156154725790509050610440525b6103a05161044051056104a0526104a051670de0b6b3a76400006104a0516103e05180820281191515600160ff1b84141517821584848405141716156154725790509050058082038281135f8312186154725790509050670de0b6b3a764000081038181136154725790506104a052610320511561072d576104605161040051131561072d576104805160206155805f395f516386fc88d36104e05260206104e060046104fc845afa61069b573d5f5f3e3d5ffd5b60203d10615472576104e09050518060ff1c6154725780828118828413021890509050610480518082038281135f83121861547257905090506104c05260016104c0511261072d576104a0516103a0516104c0516104205180820281191515600160ff1b84141517821584848405141716156154725790509050058082018281125f83121861547257905090506104a0525b60206104a0f35b6380e8f6ec81186130ba57602436103417615472576004356101e0525f61020052612b63566130ba565b637128f3b881186107a157602436103417615472576004358060a01c61547257604052680100000000000000046040516020525f5260405f205460605260206060f35b63c45a015581186107bf57346154725760206154e060403960206040f35b63036aed8881186130ba5760e436103417615472576004358060a01c61547257610960526064358060011c61547257610980526084358060a01c615472576109a05260a435600401600581351161547257803560208160051b0180836109c0375050505f546002146154725760025f555f610a8052336109605114610853576002610960516020525f5260405f2054610a80525b610960516106405260243561066052610a805161068052604435670de0b6b3a7640000818118670de0b6b3a76400008310021890506106a052610980516106c0526109a0516106e0526109c05160208160051b0180610700826109c060045afa5050506108be614e54565b60035f55006130ba565b636cce39be81186108ec573461547257680100000000000000055460405260206040f35b6331dc3ca8811861097357346154725760206155805f395f5163095a0fc6606052602060606004607c845afa610924573d5f5f3e3d5ffd5b60203d1061547257606090505160405260035460605260045460805260605160405180820281158383830414171561547257905090506080518015615472578082049050905060a052602060a0f35b63a5b4804a81186130ba576024361034176154725760206154e05f395f5163f851a440604052602060406004605c845afa6109b0573d5f5f3e3d5ffd5b60203d10615472576040518060a01c6154725760805260809050513318615472576706f05b59d3b200006004351115610a3e5760086040527f486967682066656500000000000000000000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b60206155805f395f51633217902f604052600435606052803b15615472575f60406024605c5f855af1610a73573d5f5f3e3d5ffd5b50006130ba565b634f02c4208118610a9e573461547257680100000000000000065460405260206040f35b6323cfed038118610adc57606436103417615472575f546002146154725760025f556060600461030037600161036052610ad66141a0565b60035f55005b6324049e5781186130ba57604436103417615472576024358060a01c61547257610560525b5f546002146154725760025f55600435610b1a57610b65565b600435610300525f6103205261056051610340525f61036052610b3b6145ba565b602061550060403933606052602061558060803960043560a052610b5d613d86565b610b65613411565b60035f55006130ba565b63e231bff08118610b93573461547257680100000000000000075460405260206040f35b6337671f93811861122c57608436103417615472576024358060a01c6154725761030052604435610320526064358060011c61547257610340525b5f546002146154725760025f55600435610be757611226565b6040366103603761030051604052610c006103a061349e565b6103a08051610360526020810151610380525061036051610c805760126103a0527f4c6f616e20646f65736e277420657869737400000000000000000000000000006103c0526103a0506103a051806103c001601f825f031636823750506308c379a061036052602061038052601f19601f6103a051011660440161037cfd5b61036051600435808281188284100218905090506103a0526103a05161036051036103605261036051610df35760206155805f395f5163f3fef3a3610400526103005161042052670de0b6b3a7640000610440526040610400604461041c5f855af1610cee573d5f5f3e3d5ffd5b60403d1061547257610400905080516103c05260208101516103e052506103c05115610d44573361030051186154725760206155406040396020615580606039610300516080526103c05160a052610d44613d86565b6103e05115610d735760206155006040396020615580606039610300516080526103e05160a052610d73613d86565b610300517feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f260a0366104003760a0610400a2610300517f77c6871227e5d2dec8dadd5354f78453203e22e669cd0ec4c19d9a8c5edb31d06103e051610400526103a051610420526040610400a261030051604052611165614a1056611165565b60206155805f395f5163c16ef2646103e05260206103e060046103fc845afa610e1e573d5f5f3e3d5ffd5b60203d10615472576103e09050516103c052610320516103c051136154725760206155805f395f5163b461100d6104205261030051610440526040610420602461043c845afa610e70573d5f5f3e3d5ffd5b60403d1061547257610420905080516103e0526020810151610400525060016103e0516104005103015f811261547257610420526002610300516020525f5260405f2054610440526103c0516103e05113610f7257610300517feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6104605261036051610480526103e0516104a052610400516104c052610440516104e05260a0610460a2610300517f77c6871227e5d2dec8dadd5354f78453203e22e669cd0ec4c19d9a8c5edb31d05f610460526103a051610480526040610460a261112b565b60206155805f395f5163f3fef3a36104a052610300516104c052670de0b6b3a76400006104e05260406104a060446104bc5f855af1610fb3573d5f5f3e3d5ffd5b60403d10615472576104a090508051610460526020810151610480525061048051610160526103605161018052610420516101a052610ff36104c061368d565b6104c0516104a0526104a0516103e05161040051038082018281125f83121861547257905090506104c05260206155805f395f5163ab047e006104e052610300516105005261048051610520526104a051610540526104c05161056052803b15615472575f6104e060846104fc5f855af1611070573d5f5f3e3d5ffd5b5033610300511861109f57680100000000000000095461044052610440516002610300516020525f5260405f20555b610300517feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f2610480516104e05261036051610500526104a051610520526104c05161054052610440516105605260a06104e0a2610300517f77c6871227e5d2dec8dadd5354f78453203e22e669cd0ec4c19d9a8c5edb31d05f6104e0526103a0516105005260406104e0a25b33610300511461116557600161030051604052610360516060525f6080526104405160a05261115b610460614ae4565b6104605112615472575b602061554060403933606052306080526103a05160a052611184613d86565b68010000000000000007546103a051808201828110615472579050905068010000000000000007556001610300516020525f5260405f2061036051815561038051600182015550600354610380518082028115838383041417156154725790509050600454801561547257808204905090506103c0526103a0516103c0516103a051808281188284110218905090500360035561038051600455611226613411565b60035f55005b631e0cfcef81186130ba5734615472575f546002146154725760025f5560206154e05f395f5163cab4d3db610180526020610180600461019c845afa611274573d5f5f3e3d5ffd5b60203d1061547257610180518060a01c615472576101c0526101c09050516101605260206155805f395f5163d1fea7336101a05260206101a060046101bc845afa6112c1573d5f5f3e3d5ffd5b60203d10615472576101a09050516101805260206155805f395f516389960ba76101c05260206101c060046101dc845afa6112fe573d5f5f3e3d5ffd5b60203d10615472576101c09050516101a05260206155406040396020615580606039610160516080526101805160a052611336613d86565b60206155006040396020615580606039610160516080526101a05160a05261135c613d86565b60206155805f395f5163822fe5076101c052803b15615472575f6101c060046101dc5f855af161138e573d5f5f3e3d5ffd5b5060206155805f395f5163095a0fc66101e05260206101e060046101fc845afa6113ba573d5f5f3e3d5ffd5b60203d10615472576101e09050516101c0526003546101e052600454610200526101e0516101c051808202811583838304141715615472579050905061020051801561547257808204905090506101e0526101c051610200526101e05160035561020051600455611429613411565b6101e05168010000000000000007548082018281106154725790509050610220526801000000000000000654610240526102405161022051116114ad577f5393ab6ef9bb40d91d1b04bbbeb707fbf3d1eb73f46744e2d179e4996026283f5f610260526101e051610280526040610260a15f61026052602061026061152456611524565b61022051680100000000000000065561024051610220510361022052602061554060403961016051606052610220516080526114e7613e02565b7f5393ab6ef9bb40d91d1b04bbbeb707fbf3d1eb73f46744e2d179e4996026283f61022051610260526101e051610280526040610260a160206102205b60035f55f36130ba565b63adfae4ce81186130ba573461547257680100000000000000085460405260206040f36130ba565b63627d2b83811861157a573461547257680100000000000000095460405260206040f35b631cf1f94781186116d55760643610341761547257604435610220525b5f546002146154725760043560206155205f395f5180820281158383830414171561547257905090506040526024356060526801000000000000000a546080526115e2610260613594565b61026051610240526001670de0b6b3a764000061024051611604610280613b0d565b6102805180820281158383830414171561547257905090500460018181186001831102189050036102605260206155605f395f51670de0b6b3a76400000261026051670de05bc096e9c000810281670de05bc096e9c00082041861547257905004610260526102605160206155405f395f516370a0823161028052306102a0526020610280602461029c845afa61169d573d5f5f3e3d5ffd5b60203d1061547257610280905051610220518082018281106154725790509050808281188284100218905090506102c05260206102c0f35b63720fb25481186130ba57606436103417615472575f54600214615472576020606060046101603761170861030061368d565b610300f36130ba565b632a943945811861172f573461547257602061558060403960206040f35b6381d2f1b781186130ba57602436103417615472576004358060a01c615472576040525f546002146154725760025f5560206154e05f395f5163f851a440606052602060606004607c845afa611787573d5f5f3e3d5ffd5b60203d10615472576060518060a01c6154725760a05260a0905051331861547257604051680100000000000000085560405163e91f2f4c606052602060606004607c5f855af16117d9573d5f5f3e3d5ffd5b60203d1061547257606050507f51fabb88f7860c9dbcc2a5a9b69a8b9476d63b87124591f97254e29f0e8daaeb60405160605260206060a160035f55006130ba565b632621db2f81186130ba573461547257602061550060403960206040f36130ba565b63765337b681186130ba573461547257602061554060403960206040f36130ba565b6369c6804e81186130ba5734615472575f546002146154725760025f55611884613411565b60035f55006130ba565b639b6c56ec81186118d257602436103417615472576004358060a01c6154725760e0525f5460021461547257602060e0516040526118cd61010061349e565b610100f35b627c98ab81186130ba5734615472576040366101e037612b63566130ba565b63a21adb9e81186130ba57602436103417615472576004358060a01c615472576040525f546002146154725760016040516020525f5260405f2054151560605260206060f36130ba565b639a49719681186130ba57604436103417615472575f61022052611597566130ba565b63a75732068118611aa957604436103417615472575f5460021461547257670de05bc096e9c00060206155205f395f5160043560206155605f395f51670de0b6b3a76400000280820281158383830414171561547257905090506119c3610220613b0d565b6102205180156154725780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418615472579050670de0b6b3a76400006040526024356060526801000000000000000a54608052611a1d610240613594565b61024051801561547257808204905090506024356024356107d0810181811061547257905080820281158383830414171561547257905090508082018281106154725790509050600160206155205f395f5103808201828110615472579050905004670de0b6b3a7640000810281670de0b6b3a764000082041861547257905004610260526020610260f35b638908ea8281186130ba57604436103417615472576024358060011c61547257610200525b6004358060a01c615472576101e0525f546002146154725760206101e051610280526101e051604052611b0261022061349e565b610220516102a052610200516102c05260026101e0516020525f5260405f20546102e052610280516040526102a0516060526102c0516080526102e05160a052611b4d610260614ae4565b610260f36130ba565b63bc61ea238118611cae5760c436103417615472576064358060a01c6154725761064052608435600401600581351161547257803560208160051b018083610660375050505f546002146154725760025f55602061554060403961064051606052602435608052611bc5613e02565b610640516040527fe62214fe00000000000000000000000000000000000000000000000000000000606052336080525f60a0526040600460c0376106605160208160051b01806101008261066060045afa505050611c24610740613e76565b61074060408101905051610720526004356107205180820182811061547257905090506103005260406024610320375f61036052611c606141a0565b602061550060403933606052602061558060803960043560a052611c82613d86565b60206155006040396106405160605260206155806080396107205160a052611ca8613d86565b60035f55005b63546e040d81186130ba5760443610341761547257602435610100525b6004358060a01c6154725760e0525f54600214615472575f610120523360e05114611d0457600260e0516020525f5260405f2054610120525b670de0b6b3a764000060206155805f395f5163544fb5c16101605260e051610180526040610160602461017c845afa611d3f573d5f5f3e3d5ffd5b60403d10615472576101609050516101005160405261012051606052611d666101c0614de7565b6101c05180820281158383830414171561547257905090500461014052670de0b6b3a764000060e051604052611d9d61018061349e565b6101805161010051808202811583838304141715615472579050905004610160526101405161016051610140518082811882841102189050905003610180526020610180f36130ba565b636f972f1281186130ba57602436103417615472573361056052610b01566130ba565b63d14ff5b681186130ba5760243610341761547257600161056052611e53566130ba565b632e4af52a81186130ba57604436103417615472576024358060011c61547257610560525b5f546002146154725760025f55600435611e6c57611eb5565b600435610300525f610320523361034052600161036052611e8b6145ba565b602061550060403960206155806060393360805260043560a052611ead613d86565b611eb5613411565b60035f55006130ba565b63dd171e7c81186130ba57604436103417615472575f546002146154725760025f55602435611eed57611f72565b604060046103003733610340525f61036052611f076145ba565b680100000000000000065460243580820182811061547257905090506801000000000000000655602061550060403933606052602061558060803960043560a052611f50613d86565b602061554060403933606052602435608052611f6a613e02565b611f72613411565b60035f55006130ba565b6336b7dbb781186130ba5760a436103417615472576044358060a01c6154725761064052606435600401600581351161547257803560208160051b018083610660375050505f546002146154725760025f55602435611fda5761210d565b602061554060403961064051606052602435608052611ff7613e02565b610640516040527fe62214fe00000000000000000000000000000000000000000000000000000000606052336080525f60a0526040600460c0376106605160208160051b01806101008261066060045afa505050612056610740613e76565b6107406040810190505161072052600435610720518082018281106154725790509050610300526024356103205233610340525f610360526120966145ba565b680100000000000000065460243580820182811061547257905090506801000000000000000655602061550060403933606052602061558060803960043560a0526120df613d86565b60206155006040396106405160605260206155806080396107205160a052612105613d86565b61210d613411565b60035f55006130ba565b63371fd8e681186130ba576024361034176154725733610300527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61032052600161034052610bce566130ba565b63acb7081581186130ba57604436103417615472576024358060a01c61547257610300527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61032052600161034052610bce566130ba565b63b4440df481186121f357606436103417615472576024358060a01c615472576103005260443561032052600161034052610bce565b632c5089c381186130ba57602436103417615472576004358060a01c615472576040525f546002146154725760206155805f395f5163e8dd1ef1606052604051608052602060606024607c845afa61224d573d5f5f3e3d5ffd5b60203d10615472576060518060011c6154725760a05260a0905051156154725760206155805f395f5163b461100d60a05260405160c052604060a0602460bc845afa61229b573d5f5f3e3d5ffd5b60403d106154725760a09050805160605260208101516080525060206155805f395f51632eb858e760a05260605160c052602060a0602460bc845afa6122e3573d5f5f3e3d5ffd5b60203d106154725760a09050516101205260206155805f395f516324299b7a60e05260805161010052602060e0602460fc845afa612323573d5f5f3e3d5ffd5b60203d106154725760e0905051610140526040610120f36130ba565b63152f65cb81186128ad57606436103417615472576004358060a01c6154725761064052602435600401600581351161547257803560208160051b018083610660375050505f546002146154725760025f5560206155805f395f5163b461100d6107605233610780526040610760602461077c845afa6123c1573d5f5f3e3d5ffd5b60403d106154725761076090508051610720526020810151610740525060206155805f395f5163f3fef3a36107a052336107c052670de0b6b3a76400006107e05260406107a060446107bc5f855af161241c573d5f5f3e3d5ffd5b60403d10615472576107a09050805161076052602081015161078052506040366107a0373360405261244f6107e061349e565b6107e080516107a05260208101516107c0525060206155006040396020615580606039610640516080526107805160a052612488613d86565b610640516040527fef67dc7400000000000000000000000000000000000000000000000000000000606052336080526107605160a0526107805160c0526107a05160e0526106605160208160051b01806101008261066060045afa5050506124f1610840613e76565b61084080516107e0526020810151610800526040810151610820525061080051610760518082018281106154725790509050610840526108405115615472575f610860526107a0516108405110156126f2576001610720516107405103015f811261547257610880526107e051610720511315615472576108005161086052610800516107a051036107a05261082051610160526107a05161018052610880516101a0526125a06108c061368d565b6108c0516108a0526108a0516107205161074051038082018281125f83121861547257905090506108c05260206155805f395f5163ab047e006108e052336109005261082051610920526108a051610940526108c05161096052803b15615472575f6108e060846108fc5f855af161261a573d5f5f3e3d5ffd5b5068010000000000000009546108e0526108e0516002336020525f5260405f205560206155006040396106405160605260206155806080396108205160a052612661613d86565b602061554060403961064051606052306080526108005160a052612683613d86565b337feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f261082051610900526107a051610920526108a051610940526108c051610960526108e0516109805260a0610900a261078051610820518082038281116154725790509050610780526127d0565b6107a051610860525f6107a0523360405261270b614a10565b602061554060403961064051606052306080526108005160a05261272d613d86565b60206155406040396020615580606039306080526107605160a052612750613d86565b6108605161084051111561277e5760206155406040393360605261086051610840510360805261277e613e02565b602061550060403961064051606052336080526108205160a0526127a0613d86565b337feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f260a0366108803760a0610880a25b337f77c6871227e5d2dec8dadd5354f78453203e22e669cd0ec4c19d9a8c5edb31d06107805161088052610860516108a0526040610880a2680100000000000000075461086051808201828110615472579050905068010000000000000007556001336020525f5260405f206107a05181556107c0516001820155506003546107c0518082028115838383041417156154725790509050600454801561547257808204905090506108805261086051610880516108605180828118828411021890509050036003556107c0516004556128a7613411565b60035f55005b631b25cdaf81186130ba5760243610341761547257670de0b6b3a764000061010052611ccb566130ba565b630b8db68181186130ba57608436103417615472575f61034052610194566130ba565b63bcbaf48781186130ba5760443610341761547257600161098052612944566130ba565b633ecdb82881186129c557606436103417615472576044358060011c61547257610980525b6004358060a01c61547257610960525f546002146154725760025f555f6109a052336109605114612984576002610960516020525f5260405f20546109a0525b6109605161064052602435610660526109a05161068052670de0b6b3a76400006106a052610980516106c0526040366106e0376129bf614e54565b60035f55005b63d9f11a648118612a0d573461547257602060206155805f395f5163f2388acb604052602060406004605c845afa6129ff573d5f5f3e3d5ffd5b60203d106154725760409050f35b63ec74d0a881186130ba57602436103417615472576004358060a01c6154725760e0525f546002146154725760206155805f395f5163544fb5c16101405260e051610160526040610140602461015c845afa612a6b573d5f5f3e3d5ffd5b60403d106154725761014090508051610100526020810151610120525060206155805f395f5163b461100d6101805260e0516101a0526040610180602461019c845afa612aba573d5f5f3e3d5ffd5b60403d1061547257610180905080516101405260208101516101605250610120516101c052610100516101e05260e051604052612af861018061349e565b61018051610200526001610140516101605103015f8112615472576102205260806101c0f36130ba565b63e2d8ebee81186130ba57602436103417615472575f61020052611ace566130ba565b6390f8667d81186130ba5760443610341761547257604060046101e0375b5f5460021461547257680100000000000000055461022052610200516102405261020051612b945761022051610240525b6101e051610260525f610280525f620f4240905b80620273a05261022051610260511015612bcc5761024051620273a0511815612bcf565b60015b15612bd957612d44565b6102605167fffffffffffffffe81116154725760050154620273c052620273c051604052612c096202740061349e565b6202740051620273e052620273c051604052620273e05160605260016080526002620273c0516020525f5260405f205460a052612c4862027420614ae4565b620274205162027400527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff620274005113612d245760206155805f395f5163544fb5c16202746052620273c051620274805260406202746060246202747c845afa612cb5573d5f5f3e3d5ffd5b60403d1061547257620274609050805162027420526020810151620274405250610280516103e781116154725760a081026102a001620273c05181526202742051602082015262027440516040820152620273e051606082015262027400516080820152506001810161028052505b610260516001810181811061547257905061026052600101818118612ba8575b5050602080620273a05280620273a0015f6102805180835260a081025f826103e88111615472578015612dbd57905b60a08102602087010160a082026102a00180518252602081015160208301526040810151604083015260608101516060830152608081015160808301525050600101818118612d73575b50508201602001915050905081019050620273a0f36130ba565b634189617d81186130ba576024361034176154725760206154e05f395f5163f851a440604052602060406004605c845afa612e14573d5f5f3e3d5ffd5b60203d10615472576040518060a01c61547257608052608090505133186154725760206156205f395f516004351115612e4d575f612e57565b620f424060043510155b612eb65760036040527f466565000000000000000000000000000000000000000000000000000000000060605260405060405180606001601f825f031636823750506308c379a05f526020602052601f19601f6040510116604401601cfd5b60206155805f395f51631aa02d59604052600435606052803b15615472575f60406024605c5f855af1612eeb573d5f5f3e3d5ffd5b50006130ba565b632a0c358681186130ba57604436103417615472575f546002146154725760025f5560206154e05f395f5163f851a440604052602060406004605c845afa612f3c573d5f5f3e3d5ffd5b60203d10615472576040518060a01c615472576080526080905051331861547257602435600435111561547257662386f26fc1000060243510615472576706f05b59d3b20000600435116154725760243568010000000000000009556004356801000000000000000a557fe2750bf9a7458977fcc01c1a0b615d12162f63b18cad78441bd64c590b337eca6040600460403760406040a160035f55006130ba565b63cc1891c781186130ba57602436103417615472576004358060a01c615472576040525f546002146154725760025f5560206154e05f395f5163f851a440606052602060606004607c845afa613035573d5f5f3e3d5ffd5b60203d10615472576060518060a01c6154725760a05260a090505133186154725760206155805f395f5163cc1891c7606052604051608052803b15615472575f60606024607c5f855af161308b573d5f5f3e3d5ffd5b5060035f55006130ba565b63d0c581bf81186130ba5734615472575f5460021461547257600160405260206040f35b5f5ffd5b6040516060525f60805260405160801c156130e25760405160801c60605260806080525b60605160401c156131005760605160401c6060526040608051016080525b60605160201c1561311e5760605160201c6060526020608051016080525b60605160101c1561313c5760605160101c6060526010608051016080525b60605160081c1561315a5760605160081c6060526008608051016080525b60605160041c156131785760605160041c6060526004608051016080525b60605160021c156131965760605160021c6060526002608051016080525b60605160011c156131ab576001608051016080525b608051815250565b60a0518060ff1c6154725760c05260a0511561547257606060a0516040526131dc6101006130be565b610100518060ff1c615472570360e05260c05160e051609f035f8112615472571b609f1c8060ff1c6154725760c0526d0139601a2efabe717e604cbb489460c0516c29508e458543d8aa4df2abee7860c051010260601d01610100526d02247f7a7b6594320649aa03aba160c051610100510260601d01610100526c8c3f38e95a6b1ff2ab1c3b343760c051610100510260601d03610100526d02384773bdf1ac5676facced609160c051610100510260601d03610100526cb9a025d814b29c212b8b1a07ce60c051610100510260601d0361010052780a09507084cc699bb0e71ea86a00000000000000000000000060c051610100510203610100526d0388eaa27412d5aca026815d636e60c0516c465772b2bbbb5f824b15207a3060c051010260601d01610120526d0df99ac502031bf953eff472fdcc60c051610120510260601d01610120526d13cdffb29d51d99322bdff5f221160c051610120510260601d01610120526d0a0f742023def783a307a986912e60c051610120510260601d01610120526d01920d8043ca89b5239253284e4260c051610120510260601d01610120526c0b7a86d7375468fac667a0a52760c051610120510260601d0161012052610120516101005105610140527d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642847d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b360e05102711340daa0d5f769dba1915cef59f0815a55066101405102010160ae1d815250565b680100000000000000085463e91f2f4c606052602060606004607c5f855af161343c573d5f5f3e3d5ffd5b60203d10615472576060905051640a3c2abcef818118640a3c2abcef83100218905060405260206155805f395f5163d4387a99606052604051608052602060606024607c5f855af1613490573d5f5f3e3d5ffd5b60203d106154725760605050565b60206155805f395f5163095a0fc6608052602060806004609c845afa6134c6573d5f5f3e3d5ffd5b60203d1061547257608090505160605260016040516020525f5260405f208054608052600181015460a0525060805161350e575f815260605160208201525061359256613592565b608051606051808202811583838304141715615472579050905060c05260c05160a051801561547257808206905090501561356d57600268010000000000000005541061356d5760c05160a051808201828110615472579050905060c0525b60c05160a0518015615472578082049050905060c05260c05181526060516020820152505b565b604051608051606051604051046103e88181186103e8831102189050683635c9adc5dea00000048082018281106154725790509050670de0b6b3a7640000818118670de0b6b3a7640000831002189050670de0b6b3a764000003808202811583838304141715615472579050905060605160206156005f395f51028015615472578082049050905060a05260a05160c052600160318101905b8060e05260605160e0511861364157613683565b60206155a05f395f5160a05160206155c05f395f5180820281158383830414171561547257905090500460a05260a05160c0510160c05260010181811861362d575b505060c051815250565b610180516136fa5760076101c0527f4e6f206c6f616e000000000000000000000000000000000000000000000000006101e0526101c0506101c051806101e001601f825f031636823750506308c379a06101805260206101a052601f19601f6101c051011660440161019cfd5b60206155805f395f51638f8654c56101e05260206101e060046101fc845afa613725573d5f5f3e3d5ffd5b60203d10615472576101e09050516101c05260206155805f395f51632eb858e7610200526101c051610220526020610200602461021c845afa61376a573d5f5f3e3d5ffd5b60203d10615472576102009050516101e0526101605160206155205f395f5180820281158383830414171561547257905090506040526101a0516060526801000000000000000a546080526137c0610220613594565b61022051610200526101805160206155605f395f51808202811583838304141715615472579050905060018101818110615472579050610200516101e051808202811583838304141715615472579050905004610200526102005161388457600e610220527f416d6f756e7420746f6f206c6f770000000000000000000000000000000000006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b6102005160a0526138966102406131b3565b61024051610220527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61022051136138ef5761022051600160206155e05f395f51038082038281135f8312186154725790509050610220525b60206155e05f395f51610220510561022052610220516101a0518060ff1c61547257806104000361040081135f831218615472579050808281188284120218905090506101c0518082018281125f8312186154725790509050610220526101c0516102205113613a205760206155805f395f5163ec654706610240526102205160018103818113615472579050610260526020610240602461025c845afa613999573d5f5f3e3d5ffd5b60203d1061547257610240518060011c6154725761028052610280905051613a2057600d6102a0527f4465627420746f6f2068696768000000000000000000000000000000000000006102c0526102a0506102a051806102c001601f825f031636823750506308c379a061026052602061028052601f19601f6102a051011660440161027cfd5b60206155805f395f516386fc88d3610280526020610280600461029c845afa613a4b573d5f5f3e3d5ffd5b60203d106154725761028090505160206155805f395f51632eb858e76102405261022051610260526020610240602461025c845afa613a8c573d5f5f3e3d5ffd5b60203d106154725761024090505110613b0457600d6102c0527f4465627420746f6f2068696768000000000000000000000000000000000000006102e0526102c0506102c051806102e001601f825f031636823750506308c379a06102805260206102a052601f19601f6102c051011660440161029cfd5b61022051815250565b60206155805f395f516386fc88d3610180526020610180600461019c845afa613b38573d5f5f3e3d5ffd5b60203d10615472576101809050516101605260206155805f395f5163a7db79a56101a05260206101a060046101bc845afa613b75573d5f5f3e3d5ffd5b60203d10615472576101a0905051670de0b6b3a7640000810281670de0b6b3a7640000820418615472579050610160518015615472578082049050905060a052613bc06101e06131b3565b6101e051610180527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101805113613c23576101805160206155e05f395f51600181038181136154725790508082038281135f8312186154725790509050610180525b60206155e05f395f516101805105600581018181126154725790506101805260206155805f395f5163c16ef2646101c05260206101c060046101dc845afa613c6d573d5f5f3e3d5ffd5b60203d10615472576101c09050516101a052610180516101a05160018101818112615472579050808281188284130218905090506101805260206155805f395f51632eb858e76101e052610180516102005260206101e060246101fc845afa613cd8573d5f5f3e3d5ffd5b60203d10615472576101e09050516101c0525f610401905b806101e0526101805160018103818113615472579050610180526101a0516101805113613d1c57613d7a565b6101c0516102005260206155c05f395f516101c05160206155a05f395f518082028115838383041417156154725790509050046101c052610160516101c0511115613d6f57610200518352505050613d84565b600101818118613cf0575b50506101c0518152505b565b60a05115613e00576040516323b872dd60c05260605160e0526080516101005260a05161012052602060c0606460dc5f855af1613dc5573d5f5f3e3d5ffd5b3d613ddc57803b1561547257600161014052613df4565b60203d106154725760c0518060011c61547257610140525b61014090505115615472575b565b60805115613e745760405163a9059cbb60a05260605160c05260805160e052602060a0604460bc5f855af1613e39573d5f5f3e3d5ffd5b3d613e5057803b1561547257600161010052613e68565b60203d106154725760a0518060011c61547257610100525b61010090505115615472575b565b60206155005f395f5160405114615472576060366101c03760206155805f395f51638f8654c5610220526020610220600461023c845afa613eb9573d5f5f3e3d5ffd5b60203d10615472576102209050516101c05260206155805f395f5163ebcb0067610240526101c051610260526020610240602461025c845afa613efe573d5f5f3e3d5ffd5b60203d10615472576102409050516102205260206155805f395f516331f7e306610260526101c051610280526020610260602461027c845afa613f43573d5f5f3e3d5ffd5b60203d1061547257610260905051610240526040515a5f60605181610460015260048101905060a06080516102e05260a0516103005260c0516103205260e051610340528061036052806102e0015f610100518083528060051b5f8260058111615472578015613fcd57905b8060051b61012001518160051b602088010152600101818118613faf575b505082016020019150509050810190506102c0526102c080516020820183610460018281848460045afa50505080830192505050806104405261044050506040610600610440516104605f8686f19050905061402b573d5f5f3e3d5ffd5b3d604081183d60401002186105e0526105e0602081510180610260828460045afa5050506102605160201161547257610280516102e05260206102c0526102c06020810151815160200360031b1c90506101e05261026051604011615472576102a0516102e05260206102c0526102c06020810151815160200360031b1c90506102005260206155805f395f51638f8654c56102c05260206102c060046102dc845afa6140da573d5f5f3e3d5ffd5b60203d10615472576102c09050516101c051186154725760206155805f395f5163ebcb00676102c0526101c0516102e05260206102c060246102dc845afa614124573d5f5f3e3d5ffd5b60203d10615472576102c090505161022051186154725760206155805f395f516331f7e3066102c0526101c0516102e05260206102c060246102dc845afa61416e573d5f5f3e3d5ffd5b60203d10615472576102c09050516102405118615472576101c05181526101e051602082015261020051604082015250565b6001336020525f5260405f205415614217576014610380527f4c6f616e20616c726561647920637265617465640000000000000000000000006103a0526103805061038051806103a001601f825f031636823750506308c379a061034052602061036052601f19601f61038051011660440161035cfd5b600461034051101561428857600f610380527f4e656564206d6f7265207469636b7300000000000000000000000000000000006103a0526103805061038051806103a001601f825f031636823750506308c379a061034052602061036052601f19601f61038051011660440161035cfd5b60326103405111156142f957600f610380527f4e656564206c657373207469636b7300000000000000000000000000000000006103a0526103805061038051806103a001601f825f031636823750506308c379a061034052602061036052601f19601f61038051011660440161035cfd5b61030051610160526103205161018052610340516101a05261431c6103a061368d565b6103a051610380526103805161034051600181038181116154725790508060ff1c615472578082018281125f83121861547257905090506103a05260206155805f395f5163095a0fc66103e05260206103e060046103fc845afa614382573d5f5f3e3d5ffd5b60203d10615472576103e09050516103c0526001336020525f5260405f206103205181556103c05160018201555068010000000000000009546103e0526103e0516002336020525f5260405f2055680100000000000000055461040052336104005167fffffffffffffffe811161547257600501556104005168010000000000000004336020525f5260405f20556001610400510168010000000000000005556003546103c0518082028115838383041417156154725790509050600454801561547257808204905090506103205180820182811061547257905090506003556103c05160045560206155805f395f5163ab047e00610420523361044052610300516104605261038051610480526103a0516104a052803b15615472575f610420608461043c5f855af16144b8573d5f5f3e3d5ffd5b506801000000000000000654610320518082018281106154725790509050680100000000000000065561036051156145285760206155006040393360605260206155806080396103005160a05261450d613d86565b60206155406040393360605261032051608052614528613e02565b614530613411565b337feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f26103005161042052610320516104405261038051610460526103a051610480526103e0516104a05260a0610420a2337fe1979fe4c35e0cef342fef5668e2c8e7a7e9f5d5d1ca8fee0ac6c427fa4153af610300516104205261032051610440526040610420a2565b60403661038037610340516040526145d36103c061349e565b6103c080516103805260208101516103a05250610380516146535760126103c0527f4c6f616e20646f65736e277420657869737400000000000000000000000000006103e0526103c0506103c051806103e001601f825f031636823750506308c379a06103805260206103a052601f19601f6103c051011660440161039cfd5b610380516103205180820182811061547257905090506103805260206155805f395f5163b461100d6104005261034051610420526040610400602461041c845afa6146a0573d5f5f3e3d5ffd5b60403d1061547257610400905080516103c05260208101516103e0525060016103c0516103e05103015f8112615472576104005260206155805f395f5163f3fef3a3610460526103405161048052670de0b6b3a76400006104a0526040610460604461047c5f855af1614715573d5f5f3e3d5ffd5b60403d106154725761046090508051610420526020810151610440525061042051156147a057601a610460527f416c726561647920696e20756e6465727761746572206d6f64650000000000006104805261046050610460518061048001601f825f031636823750506308c379a061042052602061044052601f19601f61046051011660440161043cfd5b610360516147c75761044051610300518082018281106154725790509050610440526147e2565b61044051610300518082038281116154725790509050610440525b61044051610160526103805161018052610400516101a05261480561048061368d565b6104805161046052610460516103c0516103e051038082018281125f83121861547257905090506104805260206155805f395f5163ab047e006104a052610340516104c052610440516104e05261046051610500526104805161052052803b15615472575f6104a060846104bc5f855af1614882573d5f5f3e3d5ffd5b506001610340516020525f5260405f206103805181556103a0516001820155505f6104a0523361034051186148d95768010000000000000009546104a0526104a0516002610340516020525f5260405f20556148ee565b6002610340516020525f5260405f20546104a0525b610320511561493f576003546103a0518082028115838383041417156154725790509050600454801561547257808204905090506103205180820182811061547257905090506003556103a0516004555b6103605161498757610340517fe1979fe4c35e0cef342fef5668e2c8e7a7e9f5d5d1ca8fee0ac6c427fa4153af610300516104c052610320516104e05260406104c0a26149bb565b610340517fe25410a4059619c9594dc6f022fe231b02aaea733f689e7ab0cd21b3d4d0eb54610300516104c05260206104c0a25b610340517feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f2610440516104c052610380516104e052610460516105005261048051610520526104a0516105405260a06104c0a2565b680100000000000000055460018103818111615472579050606052680100000000000000046040516020525f5260405f205460805260405160805167fffffffffffffffe8111615472576005015418615472575f680100000000000000046040516020525f5260405f20556060516080511015614ad45760605167fffffffffffffffe8111615472576005015460a05260a05160805167fffffffffffffffe811161547257600501556080516801000000000000000460a0516020525f5260405f20555b6060516801000000000000000555565b606051614b4757601260c0527f4c6f616e20646f65736e2774206578697374000000000000000000000000000060e05260c05060c0518060e001601f825f031636823750506308c379a0608052602060a052601f19601f60c0510116604401609cfd5b60a0518060ff1c6154725780670de0b6b3a764000003670de0b6b3a764000081135f83121861547257905060c0526060518060ff1c6154725760206155805f395f516362ca4b1860e05260405161010052602060e0602460fc845afa614baf573d5f5f3e3d5ffd5b60203d106154725760e09050518060ff1c6154725760c05180820281191515600160ff1b8414151782158484840514171615615472579050905005670de0b6b3a7640000810381811361547257905060c05260805115614ddf5760206155805f395f5163b461100d61010052604051610120526040610100602461011c845afa614c3b573d5f5f3e3d5ffd5b60403d106154725761010090505160e05260206155805f395f51638f8654c5610100526020610100600461011c845afa614c77573d5f5f3e3d5ffd5b60203d106154725761010090505160e0511315614ddf5760206155805f395f516386fc88d3610160526020610160600461017c845afa614cb9573d5f5f3e3d5ffd5b60203d10615472576101609050516101405260206155805f395f51632eb858e76101805260e0516101a0526020610180602461019c845afa614cfd573d5f5f3e3d5ffd5b60203d10615472576101809050516101605261016051610140511115614ddf5760c05160605160206155605f395f51808202811583838304141715615472579050905061016051610140510360206155805f395f5163544fb5c1610180526040516101a0526040610180602461019c845afa614d7b573d5f5f3e3d5ffd5b60403d1061547257610180905060208101905051808202811583838304141715615472579050905060206155205f395f518082028115838383041417156154725790509050048060ff1c615472578082018281125f831218615472579050905060c0525b60c051815250565b670de0b6b3a7640000608052670de0b6b3a763ffff60405111614e4c57606051670de0b6b3a764000001604051670de0b6b3a76400000360605160011c670de0b6b3a7640000010204608052670de0b6b3a76400006040516040516080510102046080525b608051815250565b6040366107c03761064051604052614e6d61080061349e565b61080080516107c05260208101516107e052506106805115614f3e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610640516040526107c05160605260016080526106805160a052614ecf610800614ae4565b610800511315614f3e57600f610820527f4e6f7420656e6f7567682072656b7400000000000000000000000000000000006108405261082050610820518061084001601f825f031636823750506308c379a06107e052602061080052601f19601f6108205101166044016107fcfd5b6107c05161080052670de0b6b3a76400006107c0516106a0518082028115838383041417156154725790509050046107c0526107c05115615472576107c05161080051036108005260206155805f395f5163f3fef3a361088052610640516108a0526106a05160405261068051606052614fb9610860614de7565b610860516108c0526040610880604461089c5f855af1614fdb573d5f5f3e3d5ffd5b60403d10615472576108809050805161082052602081015161084052506106605161082051101561506b576008610860527f536c6970706167650000000000000000000000000000000000000000000000006108805261086050610860518061088001601f825f031636823750506308c379a061082052602061084052601f19601f61086051011660440161083cfd5b610820516107c051808281188284100218905090506108605260206155406040396020615580606039306080526108605160a0526150a7613d86565b610820516107c051116151115760206155006040396020615580606039336080526108405160a0526150d7613d86565b6107c0516108205111156153065760206155406040396020615580606039336080526107c051610820510360a052615306613d8656615306565b610820516107c05103610880526106e05161516c5760206155006040396020615580606039336080526108405160a052615149613d86565b602061554060403933606052306080526108805160a052615306613d8656615306565b602061550060403960206155806060396106e0516080526108405160a052615192613d86565b6106e0516040527f4ea696bb00000000000000000000000000000000000000000000000000000000606052610640516080526108205160a0526108405160c0526107c05160e0526107005160208160051b01806101008261070060045afa5050506151fe610900613e76565b61090080516108a05260208101516108c05260408101516108e05250610880516108c051101561528d576013610900527f6e6f7420656e6f7567682070726f6365656473000000000000000000000000006109205261090050610900518061092001601f825f031636823750506308c379a06108c05260206108e052601f19601f6109005101166044016108dcfd5b610880516108c05111156152c25760206155406040396106e05160605233608052610880516108c0510360a0526152c2613d86565b60206155406040396106e051606052306080526108805160a0526152e4613d86565b60206155006040396106e051606052336080526108e05160a052615306613d86565b68010000000000000007546107c051808201828110615472579050905068010000000000000007556001610640516020525f5260405f206108005181556107e051600182015550610640517f77c6871227e5d2dec8dadd5354f78453203e22e669cd0ec4c19d9a8c5edb31d061084051610880526107c0516108a0526040610880a261064051337f642dd4d37ddd32036b9797cec464c0045dd2118c549066ae6b0f88e32240c2d06108405161088052610820516108a0526107c0516108c0526060610880a36108005161541557610640517feec6b7095a637e006c79c1819d696e353a8f703db2c49fc0219e17a8fd04f7f260a0366108803760a0610880a261064051604052615415614a10565b6003546107e051808202811583838304141715615472579050905060045480156154725780820490509050610880526107c051610880516107c05180828118828411021890509050036003556107e051600455615470613411565b565b5f80fd30ba291f30ba075e30ba185f17112b2230ba2ef21f7c2dd708c8155618f11b5630ba30ba30ba1de72b4530ba0b6f30ba181b21bd28fb30ba2117195e1e2e00181ebf30ba0143233f152e30ba28d830ba0a7a30ba309630ba1e0a2fdd30ba183d2165188e30ba30ba193b0000000000000000000000005ae28c9197a4a6570216fc7e53e7e0221d7a0fef000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f939e0a03fb07f59a73314e73794be0e57ac1b4e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b46adcd1ea7e35c4eb801406c3e76e76e9a46edf0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000331e7b009948160000000000000000000000000000000000000000000000000dfa5d892a33d4e900000000000000000000000000000000000000000000000000cb032035736db6
Verified Source Code Partial Match
Compiler: v0.3.10+commit.91361694
crvUSDController.vy 1459 lines
# @version 0.3.10
"""
@title crvUSD Controller
@author Curve.Fi
@license Copyright (c) Curve.Fi, 2020-2023 - all rights reserved
"""
interface LLAMMA:
def A() -> uint256: view
def get_p() -> uint256: view
def get_base_price() -> uint256: view
def active_band() -> int256: view
def active_band_with_skip() -> int256: view
def p_oracle_up(n: int256) -> uint256: view
def p_oracle_down(n: int256) -> uint256: view
def deposit_range(user: address, amount: uint256, n1: int256, n2: int256): nonpayable
def read_user_tick_numbers(_for: address) -> int256[2]: view
def get_sum_xy(user: address) -> uint256[2]: view
def withdraw(user: address, frac: uint256) -> uint256[2]: nonpayable
def get_x_down(user: address) -> uint256: view
def get_rate_mul() -> uint256: view
def set_rate(rate: uint256) -> uint256: nonpayable
def set_fee(fee: uint256): nonpayable
def set_admin_fee(fee: uint256): nonpayable
def price_oracle() -> uint256: view
def can_skip_bands(n_end: int256) -> bool: view
def admin_fees_x() -> uint256: view
def admin_fees_y() -> uint256: view
def reset_admin_fees(): nonpayable
def has_liquidity(user: address) -> bool: view
def bands_x(n: int256) -> uint256: view
def bands_y(n: int256) -> uint256: view
def set_callback(user: address): nonpayable
interface ERC20:
def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable
def transfer(_to: address, _value: uint256) -> bool: nonpayable
def decimals() -> uint256: view
def approve(_spender: address, _value: uint256) -> bool: nonpayable
def balanceOf(_from: address) -> uint256: view
interface MonetaryPolicy:
def rate_write() -> uint256: nonpayable
interface Factory:
def stablecoin() -> address: view
def admin() -> address: view
def fee_receiver() -> address: view
# Only if lending vault
def borrowed_token() -> address: view
def collateral_token() -> address: view
interface PriceOracle:
def price() -> uint256: view
def price_w() -> uint256: nonpayable
event UserState:
user: indexed(address)
collateral: uint256
debt: uint256
n1: int256
n2: int256
liquidation_discount: uint256
event Borrow:
user: indexed(address)
collateral_increase: uint256
loan_increase: uint256
event Repay:
user: indexed(address)
collateral_decrease: uint256
loan_decrease: uint256
event RemoveCollateral:
user: indexed(address)
collateral_decrease: uint256
event Liquidate:
liquidator: indexed(address)
user: indexed(address)
collateral_received: uint256
stablecoin_received: uint256
debt: uint256
event SetMonetaryPolicy:
monetary_policy: address
event SetBorrowingDiscounts:
loan_discount: uint256
liquidation_discount: uint256
event CollectFees:
amount: uint256
new_supply: uint256
struct Loan:
initial_debt: uint256
rate_mul: uint256
struct Position:
user: address
x: uint256
y: uint256
debt: uint256
health: int256
struct CallbackData:
active_band: int256
stablecoins: uint256
collateral: uint256
FACTORY: immutable(Factory)
MAX_LOAN_DISCOUNT: constant(uint256) = 5 * 10**17
MIN_LIQUIDATION_DISCOUNT: constant(uint256) = 10**16 # Start liquidating when threshold reached
MAX_TICKS: constant(int256) = 50
MAX_TICKS_UINT: constant(uint256) = 50
MIN_TICKS: constant(int256) = 4
MAX_SKIP_TICKS: constant(uint256) = 1024
MAX_P_BASE_BANDS: constant(int256) = 5
MAX_RATE: constant(uint256) = 43959106799 # 300% APY
loan: HashMap[address, Loan]
liquidation_discounts: public(HashMap[address, uint256])
_total_debt: Loan
loans: public(address[2**64 - 1]) # Enumerate existing loans
loan_ix: public(HashMap[address, uint256]) # Position of the loan in the list
n_loans: public(uint256) # Number of nonzero loans
minted: public(uint256)
redeemed: public(uint256)
monetary_policy: public(MonetaryPolicy)
liquidation_discount: public(uint256)
loan_discount: public(uint256)
COLLATERAL_TOKEN: immutable(ERC20)
COLLATERAL_PRECISION: immutable(uint256)
BORROWED_TOKEN: immutable(ERC20)
BORROWED_PRECISION: immutable(uint256)
AMM: immutable(LLAMMA)
A: immutable(uint256)
Aminus1: immutable(uint256)
LOGN_A_RATIO: immutable(int256) # log(A / (A - 1))
SQRT_BAND_RATIO: immutable(uint256)
MAX_ADMIN_FEE: constant(uint256) = 5 * 10**17 # 50%
MIN_FEE: constant(uint256) = 10**6 # 1e-12, still needs to be above 0
MAX_FEE: immutable(uint256) # let's set to MIN_TICKS / A: for example, 4% max fee for A=100
CALLBACK_DEPOSIT: constant(bytes4) = method_id("callback_deposit(address,uint256,uint256,uint256,uint256[])", output_type=bytes4)
CALLBACK_REPAY: constant(bytes4) = method_id("callback_repay(address,uint256,uint256,uint256,uint256[])", output_type=bytes4)
CALLBACK_LIQUIDATE: constant(bytes4) = method_id("callback_liquidate(address,uint256,uint256,uint256,uint256[])", output_type=bytes4)
DEAD_SHARES: constant(uint256) = 1000
MAX_ETH_GAS: constant(uint256) = 10000 # Forward this much gas to ETH transfers (2300 is what send() does)
@external
def __init__(
collateral_token: address,
monetary_policy: address,
loan_discount: uint256,
liquidation_discount: uint256,
amm: address):
"""
@notice Controller constructor deployed by the factory from blueprint
@param collateral_token Token to use for collateral
@param monetary_policy Address of monetary policy
@param loan_discount Discount of the maximum loan size compare to get_x_down() value
@param liquidation_discount Discount of the maximum loan size compare to
get_x_down() for "bad liquidation" purposes
@param amm AMM address (Already deployed from blueprint)
"""
FACTORY = Factory(msg.sender)
self.monetary_policy = MonetaryPolicy(monetary_policy)
self.liquidation_discount = liquidation_discount
self.loan_discount = loan_discount
self._total_debt.rate_mul = 10**18
AMM = LLAMMA(amm)
_A: uint256 = LLAMMA(amm).A()
A = _A
Aminus1 = unsafe_sub(_A, 1)
LOGN_A_RATIO = self.wad_ln(unsafe_div(_A * 10**18, unsafe_sub(_A, 1)))
MAX_FEE = min(unsafe_div(10**18 * MIN_TICKS, A), 10**17)
_collateral_token: ERC20 = ERC20(collateral_token)
_borrowed_token: ERC20 = empty(ERC20)
if collateral_token == empty(address):
# Lending vault factory
_collateral_token = ERC20(Factory(msg.sender).collateral_token())
_borrowed_token = ERC20(Factory(msg.sender).borrowed_token())
else:
# Stablecoin factory
# _collateral_token is already set
_borrowed_token = ERC20(Factory(msg.sender).stablecoin())
COLLATERAL_TOKEN = _collateral_token
BORROWED_TOKEN = _borrowed_token
COLLATERAL_PRECISION = pow_mod256(10, 18 - _collateral_token.decimals())
BORROWED_PRECISION = pow_mod256(10, 18 - _borrowed_token.decimals())
SQRT_BAND_RATIO = isqrt(unsafe_div(10**36 * _A, unsafe_sub(_A, 1)))
_borrowed_token.approve(msg.sender, max_value(uint256))
@internal
@pure
def _log_2(x: uint256) -> uint256:
"""
@dev An `internal` helper function that returns the log in base 2
of `x`, following the selected rounding direction.
@notice Note that it returns 0 if given 0. The implementation is
inspired by OpenZeppelin's implementation here:
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/Math.sol.
This code is taken from snekmate.
@param x The 32-byte variable.
@return uint256 The 32-byte calculation result.
"""
value: uint256 = x
result: uint256 = empty(uint256)
# The following lines cannot overflow because we have the well-known
# decay behaviour of `log_2(max_value(uint256)) < max_value(uint256)`.
if (x >> 128 != empty(uint256)):
value = x >> 128
result = 128
if (value >> 64 != empty(uint256)):
value = value >> 64
result = unsafe_add(result, 64)
if (value >> 32 != empty(uint256)):
value = value >> 32
result = unsafe_add(result, 32)
if (value >> 16 != empty(uint256)):
value = value >> 16
result = unsafe_add(result, 16)
if (value >> 8 != empty(uint256)):
value = value >> 8
result = unsafe_add(result, 8)
if (value >> 4 != empty(uint256)):
value = value >> 4
result = unsafe_add(result, 4)
if (value >> 2 != empty(uint256)):
value = value >> 2
result = unsafe_add(result, 2)
if (value >> 1 != empty(uint256)):
result = unsafe_add(result, 1)
return result
@internal
@pure
def wad_ln(x: uint256) -> int256:
"""
@dev Calculates the natural logarithm of a signed integer with a
precision of 1e18.
@notice Note that it returns 0 if given 0. Furthermore, this function
consumes about 1,400 to 1,650 gas units depending on the value
of `x`. The implementation is inspired by Remco Bloemen's
implementation under the MIT license here:
https://xn--2-umb.com/22/exp-ln.
This code is taken from snekmate.
@param x The 32-byte variable.
@return int256 The 32-byte calculation result.
"""
value: int256 = convert(x, int256)
assert x > 0
# We want to convert `x` from "10 ** 18" fixed point to "2 ** 96"
# fixed point. We do this by multiplying by "2 ** 96 / 10 ** 18".
# But since "ln(x * C) = ln(x) + ln(C)" holds, we can just do nothing
# here and add "ln(2 ** 96 / 10 ** 18)" at the end.
# Reduce the range of `x` to "(1, 2) * 2 ** 96".
# Also remember that "ln(2 ** k * x) = k * ln(2) + ln(x)" holds.
k: int256 = unsafe_sub(convert(self._log_2(x), int256), 96)
# Note that to circumvent Vyper's safecast feature for the potentially
# negative expression `value <<= uint256(159 - k)`, we first convert the
# expression `value <<= uint256(159 - k)` to `bytes32` and subsequently
# to `uint256`. Remember that the EVM default behaviour is to use two's
# complement representation to handle signed integers.
value = convert(convert(convert(value << convert(unsafe_sub(159, k), uint256), bytes32), uint256) >> 159, int256)
# Evaluate using a "(8, 8)"-term rational approximation. Since `p` is monic,
# we will multiply by a scaling factor later.
p: int256 = unsafe_add(unsafe_mul(unsafe_add(value, 3_273_285_459_638_523_848_632_254_066_296), value) >> 96, 24_828_157_081_833_163_892_658_089_445_524)
p = unsafe_add(unsafe_mul(p, value) >> 96, 43_456_485_725_739_037_958_740_375_743_393)
p = unsafe_sub(unsafe_mul(p, value) >> 96, 11_111_509_109_440_967_052_023_855_526_967)
p = unsafe_sub(unsafe_mul(p, value) >> 96, 45_023_709_667_254_063_763_336_534_515_857)
p = unsafe_sub(unsafe_mul(p, value) >> 96, 14_706_773_417_378_608_786_704_636_184_526)
p = unsafe_sub(unsafe_mul(p, value), 795_164_235_651_350_426_258_249_787_498 << 96)
# We leave `p` in the "2 ** 192" base so that we do not have to scale it up
# again for the division. Note that `q` is monic by convention.
q: int256 = unsafe_add(unsafe_mul(unsafe_add(value, 5_573_035_233_440_673_466_300_451_813_936), value) >> 96, 71_694_874_799_317_883_764_090_561_454_958)
q = unsafe_add(unsafe_mul(q, value) >> 96, 283_447_036_172_924_575_727_196_451_306_956)
q = unsafe_add(unsafe_mul(q, value) >> 96, 401_686_690_394_027_663_651_624_208_769_553)
q = unsafe_add(unsafe_mul(q, value) >> 96, 204_048_457_590_392_012_362_485_061_816_622)
q = unsafe_add(unsafe_mul(q, value) >> 96, 31_853_899_698_501_571_402_653_359_427_138)
q = unsafe_add(unsafe_mul(q, value) >> 96, 909_429_971_244_387_300_277_376_558_375)
# It is known that the polynomial `q` has no zeros in the domain.
# No scaling is required, as `p` is already "2 ** 96" too large. Also,
# `r` is in the range "(0, 0.125) * 2 ** 96" after the division.
r: int256 = unsafe_div(p, q)
# To finalise the calculation, we have to proceed with the following steps:
# - multiply by the scaling factor "s = 5.549...",
# - add "ln(2 ** 96 / 10 ** 18)",
# - add "k * ln(2)", and
# - multiply by "10 ** 18 / 2 ** 96 = 5 ** 18 >> 78".
# In order to perform the most gas-efficient calculation, we carry out all
# these steps in one expression.
return unsafe_add(unsafe_add(unsafe_mul(r, 1_677_202_110_996_718_588_342_820_967_067_443_963_516_166),\
unsafe_mul(k, 16_597_577_552_685_614_221_487_285_958_193_947_469_193_820_559_219_878_177_908_093_499_208_371)),\
600_920_179_829_731_861_736_702_779_321_621_459_595_472_258_049_074_101_567_377_883_020_018_308) >> 174
@external
@pure
def factory() -> Factory:
"""
@notice Address of the factory
"""
return FACTORY
@external
@pure
def amm() -> LLAMMA:
"""
@notice Address of the AMM
"""
return AMM
@external
@pure
def collateral_token() -> ERC20:
"""
@notice Address of the collateral token
"""
return COLLATERAL_TOKEN
@external
@pure
def borrowed_token() -> ERC20:
"""
@notice Address of the borrowed token
"""
return BORROWED_TOKEN
@internal
def _save_rate():
"""
@notice Save current rate
"""
rate: uint256 = min(self.monetary_policy.rate_write(), MAX_RATE)
AMM.set_rate(rate)
@external
@nonreentrant('lock')
def save_rate():
"""
@notice Save current rate
"""
self._save_rate()
@internal
@view
def _debt(user: address) -> (uint256, uint256):
"""
@notice Get the value of debt and rate_mul and update the rate_mul counter
@param user User address
@return (debt, rate_mul)
"""
rate_mul: uint256 = AMM.get_rate_mul()
loan: Loan = self.loan[user]
if loan.initial_debt == 0:
return (0, rate_mul)
else:
# Let user repay 1 smallest decimal more so that the system doesn't lose on precision
# Use ceil div
debt: uint256 = loan.initial_debt * rate_mul
if debt % loan.rate_mul > 0: # if only one loan -> don't have to do it
if self.n_loans > 1:
debt += loan.rate_mul
debt /= loan.rate_mul
return (debt, rate_mul)
@external
@view
@nonreentrant('lock')
def debt(user: address) -> uint256:
"""
@notice Get the value of debt without changing the state
@param user User address
@return Value of debt
"""
return self._debt(user)[0]
@external
@view
@nonreentrant('lock')
def loan_exists(user: address) -> bool:
"""
@notice Check whether there is a loan of `user` in existence
"""
return self.loan[user].initial_debt > 0
# No decorator because used in monetary policy
@external
@view
def total_debt() -> uint256:
"""
@notice Total debt of this controller
"""
rate_mul: uint256 = AMM.get_rate_mul()
loan: Loan = self._total_debt
return loan.initial_debt * rate_mul / loan.rate_mul
@internal
@pure
def get_y_effective(collateral: uint256, N: uint256, discount: uint256) -> uint256:
"""
@notice Intermediary method which calculates y_effective defined as x_effective / p_base,
however discounted by loan_discount.
x_effective is an amount which can be obtained from collateral when liquidating
@param collateral Amount of collateral to get the value for
@param N Number of bands the deposit is made into
@param discount Loan discount at 1e18 base (e.g. 1e18 == 100%)
@return y_effective
"""
# x_effective = sum_{i=0..N-1}(y / N * p(n_{n1+i})) =
# = y / N * p_oracle_up(n1) * sqrt((A - 1) / A) * sum_{0..N-1}(((A-1) / A)**k)
# === d_y_effective * p_oracle_up(n1) * sum(...) === y_effective * p_oracle_up(n1)
# d_y_effective = y / N / sqrt(A / (A - 1))
# d_y_effective: uint256 = collateral * unsafe_sub(10**18, discount) / (SQRT_BAND_RATIO * N)
# Make some extra discount to always deposit lower when we have DEAD_SHARES rounding
d_y_effective: uint256 = collateral * unsafe_sub(
10**18, min(discount + unsafe_div((DEAD_SHARES * 10**18), max(unsafe_div(collateral, N), DEAD_SHARES)), 10**18)
) / unsafe_mul(SQRT_BAND_RATIO, N)
y_effective: uint256 = d_y_effective
for i in range(1, MAX_TICKS_UINT):
if i == N:
break
d_y_effective = unsafe_div(d_y_effective * Aminus1, A)
y_effective = unsafe_add(y_effective, d_y_effective)
return y_effective
@internal
@view
def _calculate_debt_n1(collateral: uint256, debt: uint256, N: uint256) -> int256:
"""
@notice Calculate the upper band number for the deposit to sit in to support
the given debt. Reverts if requested debt is too high.
@param collateral Amount of collateral (at its native precision)
@param debt Amount of requested debt
@param N Number of bands to deposit into
@return Upper band n1 (n1 <= n2) to deposit into. Signed integer
"""
assert debt > 0, "No loan"
n0: int256 = AMM.active_band()
p_base: uint256 = AMM.p_oracle_up(n0)
# x_effective = y / N * p_oracle_up(n1) * sqrt((A - 1) / A) * sum_{0..N-1}(((A-1) / A)**k)
# === d_y_effective * p_oracle_up(n1) * sum(...) === y_effective * p_oracle_up(n1)
# d_y_effective = y / N / sqrt(A / (A - 1))
y_effective: uint256 = self.get_y_effective(collateral * COLLATERAL_PRECISION, N, self.loan_discount)
# p_oracle_up(n1) = base_price * ((A - 1) / A)**n1
# We borrow up until min band touches p_oracle,
# or it touches non-empty bands which cannot be skipped.
# We calculate required n1 for given (collateral, debt),
# and if n1 corresponds to price_oracle being too high, or unreachable band
# - we revert.
# n1 is band number based on adiabatic trading, e.g. when p_oracle ~ p
y_effective = unsafe_div(y_effective * p_base, debt * BORROWED_PRECISION + 1) # Now it's a ratio
# n1 = floor(log(y_effective) / self.logAratio)
# EVM semantics is not doing floor unlike Python, so we do this
assert y_effective > 0, "Amount too low"
n1: int256 = self.wad_ln(y_effective)
if n1 < 0:
n1 -= unsafe_sub(LOGN_A_RATIO, 1) # This is to deal with vyper's rounding of negative numbers
n1 = unsafe_div(n1, LOGN_A_RATIO)
n1 = min(n1, 1024 - convert(N, int256)) + n0
if n1 <= n0:
assert AMM.can_skip_bands(n1 - 1), "Debt too high"
# Let's not rely on active_band corresponding to price_oracle:
# this will be not correct if we are in the area of empty bands
assert AMM.p_oracle_up(n1) < AMM.price_oracle(), "Debt too high"
return n1
@internal
@view
def max_p_base() -> uint256:
"""
@notice Calculate max base price including skipping bands
"""
p_oracle: uint256 = AMM.price_oracle()
# Should be correct unless price changes suddenly by MAX_P_BASE_BANDS+ bands
n1: int256 = self.wad_ln(AMM.get_base_price() * 10**18 / p_oracle)
if n1 < 0:
n1 -= LOGN_A_RATIO - 1 # This is to deal with vyper's rounding of negative numbers
n1 = unsafe_div(n1, LOGN_A_RATIO) + MAX_P_BASE_BANDS
n_min: int256 = AMM.active_band_with_skip()
n1 = max(n1, n_min + 1)
p_base: uint256 = AMM.p_oracle_up(n1)
for i in range(MAX_SKIP_TICKS + 1):
n1 -= 1
if n1 <= n_min:
break
p_base_prev: uint256 = p_base
p_base = unsafe_div(p_base * A, Aminus1)
if p_base > p_oracle:
return p_base_prev
return p_base
@external
@view
@nonreentrant('lock')
def max_borrowable(collateral: uint256, N: uint256, current_debt: uint256 = 0) -> uint256:
"""
@notice Calculation of maximum which can be borrowed (details in comments)
@param collateral Collateral amount against which to borrow
@param N number of bands to have the deposit into
@param current_debt Current debt of the user (if any)
@return Maximum amount of stablecoin to borrow
"""
# Calculation of maximum which can be borrowed.
# It corresponds to a minimum between the amount corresponding to price_oracle
# and the one given by the min reachable band.
#
# Given by p_oracle (perhaps needs to be multiplied by (A - 1) / A to account for mid-band effects)
# x_max ~= y_effective * p_oracle
#
# Given by band number:
# if n1 is the lowest empty band in the AMM
# xmax ~= y_effective * amm.p_oracle_up(n1)
#
# When n1 -= 1:
# p_oracle_up *= A / (A - 1)
y_effective: uint256 = self.get_y_effective(collateral * COLLATERAL_PRECISION, N, self.loan_discount)
x: uint256 = unsafe_sub(max(unsafe_div(y_effective * self.max_p_base(), 10**18), 1), 1)
x = unsafe_div(x * (10**18 - 10**14), unsafe_mul(10**18, BORROWED_PRECISION)) # Make it a bit smaller
return min(x, BORROWED_TOKEN.balanceOf(self) + current_debt) # Cannot borrow beyond the amount of coins Controller has
@external
@view
@nonreentrant('lock')
def min_collateral(debt: uint256, N: uint256) -> uint256:
"""
@notice Minimal amount of collateral required to support debt
@param debt The debt to support
@param N Number of bands to deposit into
@return Minimal collateral required
"""
# Add N**2 to account for precision loss in multiple bands, e.g. N / (y/N) = N**2 / y
return unsafe_div(
unsafe_div(
debt * unsafe_mul(10**18, BORROWED_PRECISION) / self.max_p_base() * 10**18 / self.get_y_effective(10**18, N, self.loan_discount) + N * (N + 2 * DEAD_SHARES) + unsafe_sub(COLLATERAL_PRECISION, 1),
COLLATERAL_PRECISION
) * 10**18,
10**18 - 10**14)
@external
@view
@nonreentrant('lock')
def calculate_debt_n1(collateral: uint256, debt: uint256, N: uint256) -> int256:
"""
@notice Calculate the upper band number for the deposit to sit in to support
the given debt. Reverts if requested debt is too high.
@param collateral Amount of collateral (at its native precision)
@param debt Amount of requested debt
@param N Number of bands to deposit into
@return Upper band n1 (n1 <= n2) to deposit into. Signed integer
"""
return self._calculate_debt_n1(collateral, debt, N)
@internal
def transferFrom(token: ERC20, _from: address, _to: address, amount: uint256):
if amount > 0:
assert token.transferFrom(_from, _to, amount, default_return_value=True)
@internal
def transfer(token: ERC20, _to: address, amount: uint256):
if amount > 0:
assert token.transfer(_to, amount, default_return_value=True)
@internal
def execute_callback(callbacker: address, callback_sig: bytes4,
user: address, stablecoins: uint256, collateral: uint256, debt: uint256,
callback_args: DynArray[uint256, 5]) -> CallbackData:
assert callbacker != COLLATERAL_TOKEN.address
data: CallbackData = empty(CallbackData)
data.active_band = AMM.active_band()
band_x: uint256 = AMM.bands_x(data.active_band)
band_y: uint256 = AMM.bands_y(data.active_band)
# Callback
response: Bytes[64] = raw_call(
callbacker,
concat(callback_sig, _abi_encode(user, stablecoins, collateral, debt, callback_args)),
max_outsize=64
)
data.stablecoins = convert(slice(response, 0, 32), uint256)
data.collateral = convert(slice(response, 32, 32), uint256)
# Checks after callback
assert data.active_band == AMM.active_band()
assert band_x == AMM.bands_x(data.active_band)
assert band_y == AMM.bands_y(data.active_band)
return data
@internal
def _create_loan(collateral: uint256, debt: uint256, N: uint256, transfer_coins: bool):
assert self.loan[msg.sender].initial_debt == 0, "Loan already created"
assert N > MIN_TICKS-1, "Need more ticks"
assert N < MAX_TICKS+1, "Need less ticks"
n1: int256 = self._calculate_debt_n1(collateral, debt, N)
n2: int256 = n1 + convert(N - 1, int256)
rate_mul: uint256 = AMM.get_rate_mul()
self.loan[msg.sender] = Loan({initial_debt: debt, rate_mul: rate_mul})
liquidation_discount: uint256 = self.liquidation_discount
self.liquidation_discounts[msg.sender] = liquidation_discount
n_loans: uint256 = self.n_loans
self.loans[n_loans] = msg.sender
self.loan_ix[msg.sender] = n_loans
self.n_loans = unsafe_add(n_loans, 1)
self._total_debt.initial_debt = self._total_debt.initial_debt * rate_mul / self._total_debt.rate_mul + debt
self._total_debt.rate_mul = rate_mul
AMM.deposit_range(msg.sender, collateral, n1, n2)
self.minted += debt
if transfer_coins:
self.transferFrom(COLLATERAL_TOKEN, msg.sender, AMM.address, collateral)
self.transfer(BORROWED_TOKEN, msg.sender, debt)
self._save_rate()
log UserState(msg.sender, collateral, debt, n1, n2, liquidation_discount)
log Borrow(msg.sender, collateral, debt)
@external
@nonreentrant('lock')
def create_loan(collateral: uint256, debt: uint256, N: uint256):
"""
@notice Create loan
@param collateral Amount of collateral to use
@param debt Stablecoin debt to take
@param N Number of bands to deposit into (to do autoliquidation-deliquidation),
can be from MIN_TICKS to MAX_TICKS
"""
self._create_loan(collateral, debt, N, True)
@external
@nonreentrant('lock')
def create_loan_extended(collateral: uint256, debt: uint256, N: uint256, callbacker: address, callback_args: DynArray[uint256,5]):
"""
@notice Create loan but pass stablecoin to a callback first so that it can build leverage
@param collateral Amount of collateral to use
@param debt Stablecoin debt to take
@param N Number of bands to deposit into (to do autoliquidation-deliquidation),
can be from MIN_TICKS to MAX_TICKS
@param callbacker Address of the callback contract
@param callback_args Extra arguments for the callback (up to 5) such as min_amount etc
"""
# Before callback
self.transfer(BORROWED_TOKEN, callbacker, debt)
# Callback
# If there is any unused debt, callbacker can send it to the user
more_collateral: uint256 = self.execute_callback(
callbacker, CALLBACK_DEPOSIT, msg.sender, 0, collateral, debt, callback_args).collateral
# After callback
self._create_loan(collateral + more_collateral, debt, N, False)
self.transferFrom(COLLATERAL_TOKEN, msg.sender, AMM.address, collateral)
self.transferFrom(COLLATERAL_TOKEN, callbacker, AMM.address, more_collateral)
@internal
def _add_collateral_borrow(d_collateral: uint256, d_debt: uint256, _for: address, remove_collateral: bool):
"""
@notice Internal method to borrow and add or remove collateral
@param d_collateral Amount of collateral to add
@param d_debt Amount of debt increase
@param _for Address to transfer tokens to
@param remove_collateral Remove collateral instead of adding
"""
debt: uint256 = 0
rate_mul: uint256 = 0
debt, rate_mul = self._debt(_for)
assert debt > 0, "Loan doesn't exist"
debt += d_debt
ns: int256[2] = AMM.read_user_tick_numbers(_for)
size: uint256 = convert(unsafe_add(unsafe_sub(ns[1], ns[0]), 1), uint256)
xy: uint256[2] = AMM.withdraw(_for, 10**18)
assert xy[0] == 0, "Already in underwater mode"
if remove_collateral:
xy[1] -= d_collateral
else:
xy[1] += d_collateral
n1: int256 = self._calculate_debt_n1(xy[1], debt, size)
n2: int256 = n1 + unsafe_sub(ns[1], ns[0])
AMM.deposit_range(_for, xy[1], n1, n2)
self.loan[_for] = Loan({initial_debt: debt, rate_mul: rate_mul})
liquidation_discount: uint256 = 0
if _for == msg.sender:
liquidation_discount = self.liquidation_discount
self.liquidation_discounts[_for] = liquidation_discount
else:
liquidation_discount = self.liquidation_discounts[_for]
if d_debt != 0:
self._total_debt.initial_debt = self._total_debt.initial_debt * rate_mul / self._total_debt.rate_mul + d_debt
self._total_debt.rate_mul = rate_mul
if remove_collateral:
log RemoveCollateral(_for, d_collateral)
else:
log Borrow(_for, d_collateral, d_debt)
log UserState(_for, xy[1], debt, n1, n2, liquidation_discount)
@external
@nonreentrant('lock')
def add_collateral(collateral: uint256, _for: address = msg.sender):
"""
@notice Add extra collateral to avoid bad liqidations
@param collateral Amount of collateral to add
@param _for Address to add collateral for
"""
if collateral == 0:
return
self._add_collateral_borrow(collateral, 0, _for, False)
self.transferFrom(COLLATERAL_TOKEN, msg.sender, AMM.address, collateral)
self._save_rate()
@external
@nonreentrant('lock')
def remove_collateral(collateral: uint256, use_eth: bool = True):
"""
@notice Remove some collateral without repaying the debt
@param collateral Amount of collateral to remove
@param use_eth Use wrapping/unwrapping if collateral is ETH
"""
if collateral == 0:
return
self._add_collateral_borrow(collateral, 0, msg.sender, True)
self.transferFrom(COLLATERAL_TOKEN, AMM.address, msg.sender, collateral)
self._save_rate()
@external
@nonreentrant('lock')
def borrow_more(collateral: uint256, debt: uint256):
"""
@notice Borrow more stablecoins while adding more collateral (not necessary)
@param collateral Amount of collateral to add
@param debt Amount of stablecoin debt to take
"""
if debt == 0:
return
self._add_collateral_borrow(collateral, debt, msg.sender, False)
self.minted += debt
self.transferFrom(COLLATERAL_TOKEN, msg.sender, AMM.address, collateral)
self.transfer(BORROWED_TOKEN, msg.sender, debt)
self._save_rate()
@external
@nonreentrant('lock')
def borrow_more_extended(collateral: uint256, debt: uint256, callbacker: address, callback_args: DynArray[uint256,5]):
"""
@notice Borrow more stablecoins while adding more collateral using a callback (to leverage more)
@param collateral Amount of collateral to add
@param debt Amount of stablecoin debt to take
@param callbacker Address of the callback contract
@param callback_args Extra arguments for the callback (up to 5) such as min_amount etc
"""
if debt == 0:
return
# Before callback
self.transfer(BORROWED_TOKEN, callbacker, debt)
# Callback
# If there is any unused debt, callbacker can send it to the user
more_collateral: uint256 = self.execute_callback(
callbacker, CALLBACK_DEPOSIT, msg.sender, 0, collateral, debt, callback_args).collateral
# After callback
self._add_collateral_borrow(collateral + more_collateral, debt, msg.sender, False)
self.minted += debt
self.transferFrom(COLLATERAL_TOKEN, msg.sender, AMM.address, collateral)
self.transferFrom(COLLATERAL_TOKEN, callbacker, AMM.address, more_collateral)
self._save_rate()
@internal
def _remove_from_list(_for: address):
last_loan_ix: uint256 = self.n_loans - 1
loan_ix: uint256 = self.loan_ix[_for]
assert self.loans[loan_ix] == _for # dev: should never fail but safety first
self.loan_ix[_for] = 0
if loan_ix < last_loan_ix: # Need to replace
last_loan: address = self.loans[last_loan_ix]
self.loans[loan_ix] = last_loan
self.loan_ix[last_loan] = loan_ix
self.n_loans = last_loan_ix
@external
@nonreentrant('lock')
def repay(_d_debt: uint256, _for: address = msg.sender, max_active_band: int256 = 2**255-1, use_eth: bool = True):
"""
@notice Repay debt (partially or fully)
@param _d_debt The amount of debt to repay. If higher than the current debt - will do full repayment
@param _for The user to repay the debt for
@param max_active_band Don't allow active band to be higher than this (to prevent front-running the repay)
@param use_eth Use wrapping/unwrapping if collateral is ETH
"""
if _d_debt == 0:
return
# Or repay all for MAX_UINT256
# Withdraw if debt become 0
debt: uint256 = 0
rate_mul: uint256 = 0
debt, rate_mul = self._debt(_for)
assert debt > 0, "Loan doesn't exist"
d_debt: uint256 = min(debt, _d_debt)
debt = unsafe_sub(debt, d_debt)
if debt == 0:
# Allow to withdraw all assets even when underwater
xy: uint256[2] = AMM.withdraw(_for, 10**18)
if xy[0] > 0:
# Only allow full repayment when underwater for the sender to do
assert _for == msg.sender
self.transferFrom(BORROWED_TOKEN, AMM.address, _for, xy[0])
if xy[1] > 0:
self.transferFrom(COLLATERAL_TOKEN, AMM.address, _for, xy[1])
log UserState(_for, 0, 0, 0, 0, 0)
log Repay(_for, xy[1], d_debt)
self._remove_from_list(_for)
else:
active_band: int256 = AMM.active_band_with_skip()
assert active_band <= max_active_band
ns: int256[2] = AMM.read_user_tick_numbers(_for)
size: uint256 = convert(unsafe_add(unsafe_sub(ns[1], ns[0]), 1), uint256)
liquidation_discount: uint256 = self.liquidation_discounts[_for]
if ns[0] > active_band:
# Not in liquidation - can move bands
xy: uint256[2] = AMM.withdraw(_for, 10**18)
n1: int256 = self._calculate_debt_n1(xy[1], debt, size)
n2: int256 = n1 + unsafe_sub(ns[1], ns[0])
AMM.deposit_range(_for, xy[1], n1, n2)
if _for == msg.sender:
# Update liquidation discount only if we are that same user. No rugs
liquidation_discount = self.liquidation_discount
self.liquidation_discounts[_for] = liquidation_discount
log UserState(_for, xy[1], debt, n1, n2, liquidation_discount)
log Repay(_for, 0, d_debt)
else:
# Underwater - cannot move band but can avoid a bad liquidation
log UserState(_for, max_value(uint256), debt, ns[0], ns[1], liquidation_discount)
log Repay(_for, 0, d_debt)
if _for != msg.sender:
# Doesn't allow non-sender to repay in a way which ends with unhealthy state
# full = False to make this condition non-manipulatable (and also cheaper on gas)
assert self._health(_for, debt, False, liquidation_discount) > 0
# If we withdrew already - will burn less!
self.transferFrom(BORROWED_TOKEN, msg.sender, self, d_debt) # fail: insufficient funds
self.redeemed += d_debt
self.loan[_for] = Loan({initial_debt: debt, rate_mul: rate_mul})
total_debt: uint256 = self._total_debt.initial_debt * rate_mul / self._total_debt.rate_mul
self._total_debt.initial_debt = unsafe_sub(max(total_debt, d_debt), d_debt)
self._total_debt.rate_mul = rate_mul
self._save_rate()
@external
@nonreentrant('lock')
def repay_extended(callbacker: address, callback_args: DynArray[uint256,5]):
"""
@notice Repay loan but get a stablecoin for that from callback (to deleverage)
@param callbacker Address of the callback contract
@param callback_args Extra arguments for the callback (up to 5) such as min_amount etc
"""
# Before callback
ns: int256[2] = AMM.read_user_tick_numbers(msg.sender)
xy: uint256[2] = AMM.withdraw(msg.sender, 10**18)
debt: uint256 = 0
rate_mul: uint256 = 0
debt, rate_mul = self._debt(msg.sender)
self.transferFrom(COLLATERAL_TOKEN, AMM.address, callbacker, xy[1])
cb: CallbackData = self.execute_callback(
callbacker, CALLBACK_REPAY, msg.sender, xy[0], xy[1], debt, callback_args)
# After callback
total_stablecoins: uint256 = cb.stablecoins + xy[0]
assert total_stablecoins > 0 # dev: no coins to repay
# d_debt: uint256 = min(debt, total_stablecoins)
d_debt: uint256 = 0
# If we have more stablecoins than the debt - full repayment and closing the position
if total_stablecoins >= debt:
d_debt = debt
debt = 0
self._remove_from_list(msg.sender)
# Transfer debt to self, everything else to sender
self.transferFrom(BORROWED_TOKEN, callbacker, self, cb.stablecoins)
self.transferFrom(BORROWED_TOKEN, AMM.address, self, xy[0])
if total_stablecoins > d_debt:
self.transfer(BORROWED_TOKEN, msg.sender, unsafe_sub(total_stablecoins, d_debt))
self.transferFrom(COLLATERAL_TOKEN, callbacker, msg.sender, cb.collateral)
log UserState(msg.sender, 0, 0, 0, 0, 0)
# Else - partial repayment -> deleverage, but only if we are not underwater
else:
size: uint256 = convert(unsafe_add(unsafe_sub(ns[1], ns[0]), 1), uint256)
assert ns[0] > cb.active_band
d_debt = cb.stablecoins # cb.stablecoins <= total_stablecoins < debt
debt = unsafe_sub(debt, cb.stablecoins)
# Not in liquidation - can move bands
n1: int256 = self._calculate_debt_n1(cb.collateral, debt, size)
n2: int256 = n1 + unsafe_sub(ns[1], ns[0])
AMM.deposit_range(msg.sender, cb.collateral, n1, n2)
liquidation_discount: uint256 = self.liquidation_discount
self.liquidation_discounts[msg.sender] = liquidation_discount
self.transferFrom(COLLATERAL_TOKEN, callbacker, AMM.address, cb.collateral)
# Stablecoin is all spent to repay debt -> all goes to self
self.transferFrom(BORROWED_TOKEN, callbacker, self, cb.stablecoins)
# We are above active band, so xy[0] is 0 anyway
log UserState(msg.sender, cb.collateral, debt, n1, n2, liquidation_discount)
xy[1] -= cb.collateral
# No need to check _health() because it's the sender
# Common calls which we will do regardless of whether it's a full repay or not
log Repay(msg.sender, xy[1], d_debt)
self.redeemed += d_debt
self.loan[msg.sender] = Loan({initial_debt: debt, rate_mul: rate_mul})
total_debt: uint256 = self._total_debt.initial_debt * rate_mul / self._total_debt.rate_mul
self._total_debt.initial_debt = unsafe_sub(max(total_debt, d_debt), d_debt)
self._total_debt.rate_mul = rate_mul
self._save_rate()
@internal
@view
def _health(user: address, debt: uint256, full: bool, liquidation_discount: uint256) -> int256:
"""
@notice Returns position health normalized to 1e18 for the user.
Liquidation starts when < 0, however devaluation of collateral doesn't cause liquidation
@param user User address to calculate health for
@param debt The amount of debt to calculate health for
@param full Whether to take into account the price difference above the highest user's band
@param liquidation_discount Liquidation discount to use (can be 0)
@return Health: > 0 = good.
"""
assert debt > 0, "Loan doesn't exist"
health: int256 = 10**18 - convert(liquidation_discount, int256)
health = unsafe_div(convert(AMM.get_x_down(user), int256) * health, convert(debt, int256)) - 10**18
if full:
ns0: int256 = AMM.read_user_tick_numbers(user)[0] # ns[1] > ns[0]
if ns0 > AMM.active_band(): # We are not in liquidation mode
p: uint256 = AMM.price_oracle()
p_up: uint256 = AMM.p_oracle_up(ns0)
if p > p_up:
health += convert(unsafe_div(unsafe_sub(p, p_up) * AMM.get_sum_xy(user)[1] * COLLATERAL_PRECISION, debt * BORROWED_PRECISION), int256)
return health
@external
@view
@nonreentrant('lock')
def health_calculator(user: address, d_collateral: int256, d_debt: int256, full: bool, N: uint256 = 0) -> int256:
"""
@notice Health predictor in case user changes the debt or collateral
@param user Address of the user
@param d_collateral Change in collateral amount (signed)
@param d_debt Change in debt amount (signed)
@param full Whether it's a 'full' health or not
@param N Number of bands in case loan doesn't yet exist
@return Signed health value
"""
ns: int256[2] = AMM.read_user_tick_numbers(user)
debt: int256 = convert(self._debt(user)[0], int256)
n: uint256 = N
ld: int256 = 0
if debt != 0:
ld = convert(self.liquidation_discounts[user], int256)
n = convert(unsafe_add(unsafe_sub(ns[1], ns[0]), 1), uint256)
else:
ld = convert(self.liquidation_discount, int256)
ns[0] = max_value(int256) # This will trigger a "re-deposit"
n1: int256 = 0
collateral: int256 = 0
x_eff: int256 = 0
debt += d_debt
assert debt > 0, "Non-positive debt"
active_band: int256 = AMM.active_band_with_skip()
if ns[0] > active_band: # re-deposit
collateral = convert(AMM.get_sum_xy(user)[1], int256) + d_collateral
n1 = self._calculate_debt_n1(convert(collateral, uint256), convert(debt, uint256), n)
collateral *= convert(COLLATERAL_PRECISION, int256) # now has 18 decimals
else:
n1 = ns[0]
x_eff = convert(AMM.get_x_down(user) * unsafe_mul(10**18, BORROWED_PRECISION), int256)
debt *= convert(BORROWED_PRECISION, int256)
p0: int256 = convert(AMM.p_oracle_up(n1), int256)
if ns[0] > active_band:
x_eff = convert(self.get_y_effective(convert(collateral, uint256), n, 0), int256) * p0
health: int256 = unsafe_div(x_eff, debt)
health = health - unsafe_div(health * ld, 10**18) - 10**18
if full:
if n1 > active_band: # We are not in liquidation mode
p_diff: int256 = max(p0, convert(AMM.price_oracle(), int256)) - p0
if p_diff > 0:
health += unsafe_div(p_diff * collateral, debt)
return health
@internal
@pure
def _get_f_remove(frac: uint256, health_limit: uint256) -> uint256:
# f_remove = ((1 + h / 2) / (1 + h) * (1 - frac) + frac) * frac
f_remove: uint256 = 10 ** 18
if frac < 10 ** 18:
f_remove = unsafe_div(unsafe_mul(unsafe_add(10 ** 18, unsafe_div(health_limit, 2)), unsafe_sub(10 ** 18, frac)), unsafe_add(10 ** 18, health_limit))
f_remove = unsafe_div(unsafe_mul(unsafe_add(f_remove, frac), frac), 10 ** 18)
return f_remove
@internal
def _liquidate(user: address, min_x: uint256, health_limit: uint256, frac: uint256, use_eth: bool,
callbacker: address, callback_args: DynArray[uint256,5]):
"""
@notice Perform a bad liquidation of user if the health is too bad
@param user Address of the user
@param min_x Minimal amount of stablecoin withdrawn (to avoid liquidators being sandwiched)
@param health_limit Minimal health to liquidate at
@param frac Fraction to liquidate; 100% = 10**18
@param use_eth Use wrapping/unwrapping if collateral is ETH
@param callbacker Address of the callback contract
@param callback_args Extra arguments for the callback (up to 5) such as min_amount etc
"""
debt: uint256 = 0
rate_mul: uint256 = 0
debt, rate_mul = self._debt(user)
if health_limit != 0:
assert self._health(user, debt, True, health_limit) < 0, "Not enough rekt"
final_debt: uint256 = debt
debt = unsafe_div(debt * frac, 10**18)
assert debt > 0
final_debt = unsafe_sub(final_debt, debt)
# Withdraw sender's stablecoin and collateral to our contract
# When frac is set - we withdraw a bit less for the same debt fraction
# f_remove = ((1 + h/2) / (1 + h) * (1 - frac) + frac) * frac
# where h is health limit.
# This is less than full h discount but more than no discount
xy: uint256[2] = AMM.withdraw(user, self._get_f_remove(frac, health_limit)) # [stable, collateral]
# x increase in same block -> price up -> good
# x decrease in same block -> price down -> bad
assert xy[0] >= min_x, "Slippage"
min_amm_burn: uint256 = min(xy[0], debt)
self.transferFrom(BORROWED_TOKEN, AMM.address, self, min_amm_burn)
if debt > xy[0]:
to_repay: uint256 = unsafe_sub(debt, xy[0])
if callbacker == empty(address):
# Withdraw collateral if no callback is present
self.transferFrom(COLLATERAL_TOKEN, AMM.address, msg.sender, xy[1])
# Request what's left from user
self.transferFrom(BORROWED_TOKEN, msg.sender, self, to_repay)
else:
# Move collateral to callbacker, call it and remove everything from it back in
self.transferFrom(COLLATERAL_TOKEN, AMM.address, callbacker, xy[1])
# Callback
cb: CallbackData = self.execute_callback(
callbacker, CALLBACK_LIQUIDATE, user, xy[0], xy[1], debt, callback_args)
assert cb.stablecoins >= to_repay, "not enough proceeds"
if cb.stablecoins > to_repay:
self.transferFrom(BORROWED_TOKEN, callbacker, msg.sender, unsafe_sub(cb.stablecoins, to_repay))
self.transferFrom(BORROWED_TOKEN, callbacker, self, to_repay)
self.transferFrom(COLLATERAL_TOKEN, callbacker, msg.sender, cb.collateral)
else:
# Withdraw collateral
self.transferFrom(COLLATERAL_TOKEN, AMM.address, msg.sender, xy[1])
# Return what's left to user
if xy[0] > debt:
self.transferFrom(BORROWED_TOKEN, AMM.address, msg.sender, unsafe_sub(xy[0], debt))
self.redeemed += debt
self.loan[user] = Loan({initial_debt: final_debt, rate_mul: rate_mul})
log Repay(user, xy[1], debt)
log Liquidate(msg.sender, user, xy[1], xy[0], debt)
if final_debt == 0:
log UserState(user, 0, 0, 0, 0, 0) # Not logging partial removeal b/c we have not enough info
self._remove_from_list(user)
d: uint256 = self._total_debt.initial_debt * rate_mul / self._total_debt.rate_mul
self._total_debt.initial_debt = unsafe_sub(max(d, debt), debt)
self._total_debt.rate_mul = rate_mul
self._save_rate()
@external
@nonreentrant('lock')
def liquidate(user: address, min_x: uint256, use_eth: bool = True):
"""
@notice Peform a bad liquidation (or self-liquidation) of user if health is not good
@param min_x Minimal amount of stablecoin to receive (to avoid liquidators being sandwiched)
@param use_eth Use wrapping/unwrapping if collateral is ETH
"""
discount: uint256 = 0
if user != msg.sender:
discount = self.liquidation_discounts[user]
self._liquidate(user, min_x, discount, 10**18, use_eth, empty(address), [])
@external
@nonreentrant('lock')
def liquidate_extended(user: address, min_x: uint256, frac: uint256, use_eth: bool,
callbacker: address, callback_args: DynArray[uint256,5]):
"""
@notice Peform a bad liquidation (or self-liquidation) of user if health is not good
@param min_x Minimal amount of stablecoin to receive (to avoid liquidators being sandwiched)
@param frac Fraction to liquidate; 100% = 10**18
@param use_eth Use wrapping/unwrapping if collateral is ETH
@param callbacker Address of the callback contract
@param callback_args Extra arguments for the callback (up to 5) such as min_amount etc
"""
discount: uint256 = 0
if user != msg.sender:
discount = self.liquidation_discounts[user]
self._liquidate(user, min_x, discount, min(frac, 10**18), use_eth, callbacker, callback_args)
@view
@external
@nonreentrant('lock')
def tokens_to_liquidate(user: address, frac: uint256 = 10 ** 18) -> uint256:
"""
@notice Calculate the amount of stablecoins to have in liquidator's wallet to liquidate a user
@param user Address of the user to liquidate
@param frac Fraction to liquidate; 100% = 10**18
@return The amount of stablecoins needed
"""
health_limit: uint256 = 0
if user != msg.sender:
health_limit = self.liquidation_discounts[user]
stablecoins: uint256 = unsafe_div(AMM.get_sum_xy(user)[0] * self._get_f_remove(frac, health_limit), 10 ** 18)
debt: uint256 = unsafe_div(self._debt(user)[0] * frac, 10 ** 18)
return unsafe_sub(max(debt, stablecoins), stablecoins)
@view
@external
@nonreentrant('lock')
def health(user: address, full: bool = False) -> int256:
"""
@notice Returns position health normalized to 1e18 for the user.
Liquidation starts when < 0, however devaluation of collateral doesn't cause liquidation
"""
return self._health(user, self._debt(user)[0], full, self.liquidation_discounts[user])
@view
@external
@nonreentrant('lock')
def users_to_liquidate(_from: uint256=0, _limit: uint256=0) -> DynArray[Position, 1000]:
"""
@notice Returns a dynamic array of users who can be "hard-liquidated".
This method is designed for convenience of liquidation bots.
@param _from Loan index to start iteration from
@param _limit Number of loans to look over
@return Dynamic array with detailed info about positions of users
"""
n_loans: uint256 = self.n_loans
limit: uint256 = _limit
if _limit == 0:
limit = n_loans
ix: uint256 = _from
out: DynArray[Position, 1000] = []
for i in range(10**6):
if ix >= n_loans or i == limit:
break
user: address = self.loans[ix]
debt: uint256 = self._debt(user)[0]
health: int256 = self._health(user, debt, True, self.liquidation_discounts[user])
if health < 0:
xy: uint256[2] = AMM.get_sum_xy(user)
out.append(Position({
user: user,
x: xy[0],
y: xy[1],
debt: debt,
health: health
}))
ix += 1
return out
# AMM has a nonreentrant decorator
@view
@external
def amm_price() -> uint256:
"""
@notice Current price from the AMM
"""
return AMM.get_p()
@view
@external
@nonreentrant('lock')
def user_prices(user: address) -> uint256[2]: # Upper, lower
"""
@notice Lowest price of the lower band and highest price of the upper band the user has deposit in the AMM
@param user User address
@return (upper_price, lower_price)
"""
assert AMM.has_liquidity(user)
ns: int256[2] = AMM.read_user_ti...
// [truncated — 54674 bytes total]
Read Contract
admin_fees 0x1b1800e3 → uint256
amm 0x2a943945 → address
amm_price 0xd9f11a64 → uint256
borrowed_token 0x765337b6 → address
calculate_debt_n1 0x720fb254 → int256
check_lock 0xd0c581bf → bool
collateral_token 0x2621db2f → address
debt 0x9b6c56ec → uint256
factory 0xc45a0155 → address
health 0xe2d8ebee → int256
health 0x8908ea82 → int256
health_calculator 0x0b8db681 → int256
health_calculator 0x22c71453 → int256
liquidation_discount 0x627d2b83 → uint256
liquidation_discounts 0x5457ff7b → uint256
loan_discount 0x5449b9cb → uint256
loan_exists 0xa21adb9e → bool
loan_ix 0x7128f3b8 → uint256
loans 0xe1ec3c68 → address
max_borrowable 0x9a497196 → uint256
max_borrowable 0x1cf1f947 → uint256
min_collateral 0xa7573206 → uint256
minted 0x4f02c420 → uint256
monetary_policy 0xadfae4ce → address
n_loans 0x6cce39be → uint256
redeemed 0xe231bff0 → uint256
tokens_to_liquidate 0x1b25cdaf → uint256
tokens_to_liquidate 0x546e040d → uint256
total_debt 0x31dc3ca8 → uint256
user_prices 0x2c5089c3 → uint256[2]
user_state 0xec74d0a8 → uint256[4]
users_to_liquidate 0x007c98ab → tuple[]
users_to_liquidate 0x80e8f6ec → tuple[]
users_to_liquidate 0x90f8667d → tuple[]
Write Contract 23 functions
These functions modify contract state and require a wallet transaction to execute.
add_collateral 0x6f972f12
uint256 collateral
add_collateral 0x24049e57
uint256 collateral
address _for
borrow_more 0xdd171e7c
uint256 collateral
uint256 debt
borrow_more_extended 0x36b7dbb7
uint256 collateral
uint256 debt
address callbacker
uint256[] callback_args
collect_fees 0x1e0cfcef
No parameters
returns: uint256
create_loan 0x23cfed03
uint256 collateral
uint256 debt
uint256 N
create_loan_extended 0xbc61ea23
uint256 collateral
uint256 debt
uint256 N
address callbacker
uint256[] callback_args
liquidate 0xbcbaf487
address user
uint256 min_x
liquidate 0x3ecdb828
address user
uint256 min_x
bool use_eth
liquidate_extended 0x036aed88
address user
uint256 min_x
uint256 frac
bool use_eth
address callbacker
uint256[] callback_args
remove_collateral 0xd14ff5b6
uint256 collateral
remove_collateral 0x2e4af52a
uint256 collateral
bool use_eth
repay 0x371fd8e6
uint256 _d_debt
repay 0xacb70815
uint256 _d_debt
address _for
repay 0xb4440df4
uint256 _d_debt
address _for
int256 max_active_band
repay 0x37671f93
uint256 _d_debt
address _for
int256 max_active_band
bool use_eth
repay_extended 0x152f65cb
address callbacker
uint256[] callback_args
save_rate 0x69c6804e
No parameters
set_amm_admin_fee 0xa5b4804a
uint256 fee
set_amm_fee 0x4189617d
uint256 fee
set_borrowing_discounts 0x2a0c3586
uint256 loan_discount
uint256 liquidation_discount
set_callback 0xcc1891c7
address cb
set_monetary_policy 0x81d2f1b7
address monetary_policy
Recent Transactions
No transactions found for this address