Address Contract Partially Verified
Address
0x78eDcb307AC1d1F8F5Fd070B377A6e69C8dcFC34
Balance
0 ETH
Nonce
1
Code Size
11264 bytes
Creator
0x2C2dc95F...613C at tx 0xb445706a...29e79e
Indexed Transactions
0
Contract Bytecode
11264 bytes
0x608060405234801561001057600080fd5b50600436106102325760003560e01c806370a0823111610130578063c494448e116100b8578063ec5568891161007c578063ec55688914610554578063ee11d5eb14610569578063f1e42ccd1461057c578063f83d08ba1461058f578063f9609f081461059757600080fd5b8063c494448e146104ed578063c9818d7b14610500578063d1e61dcb14610513578063d9caed121461052e578063e95df3de1461054157600080fd5b8063a345bf43116100ff578063a345bf4314610489578063a3ec138d14610491578063ab033ea9146104b4578063bb994d48146104c7578063bfad6f8c146104da57600080fd5b806370a082311461042d5780638c89d81b1461044057806399eecb3b146104535780639bec82881461046e57600080fd5b806339ebf823116101be5780635f74bbde116101825780635f74bbde146103dc5780636a4874a1146103ef5780636c0b3e461461040a5780636dc7a627146104125780636e7dbabb1461041a57600080fd5b806339ebf8231461035f5780633e9a2ee11461038857806344693a4b1461039b57806355fef7b4146103b65780635aa6e675146103c957600080fd5b80632479b177116102055780632479b177146102b85780632c8e7a21146102d35780632fa7dcf5146103065780633777261d1461032957806339e2da541461034c57600080fd5b806309cae2c8146102375780630e5c011e1461025d57806322a2f07d1461027257806323a53c32146102a5575b600080fd5b61024a6102453660046125c8565b6105aa565b6040519081526020015b60405180910390f35b61027061026b366004612601565b6105c3565b005b61028d735f3b5dfeb7b28cdbd7faba78963ee202a494e2a281565b6040516001600160a01b039091168152602001610254565b6102706102b3366004612601565b610805565b61028d73d16d5ec345dd86fb63c6a9c43c517210f102791481565b6102f66102e1366004612601565b60036020526000908152604090205460ff1681565b6040519015158152602001610254565b6102f6610314366004612601565b60016020526000908152604090205460ff1681565b6102f6610337366004612601565b60066020526000908152604090205460ff1681565b61027061035a36600461262c565b6108be565b61028d61036d366004612601565b6000602081905290815260409020546001600160a01b031681565b61024a61039636600461265a565b61093c565b61028d73f98b45fa17de75fb1ad0e7afd971b0ca00e379fc81565b6102706103c436600461262c565b610a78565b60055461028d906001600160a01b031681565b6102706103ea36600461269c565b610ba3565b61028d73d533a949740bb3306d119cc777fa900ba034cd5281565b610270610bf1565b6102f6610d77565b61027061042836600461262c565b610ec8565b61024a61043b366004612601565b610f46565b61024a61044e366004612601565b610fbf565b61028d732f50d538606fa9edd2b11e2446beb18c9d5846bb81565b61028d73f939e0a03fb07f59a73314e73794be0e57ac1b4e81565b61024a610ff5565b6102f661049f366004612601565b60026020526000908152604090205460ff1681565b6102706104c2366004612601565b61105a565b6102706104d5366004612601565b61111a565b6102706104e836600461270f565b6112ae565b6102706104fb3660046125c8565b6112ca565b61027061050e366004612822565b6114e8565b61028d73d061d61a4d941c39e5453435b6345dc261c2fce081565b61024a61053c36600461288e565b6115d3565b61027061054f36600461262c565b611791565b61028d600080516020612bab83398151915281565b60045461028d906001600160a01b031681565b61027061058a3660046125c8565b61180f565b610270611886565b6102706105a53660046125c8565b6119ce565b60006105ba838361053c86610f46565b90505b92915050565b6001600160a01b038181166000908152602081905260409020541633146106055760405162461bcd60e51b81526004016105fc906128cf565b60405180910390fd5b6040516370a0823160e01b8152600080516020612bab833981519152600482015260009073d533a949740bb3306d119cc777fa900ba034cd52906370a0823190602401602060405180830381865afa158015610665573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068991906128f2565b6040516001600160a01b03841660248201529091506106ff9073d061d61a4d941c39e5453435b6345dc261c2fce09060009060440160408051601f198184030181529190526020810180516001600160e01b03166335313c2160e11b179052600080516020612bab833981519152929190611bf5565b6040516370a0823160e01b8152600080516020612bab8339815191526004820152819073d533a949740bb3306d119cc777fa900ba034cd52906370a0823190602401602060405180830381865afa15801561075e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078291906128f2565b61078c9190612921565b604051336024820152604481018290529091506108019073d533a949740bb3306d119cc777fa900ba034cd52906000906064015b60408051601f198184030181529190526020810180516001600160e01b031663a9059cbb60e01b179052600080516020612bab833981519152929190611bf5565b5050565b6005546001600160a01b0316331461082f5760405162461bcd60e51b81526004016105fc90612934565b6001600160a01b0381166108745760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b60448201526064016105fc565b600480546001600160a01b0319166001600160a01b0383169081179091556040517fee8c1ab31210fe712e7f0c21f2505b3a6cc72787f22544a103c88ab3e2db0fe590600090a250565b6005546001600160a01b031633146108e85760405162461bcd60e51b81526004016105fc90612934565b6001600160a01b038216600081815260036020526040808220805460ff191685151590811790915590519092917f8606778dbed23a0ff32fcf3b94d3d9c5d1f6af7e8b93a2cc2f82b1eb66833df191a35050565b3360009081526002602052604081205460ff168061096457506005546001600160a01b031633145b6109805760405162461bcd60e51b81526004016105fc90612959565b73e478de485ad2fe566d49342cbd03e49ed7db33566001600160a01b03851614806109c7575073bcff8b0b9419b9a88c44546519b1e909cf3303996001600160a01b038516145b610a0a5760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a590819185bc818dbdb9d1c9858dd60621b60448201526064016105fc565b6040516024810184905282151560448201526000606482018190529060840160408051601f198184030181529190526020810180516001600160e01b0316636f899de560e11b1790529050610a70600080516020612bab83398151915286600084611bf5565b509392505050565b6005546001600160a01b03163314610aa25760405162461bcd60e51b81526004016105fc90612934565b8015610aea57610ab182611c7c565b610aea5760405162461bcd60e51b815260206004820152600a60248201526910b9b0b332aa37b5b2b760b11b60448201526064016105fc565b6001600160a01b03821660009081526001602052604090205481151560ff909116151503610b4f5760405162461bcd60e51b81526020600482015260126024820152714e6f20617070726f76616c206368616e676560701b60448201526064016105fc565b6001600160a01b038216600081815260016020526040808220805460ff191685151590811790915590519092917f38a647972b50958de565d66a0739df26fb918436c3758ee77051c86c2fee18ef91a35050565b6005546001600160a01b0316331480610bcb57503360009081526002602052604090205460ff165b610be75760405162461bcd60e51b81526004016105fc90612959565b6108018282611df6565b6005546001600160a01b0316331480610c1957503360009081526003602052604090205460ff165b610c4f5760405162461bcd60e51b815260206004820152600760248201526610b637b1b5b2b960c91b60448201526064016105fc565b6000610c5f42630784ce00612979565b60405163adc6358960e01b8152600080516020612bab8339815191526004820152909150600090735f3b5dfeb7b28cdbd7faba78963ee202a494e2a29063adc63589906024016020604051808303816000875af1158015610cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce891906128f2565b905062093a80610cf8818461298c565b610d0291906129ae565b81101561080157610801735f3b5dfeb7b28cdbd7faba78963ee202a494e2a2600084604051602401610d3691815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166377fbd30960e11b179052600080516020612bab833981519152929190611bf5565b60008062093a80610d88814261298c565b610d9291906129ae565b604051632a2a314b60e01b8152600080516020612bab833981519152600482015290915060009073d16d5ec345dd86fb63c6a9c43c517210f102791490632a2a314b90602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1991906128f2565b9050600073d16d5ec345dd86fb63c6a9c43c517210f10279146001600160a01b0316637f58e8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9391906128f2565b9050610ea262093a8083612979565b42118015610eaf57508281115b15610ebe576001935050505090565b6000935050505090565b6005546001600160a01b03163314610ef25760405162461bcd60e51b81526004016105fc90612934565b6001600160a01b038216600081815260066020526040808220805460ff191685151590811790915590519092917ff0bca289b5abf6afc1d97cb00812df41c64cd0e301938ede001441c40566ea1091a35050565b6040516370a0823160e01b8152600080516020612bab83398151915260048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610f9b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bd91906128f2565b6005546000906001600160a01b03163314610fec5760405162461bcd60e51b81526004016105fc90612934565b6105bd82611e70565b6004546000906001600160a01b031633146110405760405162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b60448201526064016105fc565b600454611055906001600160a01b0316611e70565b905090565b6005546001600160a01b031633146110845760405162461bcd60e51b81526004016105fc90612934565b6005546001600160a01b03908116908216036110d05760405162461bcd60e51b815260206004820152600b60248201526a185b1c9958591e481cd95d60aa1b60448201526064016105fc565b600580546001600160a01b0319166001600160a01b0383169081179091556040517fc73be659241aade67e9a059bcf21494955018b213dbd1179054ccf928b13f3b690600090a250565b6005546001600160a01b031633146111445760405162461bcd60e51b81526004016105fc90612934565b6001600160a01b03808216600090815260208190526040902054168061119e5760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e481c995d9bdad959608a1b60448201526064016105fc565b604051600060248201819052600080516020612bab8339815191529163b61d27f691859160440160408051601f198184030181529181526020820180516001600160e01b0316635efcc08b60e11b1790525160e085901b6001600160e01b031916815261121093929190600401612a15565b6000604051808303816000875af115801561122f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112579190810190612a45565b50506001600160a01b0380831660008181526020819052604080822080546001600160a01b031916905551928416927f9e679fbbc4023ee1b3717af256f455ff2631ef94af1a29e2303085ac0e41127f9190a35050565b6112b782612079565b156112c0575050565b61080182826121f6565b6005546001600160a01b03163314806112f257503360009081526006602052604090205460ff165b6113285760405162461bcd60e51b81526020600482015260076024820152662161636365737360c81b60448201526064016105fc565b6001600160a01b03811661136e5760405162461bcd60e51b815260206004820152600d60248201526c646973616c6c6f77207a65726f60981b60448201526064016105fc565b6001600160a01b038281166000908152602081905260409020548183169116036113cd5760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e48185c1c1c9bdd995960821b60448201526064016105fc565b6040516001600160a01b0382166024820152600080516020612bab8339815191529063b61d27f690849060009060440160408051601f198184030181529181526020820180516001600160e01b0316635efcc08b60e11b1790525160e085901b6001600160e01b031916815261144893929190600401612a15565b6000604051808303816000875af1158015611467573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261148f9190810190612a45565b50506001600160a01b0382811660008181526020819052604080822080546001600160a01b0319169486169485179055517f44fc9c54afeb78716cfdca7c7b65d327c824a43d9d7f3842489b1047e0858d859190a35050565b6005546001600160a01b031633148061151057503360009081526002602052604090205460ff165b61152c5760405162461bcd60e51b81526004016105fc90612959565b8281146115675760405162461bcd60e51b8152602060048201526009602482015268042dad2e6dac2e8c6d60bb1b60448201526064016105fc565b60005b838110156115cc576115ba85858381811061158757611587612aef565b905060200201602081019061159c9190612601565b8484848181106115ae576115ae612aef565b90506020020135611df6565b806115c481612b05565b91505061156a565b5050505050565b6001600160a01b03838116600090815260208190526040812054909116331461160e5760405162461bcd60e51b81526004016105fc906128cf565b6040516370a0823160e01b8152600080516020612bab83398151915260048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611663573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168791906128f2565b90506116e3856000856040516024016116a291815260200190565b60408051601f198184030181529190526020810180516001600160e01b0316632e1a7d4d60e01b179052600080516020612bab833981519152929190611bf5565b6040516370a0823160e01b8152600080516020612bab833981519152600482015281906001600160a01b038616906370a0823190602401602060405180830381865afa158015611737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175b91906128f2565b6117659190612921565b604051336024820152604481018290529091506117899085906000906064016107c0565b949350505050565b6005546001600160a01b031633146117bb5760405162461bcd60e51b81526004016105fc90612934565b6001600160a01b038216600081815260026020526040808220805460ff191685151590811790915590519092917f5d328fb3f9d2e4cacafc1777a9d61d193b51514c8916471fe57fed3141e44b5b91a35050565b61181882612079565b15611821575050565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061185757611857612aef565b60200260200101906001600160a01b031690816001600160a01b03168152505061188183826121f6565b505050565b6005546001600160a01b03163314806118ae57503360009081526003602052604090205460ff165b6118e45760405162461bcd60e51b815260206004820152600760248201526610b637b1b5b2b960c91b60448201526064016105fc565b6040516370a0823160e01b8152600080516020612bab833981519152600482015260009073d533a949740bb3306d119cc777fa900ba034cd52906370a0823190602401602060405180830381865afa158015611944573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196891906128f2565b905080156119cb57604051630aa2b75d60e11b815260048101829052600080516020612bab833981519152906315456eba90602401600060405180830381600087803b1580156119b757600080fd5b505af11580156115cc573d6000803e3d6000fd5b50565b6001600160a01b03828116600090815260208190526040902054163314611a075760405162461bcd60e51b81526004016105fc906128cf565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7291906128f2565b9050611a966001600160a01b038316600080516020612bab833981519152836122b0565b6040516370a0823160e01b8152600080516020612bab83398151915260048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0c91906128f2565b6040516001600160a01b0385166024820152600060448201819052919250611b759184916064015b60408051601f198184030181529190526020810180516001600160e01b031663095ea7b360e01b179052600080516020612bab833981519152929190611bf5565b6040516001600160a01b038416602482015260448101829052611b9f908390600090606401611b34565b61188183600083604051602401611bb891815260200190565b60408051601f198184030181529190526020810180516001600160e01b031663b6b55f2560e01b179052600080516020612bab8339815191529291905b604051635b0e93fb60e11b81526000906001600160a01b0386169063b61d27f690611c2890879087908790600401612a15565b6000604051808303816000875af1158015611c47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c6f9190810190612a45565b509050806115cc57600080fd5b60006001600160a01b03821673d533a949740bb3306d119cc777fa900ba034cd521480611cc557506001600160a01b03821673f939e0a03fb07f59a73314e73794be0e57ac1b4e145b15611cd257506000919050565b604051633f9095b760e01b81526001600160a01b0383166004820152732f50d538606fa9edd2b11e2446beb18c9d5846bb90633f9095b790602401602060405180830381865afa925050508015611d46575060408051601f3d908101601f19168201909252611d4391810190612b1e565b60015b15611d545750600092915050565b60405163bdf475c360e01b81526001600160a01b038316600482015260009073f98b45fa17de75fb1ad0e7afd971b0ca00e379fc9063bdf475c390602401602060405180830381865afa158015611daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd39190612b41565b90506001600160a01b03811615611ded5750600092915050565b50600192915050565b6040516001600160a01b03831660248201526044810182905261080190732f50d538606fa9edd2b11e2446beb18c9d5846bb9060009060640160408051601f198184030181529190526020810180516001600160e01b0316631ae26c6560e31b179052600080516020612bab833981519152929190611bf5565b6040516370a0823160e01b8152600080516020612bab83398151915260048201819052600091829073f939e0a03fb07f59a73314e73794be0e57ac1b4e906370a0823190602401602060405180830381865afa158015611ed4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef891906128f2565b9050611f02610d77565b611f3a57670de0b6b3a76400008111611f1c576000611789565b61178973f939e0a03fb07f59a73314e73794be0e57ac1b4e85612302565b60005b600a81101561205a57604051630f41a04d60e11b81526001600160a01b038416600482015273d16d5ec345dd86fb63c6a9c43c517210f102791490631e83409a906024016020604051808303816000875af1158015611fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc491906128f2565b506040516370a0823160e01b81526001600160a01b0384166004820152829073f939e0a03fb07f59a73314e73794be0e57ac1b4e906370a0823190602401602060405180830381865afa15801561201f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204391906128f2565b1161205a578061205281612b05565b915050611f3d565b5061178973f939e0a03fb07f59a73314e73794be0e57ac1b4e85612302565b6001600160a01b0381811660009081526020819052604081205490911633146120b45760405162461bcd60e51b81526004016105fc906128cf565b604051634274debf60e11b8152600080516020612bab83398151915260048201526001600160a01b038316906384e9bd7e90602401600060405180830381600087803b15801561210357600080fd5b505af1158015612117573d6000803e3d6000fd5b50506040516301ddabf160e01b8152600080516020612bab83398151915260048201526001600160a01b03851692506301ddabf19150602401602060405180830381865afa925050508015612189575060408051601f3d908101601f1916820190925261218691810190612b41565b60015b61219557506000919050565b6001600160a01b03811633146121ed5760405162461bcd60e51b815260206004820152601c60248201527f7374726174656779206e6f74207265776172642072656365697665720000000060448201526064016105fc565b50506001919050565b60005b8151811015611881576001600083838151811061221857612218612aef565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1661227c5760405162461bcd60e51b815260206004820152600e60248201526d10b0b8383937bb32b22a37b5b2b760911b60448201526064016105fc565b61229f82828151811061229157612291612aef565b602002602001015133612302565b506122a981612b05565b90506121f9565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526118819084906123bb565b6040516370a0823160e01b8152600080516020612bab833981519152600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa158015612359573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237d91906128f2565b9050806000036123915760009150506105bd565b6040516001600160a01b0384166024820152604481018290526105ba9085906000906064016107c0565b6000612410826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166124909092919063ffffffff16565b90508051600014806124315750808060200190518101906124319190612b5e565b6118815760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016105fc565b6060611789848460008585600080866001600160a01b031685876040516124b79190612b7b565b60006040518083038185875af1925050503d80600081146124f4576040519150601f19603f3d011682016040523d82523d6000602084013e6124f9565b606091505b509150915061250a87838387612515565b979650505050505050565b6060831561258457825160000361257d576001600160a01b0385163b61257d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105fc565b5081611789565b61178983838151156125995781518083602001fd5b8060405162461bcd60e51b81526004016105fc9190612b97565b6001600160a01b03811681146119cb57600080fd5b600080604083850312156125db57600080fd5b82356125e6816125b3565b915060208301356125f6816125b3565b809150509250929050565b60006020828403121561261357600080fd5b81356105ba816125b3565b80151581146119cb57600080fd5b6000806040838503121561263f57600080fd5b823561264a816125b3565b915060208301356125f68161261e565b60008060006060848603121561266f57600080fd5b833561267a816125b3565b92506020840135915060408401356126918161261e565b809150509250925092565b600080604083850312156126af57600080fd5b82356126ba816125b3565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612707576127076126c8565b604052919050565b6000806040838503121561272257600080fd5b823561272d816125b3565b915060208381013567ffffffffffffffff8082111561274b57600080fd5b818601915086601f83011261275f57600080fd5b813581811115612771576127716126c8565b8060051b91506127828483016126de565b818152918301840191848101908984111561279c57600080fd5b938501935b838510156127c657843592506127b6836125b3565b82825293850193908501906127a1565b8096505050505050509250929050565b60008083601f8401126127e857600080fd5b50813567ffffffffffffffff81111561280057600080fd5b6020830191508360208260051b850101111561281b57600080fd5b9250929050565b6000806000806040858703121561283857600080fd5b843567ffffffffffffffff8082111561285057600080fd5b61285c888389016127d6565b9096509450602087013591508082111561287557600080fd5b50612882878288016127d6565b95989497509550505050565b6000806000606084860312156128a357600080fd5b83356128ae816125b3565b925060208401356128be816125b3565b929592945050506040919091013590565b60208082526009908201526821737472617465677960b81b604082015260600190565b60006020828403121561290457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156105bd576105bd61290b565b6020808252600b908201526a21676f7665726e616e636560a81b604082015260600190565b60208082526006908201526510bb37ba32b960d11b604082015260600190565b808201808211156105bd576105bd61290b565b6000826129a957634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176105bd576105bd61290b565b60005b838110156129e05781810151838201526020016129c8565b50506000910152565b60008151808452612a018160208601602086016129c5565b601f01601f19169290920160200192915050565b60018060a01b0384168152826020820152606060408201526000612a3c60608301846129e9565b95945050505050565b60008060408385031215612a5857600080fd5b8251612a638161261e565b602084015190925067ffffffffffffffff80821115612a8157600080fd5b818501915085601f830112612a9557600080fd5b815181811115612aa757612aa76126c8565b612aba601f8201601f19166020016126de565b9150808252866020828501011115612ad157600080fd5b612ae28160208401602086016129c5565b5080925050509250929050565b634e487b7160e01b600052603260045260246000fd5b600060018201612b1757612b1761290b565b5060010190565b600060208284031215612b3057600080fd5b815180600f0b81146105ba57600080fd5b600060208284031215612b5357600080fd5b81516105ba816125b3565b600060208284031215612b7057600080fd5b81516105ba8161261e565b60008251612b8d8184602087016129c5565b9190910192915050565b6020815260006105ba60208301846129e956fe000000000000000000000000f147b8125d2ef93fb6965db97d6746952a133934a2646970667358221220a5c04be43bba584357c50d124fac5010c3208919c33a3885288c1a481051063564736f6c63430008110033
Verified Source Code Partial Match
Compiler: v0.8.17+commit.8df45f5f
EVM: istanbul
Optimization: Yes (200 runs)
StrategyProxy.sol 542 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "contracts/token/ERC20/IERC20.sol";
import "contracts/utils/Address.sol";
import "contracts/token/ERC20/utils/SafeERC20.sol";
import {IEscrow, IGauge, IFeeDistribution, IMetaRegistry, IGaugeController} from "contracts/interfaces/Curve.sol";
import {IProxy, SafeProxy} from "contracts/interfaces/IProxy.sol";
contract StrategyProxy {
using SafeERC20 for IERC20;
using Address for address;
using SafeProxy for IProxy;
uint constant WEEK = 1 weeks;
/// @notice Yearn's voter proxy. Typically referred to as "voter".
IProxy public constant proxy =
IProxy(0xF147b8125d2ef93FB6965Db97D6746952a133934);
/// @notice Curve's token minter.
address public constant mintr = 0xd061D61a4d941c39E5453435B6345Dc261C2fcE0;
/// @notice Curve's CRV token address.
address public constant crv = 0xD533a949740bb3306d119CC777fa900bA034cd52;
/// @notice Curve's crvUSD address (weekly fees paid in this token).
IERC20 public constant crvUSD =
IERC20(0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E);
/// @notice Curve's fee distributor contract.
IFeeDistribution public constant feeDistribution =
IFeeDistribution(0xD16d5eC345Dd86Fb63C6a9C43c517210F1027914);
/// @notice Curve's vote-escrowed Curve address.
IEscrow public constant veCRV =
IEscrow(0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2);
/// @notice Curve's meta-registry. Can pull data from the many existing curve registries.
IMetaRegistry public constant metaRegistry =
IMetaRegistry(0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC);
/// @notice Curve's gauge controller.
IGaugeController public constant gaugeController =
IGaugeController(0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB);
/// @notice Look up the strategy approved for a given Curve gauge.
mapping(address => address) public strategies;
/// @notice Check if a gauge reward token is approved for claiming.
mapping(address => bool) public rewardTokenApproved;
/// @notice Check if an address is an approved voter for gauge weights.
mapping(address => bool) public voters;
/// @notice Check if an address is an approved locker of CRV tokens.
mapping(address => bool) public lockers;
/// @notice Check if an address is an approved admin fee claimer.
address public adminFeeRecipient;
/// @notice Current governance address.
address public governance;
/// @notice Check if an address is an approved factory for deploying Curve voter strategies.
mapping(address => bool) public approvedFactories;
// Events so that indexers can keep track of key actions
event GovernanceSet(address indexed governance);
event AdminFeeRecipientSet(address indexed recipient);
event StrategyApproved(address indexed gauge, address indexed strategy);
event StrategyRevoked(address indexed gauge, address indexed strategy);
event VoterApprovalSet(address indexed voter, bool indexed approved);
event LockerApprovalSet(address indexed locker, bool indexed approved);
event RewardTokenApprovalSet(address indexed token, bool indexed approved);
event FactoryApproved(address indexed factory, bool indexed approved);
event TokenClaimed(
address indexed token,
address indexed recipient,
uint balance
);
constructor(address _adminFeeRecipient) {
require(_adminFeeRecipient != address(0), "Empty admin fee recipient");
governance = msg.sender;
adminFeeRecipient = _adminFeeRecipient;
}
/**
* @notice Approve curve vault factory addresses.
* @dev Must be called by governance. Multiple factories possible (Curve LP, Curve Lend).
* @param _factory Address to set as a curve vault factory.
* @param _approved Whether the address is allowed factory permissions (to approve strategies).
*/
function approveFactory(address _factory, bool _approved) external {
require(msg.sender == governance, "!governance");
approvedFactories[_factory] = _approved;
emit FactoryApproved(_factory, _approved);
}
/**
* @notice Set governance address.
* @dev Must be called by current governance.
* @param _governance Address to set as governance.
*/
function setGovernance(address _governance) external {
require(msg.sender == governance, "!governance");
require(_governance != governance, "already set");
governance = _governance;
emit GovernanceSet(_governance);
}
/**
* @notice Set recipient of weekly crvUSD admin fees.
* @dev Only a single address can be approved at any time. Must be called by governance.
* @param _recipient Address to approve for fees.
*/
function setAdminFeeRecipient(address _recipient) external {
require(msg.sender == governance, "!governance");
require(_recipient != address(0), "zero address");
adminFeeRecipient = _recipient;
emit AdminFeeRecipientSet(_recipient);
}
/**
* @notice Add strategy to a gauge.
* @dev Must be called by governance or factory.
* @param _gauge Gauge to permit strategy on.
* @param _strategy Strategy to approve on gauge.
*/
function approveStrategy(address _gauge, address _strategy) external {
require(
msg.sender == governance || approvedFactories[msg.sender],
"!access"
);
require(_strategy != address(0), "disallow zero");
require(strategies[_gauge] != _strategy, "already approved");
// @dev The following call should fail gracefully on older gauges that don't implement this interface.
proxy.execute(
_gauge,
0,
abi.encodeWithSignature("set_rewards_receiver(address)", _strategy)
);
strategies[_gauge] = _strategy;
emit StrategyApproved(_gauge, _strategy);
}
/**
* @notice Clear any previously approved strategy to a gauge.
* @dev Must be called by governance.
* @param _gauge Gauge from which to remove strategy.
*/
function revokeStrategy(address _gauge) external {
require(msg.sender == governance, "!governance");
address _strategy = strategies[_gauge];
require(_strategy != address(0), "already revoked");
// @dev The following call should fail gracefully on older gauges that don't implement this interface.
proxy.execute(
_gauge,
0,
abi.encodeWithSignature("set_rewards_receiver(address)", address(0))
);
strategies[_gauge] = address(0);
emit StrategyRevoked(_gauge, _strategy);
}
/**
* @notice Approve an address for voting on gauge weights.
* @dev Must be called by governance.
* @param _voter Voter to add.
* @param _approved Whether the address is allowed to vote.
*/
function approveVoter(address _voter, bool _approved) external {
require(msg.sender == governance, "!governance");
voters[_voter] = _approved;
emit VoterApprovalSet(_voter, _approved);
}
/**
* @notice Approve an address for locking CRV.
* @dev Must be called by governance.
* @param _locker Locker to add.
* @param _approved Whether the address is allowed to lock.
*/
function approveLocker(address _locker, bool _approved) external {
require(msg.sender == governance, "!governance");
lockers[_locker] = _approved;
emit LockerApprovalSet(_locker, _approved);
}
/**
* @notice Lock CRV into veCRV contract.
* @dev Must be called by governance or locker.
*/
function lock() external {
require(msg.sender == governance || lockers[msg.sender], "!locker");
uint256 amount = IERC20(crv).balanceOf(address(proxy));
if (amount > 0) proxy.increaseAmount(amount);
}
/**
* @notice Extend veCRV lock time to maximum amount of 4 years.
* @dev Must be called by governance or locker.
*/
function maxLock() external {
require(msg.sender == governance || lockers[msg.sender], "!locker");
uint max = block.timestamp + (365 days * 4);
uint lock_end = veCRV.locked__end(address(proxy));
if (lock_end < (max / WEEK) * WEEK) {
proxy.safeExecute(
address(veCRV),
0,
abi.encodeWithSignature("increase_unlock_time(uint256)", max)
);
}
}
/**
* @notice Vote on a gauge.
* @dev Must be called by governance or voter.
* @param _gauge The gauge to vote on.
* @param _weight Weight to vote with.
*/
function vote(address _gauge, uint256 _weight) external {
require(msg.sender == governance || voters[msg.sender], "!voter");
_vote(_gauge, _weight);
}
/**
* @notice Vote on a multiple gauges.
* @dev Must be called by governance or voter.
* @param _gauges List of gauges to vote on.
* @param _weights List of weight to vote with.
*/
function voteMany(
address[] calldata _gauges,
uint256[] calldata _weights
) external {
require(msg.sender == governance || voters[msg.sender], "!voter");
require(_gauges.length == _weights.length, "!mismatch");
for (uint256 i = 0; i < _gauges.length; i++) {
_vote(_gauges[i], _weights[i]);
}
}
function _vote(address _gauge, uint256 _weight) internal {
proxy.safeExecute(
address(gaugeController),
0,
abi.encodeWithSignature(
"vote_for_gauge_weights(address,uint256)",
_gauge,
_weight
)
);
}
/**
* @notice Withdraw exact amount of LPs from gauge.
* @dev Must be called by the strategy approved for the given gauge.
* @param _gauge The gauge from which to withdraw.
* @param _token The LP token to withdraw from gauge.
* @param _amount The exact amount of LPs with withdraw.
*/
function withdraw(
address _gauge,
address _token,
uint256 _amount
) public returns (uint256) {
require(strategies[_gauge] == msg.sender, "!strategy");
uint256 _balance = IERC20(_token).balanceOf(address(proxy));
proxy.safeExecute(
_gauge,
0,
abi.encodeWithSignature("withdraw(uint256)", _amount)
);
_balance = IERC20(_token).balanceOf(address(proxy)) - _balance;
proxy.safeExecute(
_token,
0,
abi.encodeWithSignature(
"transfer(address,uint256)",
msg.sender,
_balance
)
);
return _balance;
}
/**
* @notice Find Yearn voter's full balance within a given gauge.
* @param _gauge The gauge from which to check balance.
*/
function balanceOf(address _gauge) public view returns (uint256) {
return IERC20(_gauge).balanceOf(address(proxy));
}
/**
* @notice Withdraw full balance of voter's LPs from gauge.
* @param _gauge The gauge from which to withdraw.
* @param _token The LP token to withdraw from gauge.
*/
function withdrawAll(
address _gauge,
address _token
) external returns (uint256) {
return withdraw(_gauge, _token, balanceOf(_gauge));
}
/**
* @notice Takes care of depositing Curve LPs into gauge.
* @dev Strategy must first transfer LPs to this contract prior to calling.
* Must be called by strategy approved for this gauge.
* @param _gauge The gauge to deposit LP token into.
* @param _token The LP token to deposit into gauge.
*/
function deposit(address _gauge, address _token) external {
require(strategies[_gauge] == msg.sender, "!strategy");
uint256 _balance = IERC20(_token).balanceOf(address(this));
IERC20(_token).safeTransfer(address(proxy), _balance);
_balance = IERC20(_token).balanceOf(address(proxy));
proxy.safeExecute(
_token,
0,
abi.encodeWithSignature("approve(address,uint256)", _gauge, 0)
);
proxy.safeExecute(
_token,
0,
abi.encodeWithSignature(
"approve(address,uint256)",
_gauge,
_balance
)
);
proxy.safeExecute(
_gauge,
0,
abi.encodeWithSignature("deposit(uint256)", _balance)
);
}
/**
* @notice Abstracts the CRV minting and transfers to an approved strategy with CRV earnings.
* @dev Designed to be called within the harvest function of a strategy.
* @param _gauge The gauge which this strategy is claiming CRV from.
*/
function harvest(address _gauge) external {
require(strategies[_gauge] == msg.sender, "!strategy");
uint256 _balance = IERC20(crv).balanceOf(address(proxy));
proxy.safeExecute(
mintr,
0,
abi.encodeWithSignature("mint(address)", _gauge)
);
_balance = IERC20(crv).balanceOf(address(proxy)) - _balance;
proxy.safeExecute(
crv,
0,
abi.encodeWithSignature(
"transfer(address,uint256)",
msg.sender,
_balance
)
);
}
/**
* @notice Claim share of weekly admin fees from Curve fee distributor.
* @dev Admin fees become available every Thursday at 00:00 UTC
* @return Amount of crvUSD claimed.
*/
function claimAdminFees() external returns (uint) {
require(msg.sender == adminFeeRecipient, "!authorized");
return _claimAdminFees(adminFeeRecipient);
}
/**
* @notice Allow governance to claim weekly admin fees from Curve fee distributor.
* @param _recipient Where to send the crvUSD.
* @return Amount of crvUSD claimed.
*/
function claimAdminFeesTo(address _recipient) external returns (uint) {
require(msg.sender == governance, "!governance");
return _claimAdminFees(_recipient);
}
function _claimAdminFees(address _recipient) internal returns (uint) {
address p = address(proxy);
uint balance = crvUSD.balanceOf(p);
if (!canClaim()) {
return balance > 1e18 ? _transferBalance(crvUSD, _recipient) : 0;
}
for (uint i; i < 10; i++) {
// @dev max 10 tries is up to 500 weeks of history.
feeDistribution.claim(p);
if (crvUSD.balanceOf(p) > balance) break;
}
return _transferBalance(crvUSD, _recipient);
}
/**
* @notice Cast a DAO vote
* @dev Allows for casting a vote in either the admin or parameter DAO.
* @param _target The address of the DAO contract
* @param _voteId Vote identifier
* @param _support true/false
*/
function dao_vote(
address _target,
uint _voteId,
bool _support
) external returns (uint amount) {
require(voters[msg.sender] || msg.sender == governance, "!voter");
require(
_target == 0xE478de485ad2fe566d49342Cbd03E49ed7DB3356 ||
_target == 0xBCfF8B0b9419b9A88c44546519b1e909cF330399,
"invalid dao contract"
);
bytes memory data = abi.encodeWithSignature(
"vote(uint256,bool,bool)",
_voteId,
_support,
false
);
proxy.safeExecute(_target, 0, data);
}
/**
* @notice Check if any admin fees are available for claim.
* @return Whether admin fees are claimable.
*/
function canClaim() public view returns (bool) {
uint weekStart = (block.timestamp / WEEK) * WEEK;
uint lastClaimWeek = feeDistribution.time_cursor_of(address(proxy));
uint lastCheckpoint = feeDistribution.last_token_time();
if (
block.timestamp > lastClaimWeek + WEEK && lastCheckpoint > weekStart
) return true;
return false;
}
/**
* @notice Claim non-CRV token incentives from the gauge and transfer to strategy.
* @dev There are two claim methods:
* - new (preferred): strategy is set as recipient in gauge contract. Rewards are forwarded directly to strategy.
* - legacy: fallback method for old gauges that do not support rewards_receiver interface. In this case, reward
* tokens are sent to voter and then swept to strategy.
* @param _gauge The gauge which this strategy is claiming rewards.
* @param _token The token to be claimed to the approved strategy.
*/
function claimRewards(address _gauge, address _token) external {
if (_claimRewards(_gauge)) return;
address[] memory tokens = new address[](1);
tokens[0] = _token;
_legacyClaimRewards(_gauge, tokens);
}
/**
* @notice Claim non-CRV token incentives from the gauge and transfer to strategy.
* @dev Must be called by the strategy approved for the given gauge.
* @param _gauge The gauge which this strategy is claiming rewards.
* @param _tokens The token(s) to be claimed to the approved strategy.
*/
function claimManyRewards(
address _gauge,
address[] memory _tokens
) external {
if (_claimRewards(_gauge)) return;
_legacyClaimRewards(_gauge, _tokens);
}
// use this internal function to eliminate the need for transfers when claiming extra rewards
function _claimRewards(address _gauge) internal returns (bool) {
require(strategies[_gauge] == msg.sender, "!strategy");
IGauge(_gauge).claim_rewards(address(proxy));
try IGauge(_gauge).rewards_receiver(address(proxy)) returns (
address receiver
) {
require(receiver == msg.sender, "strategy not reward receiver"); // Reverts txn if fails.
} catch {
return false;
}
return true;
}
function _legacyClaimRewards(
address _gauge,
address[] memory _tokens
) internal {
for (uint256 i; i < _tokens.length; ++i) {
require(rewardTokenApproved[_tokens[i]], "!approvedToken");
_transferBalance(IERC20(_tokens[i]), msg.sender);
}
}
/**
* @notice Approve reward tokens to be claimed by strategies.
* @dev Must be called by governance. Only required for legacy gauges without rewards_receiver interface.
* @param _token The token to be claimed.
* @param _approved Whether a reward token is approved to be claimed.
*/
function approveRewardToken(address _token, bool _approved) external {
require(msg.sender == governance, "!governance");
if (_approved) require(_isSafeToken(_token), "!safeToken");
require(rewardTokenApproved[_token] != _approved, "No approval change");
rewardTokenApproved[_token] = _approved;
emit RewardTokenApprovalSet(_token, _approved);
}
// make sure a strategy can't yoink gauge or LP tokens.
function _isSafeToken(address _token) internal view returns (bool) {
if (_token == crv || _token == address(crvUSD)) return false;
try gaugeController.gauge_types(_token) {
return false;
} catch {} // @dev: Since we expect try should fail, proceed without any catch logic error here.
address pool = metaRegistry.get_pool_from_lp_token(_token);
if (pool != address(0)) return false;
return true;
}
function _transferBalance(
IERC20 _token,
address _recipient
) internal returns (uint) {
uint balance = _token.balanceOf(address(proxy));
if (balance == 0) return 0;
proxy.safeExecute(
address(_token),
0,
abi.encodeWithSignature(
"transfer(address,uint256)",
_recipient,
balance
)
);
return balance;
}
}
Address.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Curve.sol 94 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface ICurveFi {
function get_virtual_price() external view returns (uint256);
function add_liquidity(
// EURs
uint256[2] calldata amounts,
uint256 min_mint_amount
) external;
function add_liquidity(
// sBTC pool
uint256[3] calldata amounts,
uint256 min_mint_amount
) external;
function add_liquidity(
// bUSD pool
uint256[4] calldata amounts,
uint256 min_mint_amount
) external;
function remove_liquidity_imbalance(uint256[4] calldata amounts, uint256 max_burn_amount) external;
function remove_liquidity(uint256 _amount, uint256[4] calldata amounts) external;
function remove_liquidity_one_coin(
uint256 _token_amount,
int128 i,
uint256 min_amount
) external;
function exchange(
int128 from,
int128 to,
uint256 _from_amount,
uint256 _min_to_amount
) external;
function exchange_underlying(
int128 from,
int128 to,
uint256 _from_amount,
uint256 _min_to_amount
) external;
function balances(int128) external view returns (uint256);
function get_dy(
int128 from,
int128 to,
uint256 _from_amount
) external view returns (uint256);
}
interface Zap {
function remove_liquidity_one_coin(
uint256,
int128,
uint256
) external;
}
interface IGauge {
function deposit(uint256) external;
function balanceOf(address) external view returns (uint256);
function withdraw(uint256) external;
function claim_rewards(address) external;
function reward_tokens(uint256) external view returns (address);
function rewards_receiver(address) external view returns (address);
}
interface IFeeDistribution {
function claim(address) external returns (uint);
function claim_many(address[20] calldata) external returns (bool);
function last_token_time() external view returns (uint256);
function time_cursor() external view returns (uint256);
function time_cursor_of(address) external view returns (uint256);
}
interface IEscrow {
function increase_unlock_time(uint256 _time) external;
function locked__end(address user) external returns (uint);
}
interface IMetaRegistry {
function get_pool_from_lp_token(address _lp) external view returns (address);
}
interface IGaugeController {
function gauge_types(address _gauge) external view returns (int128);
}
IProxy.sol 24 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface IProxy {
function execute(
address to,
uint256 value,
bytes calldata data
) external returns (bool, bytes memory);
function increaseAmount(uint256) external;
}
library SafeProxy {
function safeExecute(
IProxy proxy,
address to,
uint256 value,
bytes memory data
) internal {
(bool success, ) = proxy.execute(to, value, data);
require(success);
}
}
IERC20.sol 78 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
SafeERC20.sol 143 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "contracts/token/ERC20/IERC20.sol";
import "contracts/token/ERC20/extensions/IERC20Permit.sol";
import "contracts/utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
IERC20Permit.sol 60 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
Read Contract
adminFeeRecipient 0xee11d5eb → address
approvedFactories 0x3777261d → bool
balanceOf 0x70a08231 → uint256
canClaim 0x6dc7a627 → bool
crv 0x6a4874a1 → address
crvUSD 0x9bec8288 → address
feeDistribution 0x2479b177 → address
gaugeController 0x99eecb3b → address
governance 0x5aa6e675 → address
lockers 0x2c8e7a21 → bool
metaRegistry 0x44693a4b → address
mintr 0xd1e61dcb → address
proxy 0xec556889 → address
rewardTokenApproved 0x2fa7dcf5 → bool
strategies 0x39ebf823 → address
veCRV 0x22a2f07d → address
voters 0xa3ec138d → bool
Write Contract 21 functions
These functions modify contract state and require a wallet transaction to execute.
approveFactory 0x6e7dbabb
address _factory
bool _approved
approveLocker 0x39e2da54
address _locker
bool _approved
approveRewardToken 0x55fef7b4
address _token
bool _approved
approveStrategy 0xc494448e
address _gauge
address _strategy
approveVoter 0xe95df3de
address _voter
bool _approved
claimAdminFees 0xa345bf43
No parameters
returns: uint256
claimAdminFeesTo 0x8c89d81b
address _recipient
returns: uint256
claimManyRewards 0xbfad6f8c
address _gauge
address[] _tokens
claimRewards 0xf1e42ccd
address _gauge
address _token
dao_vote 0x3e9a2ee1
address _target
uint256 _voteId
bool _support
returns: uint256
deposit 0xf9609f08
address _gauge
address _token
harvest 0x0e5c011e
address _gauge
lock 0xf83d08ba
No parameters
maxLock 0x6c0b3e46
No parameters
revokeStrategy 0xbb994d48
address _gauge
setAdminFeeRecipient 0x23a53c32
address _recipient
setGovernance 0xab033ea9
address _governance
vote 0x5f74bbde
address _gauge
uint256 _weight
voteMany 0xc9818d7b
address[] _gauges
uint256[] _weights
withdraw 0xd9caed12
address _gauge
address _token
uint256 _amount
returns: uint256
withdrawAll 0x09cae2c8
address _gauge
address _token
returns: uint256
Recent Transactions
No transactions found for this address