Address Contract Partially Verified
Address
0x66a0f676479Cee1d7373f3DC2e2952778BfF5bd6
Balance
0 ETH
Nonce
1
Code Size
24195 bytes
Creator
0x641AD78B...e689 at tx 0x0d6658ee...fe3599
Indexed Transactions
0
Contract Bytecode
24195 bytes
0x6080604052600436106103bb5760003560e01c806395d89b41116101f2578063c31245251161010d578063dd62ed3e116100a0578063e3073bfb1161006f578063e3073bfb146113aa578063e742806a146113d4578063e7881cda1461140d578063fc527bf51461144c576103c5565b8063dd62ed3e146111ee578063df0618d214611229578063df2d02b1146112a3578063e1d033e9146112eb576103c5565b8063d6565a2d116100dc578063d6565a2d14611149578063d826492014611173578063d8d44a2914611188578063db74559b146111bb576103c5565b8063c312452514611072578063c74c0fac146110ba578063ce8f9f00146110cf578063d1cf9098146110f9576103c5565b8063ae3d1de211610185578063be21ff7011610154578063be21ff7014610f52578063bf58f6d214610f7c578063c172628e14610fc5578063c23d656414611048576103c5565b8063ae3d1de214610ecb578063b381a81114610efe578063b543c4ba14610f13578063bba85e1f14610f28576103c5565b8063a4ed0550116101c1578063a4ed055014610d8e578063a50af89514610e2b578063a9059cbb14610e5f578063a91b19f214610e98576103c5565b806395d89b4114610cc257806399c2def414610cd75780639b57ab1214610d0b5780639e78fb4f14610d79576103c5565b806348e4ccab116102e257806370a08231116102755780638649102b116102445780638649102b14610bb357806387da627414610bfb57806389201d4e14610c105780638a26306014610cad576103c5565b806370a082311461095857806375c3fa4f1461098b578063763241d3146109be578063779e2e1814610b70576103c5565b8063601f37ac116102b1578063601f37ac146108ca57806360e4c651146108fd578063613fc9fd1461092e5780636ba631cf14610943576103c5565b806348e4ccab146107dc5780634dfc7a031461080d5780634f47b16d146108405780635b2023871461087a576103c5565b806320429fac1161035a57806333060d901161032957806333060d90146107035780633697e979146107365780633b58afe71461076457806342966c68146107b0576103c5565b806320429fac146105c357806323672d8a1461060657806323b872dd14610695578063313ce567146106d8576103c5565b8063095ea7b311610396578063095ea7b3146104a457806310748592146104dd57806318160ddd1461054d5780631c0b37e114610562576103c5565b80625ada7f146103ca57806302cbb266146103f157806306fdde031461041a576103c5565b366103c557600080fd5b600080fd5b3480156103d657600080fd5b506103df61157c565b60408051918252519081900360200190f35b3480156103fd57600080fd5b50610406611582565b604080519115158252519081900360200190f35b34801561042657600080fd5b5061042f611592565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610469578181015183820152602001610451565b50505050905090810190601f1680156104965780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104b057600080fd5b50610406600480360360408110156104c757600080fd5b506001600160a01b038135169060200135611626565b3480156104e957600080fd5b506105206004803603604081101561050057600080fd5b5080356001600160a01b031690602001356001600160801b031916611644565b60408051958652602086019490945284840192909252606084015215156080830152519081900360a00190f35b34801561055957600080fd5b506103df6116f2565b6105976004803603604081101561057857600080fd5b5080356001600160401b031690602001356001600160a01b03166116f8565b604080516001600160801b03199485168152602081019390935292168183015290519081900360600190f35b3480156105cf57600080fd5b506103df600480360360408110156105e657600080fd5b5080356001600160a01b031690602001356001600160801b031916611947565b34801561061257600080fd5b506106456004803603606081101561062957600080fd5b506001600160a01b038135169060208101359060400135611964565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610681578181015183820152602001610669565b505050509050019250505060405180910390f35b3480156106a157600080fd5b50610406600480360360608110156106b857600080fd5b506001600160a01b03813581169160208101359091169060400135611ad1565b3480156106e457600080fd5b506106ed611b40565b6040805160ff9092168252519081900360200190f35b34801561070f57600080fd5b506103df6004803603602081101561072657600080fd5b50356001600160a01b0316611b49565b34801561074257600080fd5b5061074b611b5b565b6040805163ffffffff9092168252519081900360200190f35b34801561077057600080fd5b506107976004803603602081101561078757600080fd5b50356001600160a01b0316611b6e565b6040805192835260208301919091528051918290030190f35b3480156107bc57600080fd5b506107da600480360360208110156107d357600080fd5b5035611b87565b005b3480156107e857600080fd5b506107f1611b94565b604080516001600160401b039092168252519081900360200190f35b34801561081957600080fd5b506107da6004803603602081101561083057600080fd5b50356001600160a01b0316611bd9565b34801561084c57600080fd5b506107da6004803603604081101561086357600080fd5b506001600160801b03198135169060200135611c4a565b34801561088657600080fd5b506108ad6004803603602081101561089d57600080fd5b50356001600160a01b0316611c69565b604080516001600160801b03199092168252519081900360200190f35b3480156108d657600080fd5b506103df600480360360208110156108ed57600080fd5b50356001600160a01b0316611cc8565b34801561090957600080fd5b50610912611cda565b604080516001600160a01b039092168252519081900360200190f35b34801561093a57600080fd5b506107da611ce9565b34801561094f57600080fd5b50610912611cf6565b34801561096457600080fd5b506103df6004803603602081101561097b57600080fd5b50356001600160a01b0316611d0c565b34801561099757600080fd5b506108ad600480360360208110156109ae57600080fd5b50356001600160a01b0316611d27565b3480156109ca57600080fd5b506107da600480360360608110156109e157600080fd5b810190602081018135600160201b8111156109fb57600080fd5b820183602082011115610a0d57600080fd5b803590602001918460208302840111600160201b83111715610a2e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610a7d57600080fd5b820183602082011115610a8f57600080fd5b803590602001918460208302840111600160201b83111715610ab057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610aff57600080fd5b820183602082011115610b1157600080fd5b803590602001918460208302840111600160201b83111715610b3257600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611d79945050505050565b348015610b7c57600080fd5b5061040660048036036040811015610b9357600080fd5b5080356001600160a01b031690602001356001600160801b031916611dda565b348015610bbf57600080fd5b50610bdd60048036036020811015610bd657600080fd5b5035611ebe565b60408051938452602084019290925282820152519081900360600190f35b348015610c0757600080fd5b506107da611edf565b348015610c1c57600080fd5b50610c5360048036036040811015610c3357600080fd5b5080356001600160a01b031690602001356001600160801b03191661214d565b604080516001600160a01b0390991689526001600160801b031990971660208901528787019590955260608701939093529015156080860152151560a0850152151560c0840152151560e083015251908190036101000190f35b348015610cb957600080fd5b5061091261243f565b348015610cce57600080fd5b5061042f61244e565b348015610ce357600080fd5b506103df60048036036020811015610cfa57600080fd5b50356001600160801b0319166124af565b348015610d1757600080fd5b50610d4e60048036036040811015610d2e57600080fd5b5080356001600160801b03191690602001356001600160401b031661270c565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b348015610d8557600080fd5b506107da612ba0565b348015610d9a57600080fd5b50610dd160048036036040811015610db157600080fd5b5080356001600160a01b031690602001356001600160801b031916612c6a565b604080519b8c5260208c019a909a528a8a019890985260608a0196909652608089019490945260a088019290925260c087015260e08601526101008501521515610120840152151561014083015251908190036101600190f35b348015610e3757600080fd5b506103df60048036036020811015610e4e57600080fd5b50356001600160801b031916612d96565b348015610e6b57600080fd5b5061040660048036036040811015610e8257600080fd5b506001600160a01b038135169060200135612f2b565b348015610ea457600080fd5b506107da60048036036020811015610ebb57600080fd5b50356001600160401b0316612f3f565b348015610ed757600080fd5b506108ad60048036036020811015610eee57600080fd5b50356001600160a01b0316612f99565b348015610f0a57600080fd5b5061074b612feb565b348015610f1f57600080fd5b50610912612ff7565b348015610f3457600080fd5b506103df60048036036020811015610f4b57600080fd5b503561300f565b348015610f5e57600080fd5b506103df60048036036020811015610f7557600080fd5b5035613021565b348015610f8857600080fd5b506108ad60048036036060811015610f9f57600080fd5b5080356001600160a01b031690602081013590604001356001600160f81b031916613033565b348015610fd157600080fd5b5061100860048036036040811015610fe857600080fd5b5080356001600160a01b031690602001356001600160801b03191661308e565b604080516001600160a01b0390961686526001600160801b0319909416602086015284840192909252606084015215156080830152519081900360a00190f35b34801561105457600080fd5b506103df6004803603602081101561106b57600080fd5b50356130da565b34801561107e57600080fd5b506110876130ec565b604080519687526020870195909552858501939093526060850191909152608084015260a0830152519081900360c00190f35b3480156110c657600080fd5b50610912613101565b3480156110db57600080fd5b506108ad600480360360208110156110f257600080fd5b5035613119565b34801561110557600080fd5b506105976004803603608081101561111c57600080fd5b506001600160a01b0381358116916020810135916001600160401b03604083013516916060013516613249565b34801561115557600080fd5b50610bdd6004803603602081101561116c57600080fd5b5035613534565b34801561117f57600080fd5b50610912613555565b34801561119457600080fd5b506107da600480360360208110156111ab57600080fd5b50356001600160a01b031661356d565b3480156111c757600080fd5b506103df600480360360208110156111de57600080fd5b50356001600160a01b03166135ad565b3480156111fa57600080fd5b506103df6004803603604081101561121157600080fd5b506001600160a01b03813581169160200135166135bf565b34801561123557600080fd5b5061126c6004803603604081101561124c57600080fd5b5080356001600160a01b031690602001356001600160801b0319166135ea565b6040805195865260208601949094526001600160401b03928316858501529116606084015215156080830152519081900360a00190f35b3480156112af57600080fd5b50610597600480360360608110156112c657600080fd5b5080359060208101356001600160401b031690604001356001600160a01b0316613637565b3480156112f757600080fd5b5061132e6004803603604081101561130e57600080fd5b5080356001600160a01b031690602001356001600160801b0319166139d2565b604080519c8d5260208d019b909b528b8b01999099526001600160401b0397881660608c015295871660808b015293861660a08a01529190941660c088015260e08701939093526101008601929092526101208501919091526001600160a01b0316610140840152151561016083015251908190036101800190f35b3480156113b657600080fd5b50610797600480360360208110156113cd57600080fd5b5035613a5e565b3480156113e057600080fd5b506107da600480360360408110156113f757600080fd5b506001600160a01b038135169060200135613a77565b34801561141957600080fd5b506106456004803603606081101561143057600080fd5b506001600160a01b038135169060208101359060400135613a98565b34801561145857600080fd5b506107da6004803603604081101561146f57600080fd5b810190602081018135600160201b81111561148957600080fd5b82018360208201111561149b57600080fd5b803590602001918460208302840111600160201b831117156114bc57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561150b57600080fd5b82018360208201111561151d57600080fd5b803590602001918460208302840111600160201b8311171561153e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613c02945050505050565b600d5481565b600c54600160e01b900460ff1681565b60028054604080516020601f600019610100600187161502019094168590049384018190048102820181019092528281526060939092909183018282801561161b5780601f106115f05761010080835404028352916020019161161b565b820191906000526020600020905b8154815290600101906020018083116115fe57829003601f168201915b505050505090505b90565b600061163a611633613c57565b8484613c5b565b5060015b92915050565b6001600160a01b03821660009081526016602090815260408083206001600160801b0319851684528252808320815160a08101835281548082526001830154948201949094526002909101546001600160401b03808216938301849052600160401b8204166060830152600160801b900460ff1615156080820152909290819081906116cf81613ce3565b6060820151608090920151969995985096506001600160401b0316949392505050565b60055490565b60408051600280825260608201835260009283928392839260208301908036833701905050905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160008151811061174157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061176f57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506000737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b0316637ff36ab5346001853342611c20016040518663ffffffff1660e01b81526004018085815260200180602001846001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015611828578181015183820152602001611810565b50505050905001955050505050506000604051808303818588803b15801561184f57600080fd5b505af1158015611863573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052602081101561188d57600080fd5b8101908080516040519392919084600160201b8211156118ac57600080fd5b9083019060208201858111156118c157600080fd5b82518660208202830111600160201b821117156118dd57600080fd5b82525081516020918201928201910280838360005b8381101561190a5781810151838201526020016118f2565b5050505090500160405250505090506119388160018151811061192957fe5b60200260200101518888613637565b94509450945050509250925092565b601360209081526000928352604080842090915290825290205481565b60606000808411801561198e57506001600160a01b0385166000908152600f602052604090205484105b6119b0576001600160a01b0385166000908152600f60205260409020546119cd565b6001600160a01b0385166000908152600f60205260409020548490035b9050600080841180156119df57508382115b6119ea5760006119ee565b8382035b905060008183036001600160401b0381118015611a0a57600080fd5b50604051908082528060200260200182016040528015611a34578160200160208202803683370190505b509350825b82811115611ac6576000611a56896000198401600160f81b613033565b6001600160a01b038a1660009081526014602090815260408083206001600160801b03198516845290915290206001015490915015611abc5780868481518110611a9c57fe5b6001600160801b0319909216602092830291909101909101526001909201915b5060001901611a39565b505050509392505050565b6000611b2b84611adf613c57565b6001600160a01b0387166000908152600160205260408120611b2691879190611b06613c57565b6001600160a01b0316815260208101919091526040016000205490613d6b565b613c5b565b611b36848484613d80565b5060019392505050565b60045460ff1690565b600f6020526000908152604090205481565b600c54600160201b900463ffffffff1681565b6012602052600090815260409020805460019091015482565b611b913382613e52565b50565b60007f000000000000000000000000000000000000000000000000000000005fa9d800611bbf613ef6565b1015611bcc576000611bd4565b611bd4613efa565b905090565b601d546001600160a01b03163314611bf057600080fd5b6001600160a01b038116600090815260126020526040902069021e19e0c9bab24000009055611c1d613f0c565b6001600160a01b0390911660009081526012602052604090206001600160401b0391909116600190910155565b611c5a611c55613efa565b613f1e565b611c6533838361423f565b5050565b6001600160a01b03811660009081526010602052604081205415611cc0576001600160a01b038216600090815260106020526040902054611cbb908390611cb1906001613d6b565b600160f91b613033565b61163e565b600092915050565b60116020526000908152604090205481565b601d546001600160a01b031681565b611cf4611c55613efa565b565b600c54600160401b90046001600160a01b031681565b6001600160a01b031660009081526020819052604090205490565b6001600160a01b03811660009081526011602052604081205415611cc0576001600160a01b038216600090815260116020526040902054611cbb908390611d6f906001613d6b565b600360f81b613033565b60005b8351811015611dd457611dc9848281518110611d9457fe5b6020026020010151848381518110611da857fe5b6020026020010151848481518110611dbc57fe5b6020026020010151613637565b505050600101611d7c565b50505050565b6001600160a01b0382811660009081526014602090815260408083206001600160801b03198616845282528083208151610180810183528154815260018201549381019390935260028101549183019190915260038101546001600160401b038082166060850152600160401b820481166080850152600160801b8204811660a0850152600160c01b9091041660c0830152600481015460e08301526005810154610100830152600681015461012083015260070154928316610140820152600160a01b90920460ff16151561016083015290611eb6816145bd565b949350505050565b601b6020526000908152604090208054600182015460029092015490919083565b6000806000600c60089054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015611f3257600080fd5b505afa158015611f46573d6000803e3d6000fd5b505050506040513d6060811015611f5c57600080fd5b50805160208083015160409384015184516001600160701b03808616825283169381019390935263ffffffff811683860152935192965094509192507f17057eec9ed80c65db1c29e57a343df0e9f052cf0f5ec6e93bc084533ae9b8c99181900360600190a1600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316600c60089054906101000a90046001600160a01b03166001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d602081101561205a57600080fd5b50516001600160a01b0316146120705782612072565b835b6001600160701b0316905060006120876116f2565b156120ad576120a86120976116f2565b6120a28460c861461e565b9061464c565b6120b0565b60005b90506028811080156120cc5750600c54600160e01b900460ff16155b156120d9576120d961466e565b603c811180156120f75750600c54600160e01b900460ff1615156001145b1561210457612104614683565b600c5460408051600160e01b90920460ff1615158252517fbbf65e071e5468fb599b01ba3b914ae6065cf10ad084e0efe2133f7eaa8979bd916020908290030190a15050505050565b6000806000806000806000806000601560008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160801b0319166001600160801b03191681526020019081526020016000206040518060a00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160009054906101000a900460801b6001600160801b0319166001600160801b031916815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff16151515158152505090508060000151985080602001519750806080015194506000601460008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a6001600160801b0319166001600160801b0319168152602001908152602001600020604051806101800160405290816000820154815260200160018201548152602001600282015481526020016003820160009054906101000a90046001600160401b03166001600160401b03166001600160401b031681526020016003820160089054906101000a90046001600160401b03166001600160401b03166001600160401b031681526020016003820160109054906101000a90046001600160401b03166001600160401b03166001600160401b031681526020016003820160189054906101000a90046001600160401b03166001600160401b03166001600160401b031681526020016004820154815260200160058201548152602001600682015481526020016007820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016007820160149054906101000a900460ff16151515158152505090508061012001519750612410816124028385614692565b61240b84614717565b614747565b9650806101600151945061242381614775565b925061242e816145bd565b935050509295985092959890939650565b601e546001600160a01b031681565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561161b5780601f106115f05761010080835404028352916020019161161b565b60006124bc611c55613efa565b6000806124c9338561478e565b6040805161018081018252835480825260018501546020830181905260028601549383019390935260038501546001600160401b038082166060850152600160401b820481166080850152600160801b8204811660a0850152600160c01b9091041660c0830152600485015460e08301526005850154610100830152600685015461012083018190526007909501546001600160a01b038116610140840152600160a01b900460ff16151561016083015290955091935061258c929091906149d9565b6125a78260a001516001600160401b03168360000151614a36565b6125c38260a001516001600160401b0316836101200151614ae9565b6125e582610140015183610100015184606001516001600160401b0316614b9c565b6125f38260c0015182614c41565b61266081836020015111612608576000612610565b818360200151035b3360009081526013602090815260408083206001600160801b03198a16845290915290819020549085015161014086015160808701518751929093019290916001600160401b0390911690614c87565b8161014001516001600160a01b0316336001600160a01b0316856001600160801b0319167f8cc66e48ebd8c008b36e03ee2f7c3f60a313a34a5bf1f3cb988a7936cd47f0d48560200151866000015187610120015188604001518960c001518960405180878152602001868152602001858152602001848152602001836001600160401b03168152602001828152602001965050505050505060405180910390a4506040015192915050565b600080600080600061271f611c55613efa565b3360009081526014602090815260408083206001600160801b03198b168452909152902060070154600160a01b900460ff1661275a57600080fd5b3360009081526014602090815260408083206001600160801b03198b1684528252918290208251610180810184528154815260018201549281019290925260028101549282019290925260038201546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b909104811660c0830152600483015460e0830152600583015461010083015260068301546101208301526007909201546001600160a01b038116610140830152600160a01b900460ff1615156101608201529087166128415761283c81614d90565b61285d565b61285d876001600160401b031661285783614dc6565b90614def565b95508060a001516001600160401b031686116128795785612882565b61288281614d90565b955061289b816000015161289583614dc6565b88614e01565b94506128a6816145bd565b612975576128b381614e47565b93506128c6858533600660020154614ea0565b81519093506128d59084613d6b565b815260a08101516128ef906001600160401b031684614a36565b6101208101511561293d5761290c85856000600660020154614ea0565b61012082015190925061291f9083613d6b565b61012082015260a081015161293d906001600160401b031683614ae9565b612949600084846149d9565b61297081602001518683610140015184608001516001600160401b03168560000151614c87565b6129f0565b3360009081526013602090815260408083206001600160801b03198c1684529091529020546129a49086614def565b3360009081526013602090815260408083206001600160801b03198d1684528252909120829055820151610140830151608084015184516129f09492916001600160401b031690614c87565b60e081018681523360008181526014602090815260408083206001600160801b03198e168452825291829020855181559085015160018201559084015160028201556060840151600382018054608087015160a088015160c089015167ffffffffffffffff199093166001600160401b039586161767ffffffffffffffff60401b1916600160401b928616929092029190911767ffffffffffffffff60801b1916600160801b91851691909102176001600160c01b0316600160c01b93909116929092029190911790559151600483015561010083015160058301556101208301516006830155610140830151600790920180546101608501516001600160a01b03199091166001600160a01b039094169390931760ff60a01b1916600160a01b9315159390930292909217909155612b299086614edf565b336001600160801b031989167f7b5d0995432c9ea1c8033b358af591013d0deff8dec5f4ae49612eba8bfafc0c87898787612b62613efa565b6040805195865260208601949094528484019290925260608401526001600160401b03166080830152519081900360a00190a3509295509295909350565b604080516364e329cb60e11b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201523060248201529051735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f9163c9c653969160448083019260209291908290030181600087803b158015612c0d57600080fd5b505af1158015612c21573d6000803e3d6000fd5b505050506040513d6020811015612c3757600080fd5b5051600c80546001600160a01b03909216600160401b0268010000000000000000600160e01b0319909216919091179055565b6001600160a01b0382811660009081526014602090815260408083206001600160801b03198616845282528083208151610180810183528154808252600183015494820185905260028301549382019390935260038201546001600160401b0380821660608401819052600160401b8304821660808501819052600160801b8404831660a08601819052600160c01b90940490921660c08501819052600486015460e0860181905260058701546101008701526006870154610120870152600790960154998a16610140860152600160a01b90990460ff161515610160850152979096919590949092909190819081908190612d6581614f7b565b9450612d7081614f9a565b93508061016001519250612d83816145bd565b9150509295989b509295989b9093969950565b6000612da3611c55613efa565b3360009081526016602090815260408083206001600160801b031986168452825291829020825160a08101845281548152600182015492810192909252600201546001600160401b0380821693830193909352600160401b81049092166060820152600160801b90910460ff16151560808201819052612e2257600080fd5b60006080820152612e31613efa565b6001600160401b03166060820152612e4881613ce3565b60208201819052612e5a903390614edf565b600c548151612e7b91600160401b90046001600160a01b0316903390614fc1565b8051600b54612e8991613d6b565b600b553360009081526016602090815260408083206001600160801b0319969096168352948152908490208251815590820151600182018190559382015160029091018054606084015160809094015167ffffffffffffffff199091166001600160401b039384161767ffffffffffffffff60401b1916600160401b93909416929092029290921760ff60801b1916600160801b911515919091021790555090565b600061163a612f38613c57565b8484613d80565b6000816001600160401b0316118015612f705750612f5b613efa565b6001600160401b0316816001600160401b0316105b612f7957600080fd5b6009546001600160401b03821611612f9057600080fd5b611b9181613f1e565b6001600160a01b0381166000908152600f602052604081205415611cc0576001600160a01b0382166000908152600f6020526040902054611cbb908390612fe1906001613d6b565b600160f81b613033565b600c5463ffffffff1681565b739c306cad86550ec80d77668c0a8bee6eb34684b681565b60196020526000908152604090205481565b60186020526000908152604090205481565b604080516bffffffffffffffffffffffff19606086901b16602080830191909152603482018590526001600160f81b0319841660548301528251603581840301815260559092019092528051910120600090611eb690611623565b6015602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401546001600160a01b039093169360809290921b9290919060ff1685565b60176020526000908152604090205481565b600654600754600854600954600a54600b5486565b735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f81565b6000613126611c55613efa565b600c54600160e01b900460ff16151560011461314157600080fd5b600c5461316090600160401b90046001600160a01b03163330856150db565b613168615ce5565b61317133615205565b915061317b613f0c565b6001600160401b0316604082015282815260016080820152600b546131a09084614def565b600b553360008181526016602090815260408083206001600160801b031987168452825291829020845181559084015160018201559083015160029091018054606085015160808601511515600160801b0260ff60801b196001600160401b03928316600160401b0267ffffffffffffffff60401b199390961667ffffffffffffffff19909416939093179190911693909317169190911790556132439061522e565b50919050565b604080516323b872dd60e01b81523360048201523060248201526044810185905290516000918291829188916001600160a01b038316916323b872dd91606480830192602092919082900301818887803b1580156132a657600080fd5b505af11580156132ba573d6000803e3d6000fd5b505050506040513d60208110156132d057600080fd5b50506040805163095ea7b360e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d60048201526024810189905290516001600160a01b0383169163095ea7b39160448083019260209291908290030181600087803b15801561333557600080fd5b505af1158015613349573d6000803e3d6000fd5b505050506040513d602081101561335f57600080fd5b506000905061336e893061524e565b90506000737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b03166338ed17398a6001853342611c20016040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b8381101561340f5781810151838201526020016133f7565b505050509050019650505050505050600060405180830381600087803b15801561343857600080fd5b505af115801561344c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561347557600080fd5b8101908080516040519392919084600160201b82111561349457600080fd5b9083019060208201858111156134a957600080fd5b82518660208202830111600160201b821117156134c557600080fd5b82525081516020918201928201910280838360005b838110156134f25781810151838201526020016134da565b5050505090500160405250505090506135208160028151811061351157fe5b60200260200101518989613637565b9550955095505050505b9450945094915050565b601a6020526000908152604090208054600182015460029092015490919083565b737a250d5630b4cf539739df2c5dacb4c659f2488d81565b601e546001600160a01b0316331461358457600080fd5b601d80546001600160a01b039092166001600160a01b0319928316179055601e80549091169055565b60106020526000908152604090205481565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60166020908152600092835260408084209091529082529020805460018201546002909201549091906001600160401b0380821691600160401b810490911690600160801b900460ff1685565b6000806000613647611c55613efa565b336001600160a01b03851614801590613664575061366484615314565b61366d57600080fd5b60016001600160401b038616108015906136925750613be26001600160401b03861611155b61369b57600080fd5b620f42408610156136ab57600080fd5b60008060006136bc338a8a8a61531f565b6001600160401b0316925092509250600083610120015111156137b3576136e1615ce5565b3381526001600160801b0319831660208201526001608082015261370488615413565b6001600160a01b0389811660009081526015602090815260408083206001600160801b0319868116855290835292819020865181546001600160a01b031916951694909417845590850151600184018054909316608091821c179092558401516002830155606084015160038301558301516004909101805460ff191691151591909117905594506137958861543c565b6137b18460a001516001600160401b031685610120015161545c565b505b3360008181526014602090815260408083206001600160801b031987168452825291829020865181559086015160018201559085015160028201556060850151600382018054608088015160a089015160c08a015167ffffffffffffffff199093166001600160401b039586161767ffffffffffffffff60401b1916600160401b928616929092029190911767ffffffffffffffff60801b1916600160801b91851691909102176001600160c01b0316600160c01b939091169290920291909117905560e0850151600482015561010085015160058201556101208501516006820155610140850151600790910180546101608701516001600160a01b03199091166001600160a01b039093169290921760ff60a01b1916600160a01b921515929092029190911790556138e69061548b565b6138fe836020015184600001518561012001516154ab565b6139198360a001516001600160401b031684600001516154de565b866001600160a01b0316336001600160a01b0316836001600160801b0319167f6619c8f19b39bf3558af16516f9ca110fcac4a7ab6d846d1b02a17b11f703a338660200151876000015188610120015189606001518a608001518b610100015160405180878152602001868152602001858152602001846001600160401b03168152602001836001600160401b03168152602001828152602001965050505050505060405180910390a490945092505093509350939050565b6014602090815260009283526040808420909152908252902080546001820154600283015460038401546004850154600586015460068701546007909701549596949593946001600160401b0380851695600160401b8604821695600160801b8104831695600160c01b909104909216939192906001600160a01b03811690600160a01b900460ff168c565b601c602052600090815260409020805460019091015482565b601d546001600160a01b03163314613a8e57600080fd5b611c658282614edf565b606060008084118015613ac257506001600160a01b03851660009081526010602052604090205484105b613ae4576001600160a01b038516600090815260106020526040902054613b01565b6001600160a01b0385166000908152601060205260409020548490035b905060008084118015613b1357508382115b613b1e576000613b22565b8382035b905060008183036001600160401b0381118015613b3e57600080fd5b50604051908082528060200260200182016040528015613b68578160200160208202803683370190505b509350825b82811115611ac6576000613b8a896000198401600160f91b613033565b6001600160a01b03808b1660009081526015602090815260408083206001600160801b031986168452909152902054919250613bc6911661550d565b15613bf85780868481518110613bd857fe5b6001600160801b0319909216602092830291909101909101526001909201915b5060001901613b6d565b613c0d611c55613efa565b60005b8251811015613c5257613c4a33848381518110613c2957fe5b6020026020010151848481518110613c3d57fe5b602002602001015161423f565b600101613c10565b505050565b3390565b6001600160a01b038316613c6e57600080fd5b6001600160a01b038216613c8157600080fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008061016d61ffff168360400151016001600160401b0316905060008160066003015410613d125781613d16565b6009545b60408501519091506001600160401b03165b81811015613d63576000818152601c60205260409020600101548551670de0b6b3a76400000281613d5557fe5b049390930192600101613d28565b505050919050565b600082821115613d7a57600080fd5b50900390565b6001600160a01b038316613d9357600080fd5b6001600160a01b038216613da657600080fd5b6001600160a01b038316600090815260208190526040902054613dc99082613d6b565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613df89082614def565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6001600160a01b038216613e6557600080fd5b6001600160a01b038216600090815260208190526040902054613e889082613d6b565b6001600160a01b038316600090815260208190526040902055600554613eae9082613d6b565b6005556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b4290565b6000611bd4613f07613ef6565b61551b565b6000613f16613efa565b600101905090565b613f26611edf565b600654600954600091905b836001600160401b0316811015611dd45760001981016000908152601a602081815260408084206002015485855260178352818520549383529381902081516060810183528154815260019091015492810192909252919092019082018190526007549094508410613fa4576000613fab565b6007548490035b815261406a61405684613fbc6116f2565b60008681526019602090815260409182902054600c5483516330550a4b60e01b815263ffffffff909116600482015292519092739c306cad86550ec80d77668c0a8bee6eb34684b6926330550a4b92602480840193829003018186803b15801561402557600080fd5b505afa158015614039573d6000803e3d6000fd5b505050506040513d602081101561404f57600080fd5b505161554c565b82516120a290670de0b6b3a764000061461e565b60208083019182526000848152601a825260408082208551815593516001808601919091558186015160029586015560001987018352601b80855282842090950154878452601885528284205495855292829020825160608101845281548152910154938101939093529201918101829052600a549195509085106140f05760006140f7565b600a548590035b815261410d614056856141086116f2565b615569565b60208083019182526000858152601b8252604080822085518155935160018086019190915581860151600290950194909455601c83529081902081518083019092529092015490820152600b5481526141fc6140568661416b6116f2565b600c54604080516330550a4b60e01b8152600160201b90920463ffffffff16600483015251739c306cad86550ec80d77668c0a8bee6eb34684b6916330550a4b916024808301926020929190829003018186803b1580156141cb57600080fd5b505afa1580156141df573d6000803e3d6000fd5b505050506040513d60208110156141f557600080fd5b5051615578565b60208083019182526000868152601c90915260409020825181559051600190910155614226615589565b5050600980546001908101909155919091019050613f31565b6001600160a01b0380841660009081526015602090815260408083206001600160801b0319808816855290835292819020815160a08101835281549095168552600180820154608090811b90951693860193909352600281015491850191909152600381015460608501526004015460ff161515918301829052146142c357600080fd5b80516020808301516001600160a01b0380841660009081526014845260408082206001600160801b03198516835285528082208151610180810183528154815260018201549681019690965260028101549186019190915260038101546001600160401b038082166060880152600160401b820481166080880152600160801b8204811660a0880152600160c01b9091041660c0860152600481015460e08601526005810154610100860152600681015461012086015260070154918216610140850152600160a01b90910460ff1615156101608401529091906143a78286614692565b905060006143b483614717565b90506143bf83614775565b15614413576000871180156143dc57506143d98282615670565b87105b156144065760608601516143f09088614def565b60608701526143ff8288614def565b905061440e565b600060808701525b614451565b61442d8261441f613efa565b6001600160401b0316615670565b606087015190975061443f9088614def565b606087015261444e8288614def565b90505b600061445e848484614747565b60408801519091506144709082614def565b87604001818152505086601560008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160801b0319166001600160801b031916815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010160006101000a8154816001600160801b03021916908360801c0217905550604082015181600201556060820151816003015560808201518160040160006101000a81548160ff0219169083151502179055509050506145598a82614edf565b604080516001600160801b03198b811682526020820184905282516001600160a01b03808f1694928a1693908b16927f5d13067bdc9e4d510839580df1e932220b31fb2bc7790b5bd35aae14f0303bed92918290030190a450505050505050505050565b6000808260c001516001600160401b0316116145f9576145db613efa565b6001600160401b03168260a001516001600160401b0316111561163e565b8160c001516001600160401b03168260a001516001600160401b031611159050919050565b60008261462d5750600061163e565b8282028284828161463a57fe5b041461464557600080fd5b9392505050565b600080821161465a57600080fd5b600082848161466557fe5b04949350505050565b600c805460ff60e01b1916600160e01b179055565b600c805460ff60e01b19169055565b6000614645826060015184606001516001600160401b0316601260008761014001516001600160a01b03166001600160a01b0316815260200190815260200160002060010154116146f05784606001516001600160401b0316612857565b6101408501516001600160a01b031660009081526012602052604090206001015490614def565b6000808260c001516001600160401b03161161473657611cbb82614d90565b5060c001516001600160401b031690565b6000614757846101400151615691565b61476b576147668484846156b0565b611eb6565b5060009392505050565b610160810151600090158061163e575061163e826145bd565b6001600160a01b03821660009081526014602090815260408083206001600160801b0319851684529091528120600701548190600160a01b900460ff166147d457600080fd5b6001600160a01b03841660009081526014602090815260408083206001600160801b0319871684529091529020915061480b613efa565b6003830180546001600160c01b0316600160c01b6001600160401b0393841681029190911791829055604080516101808101825286548152600187015460208201526002870154918101919091528284166060820152600160401b830484166080820152600160801b8304841660a0820152910490911660c0820152600483015460e08201526005830154610100820152600683015461012082015260078301546001600160a01b038116610140830152600160a01b900460ff1615156101608201526148d7906156ef565b60028301819055604080516101808101825284548152600185015460208201529081019190915260038301546001600160401b038082166060840152600160401b820481166080840152600160801b8204811660a0840152600160c01b9091041660c0820152600483015460e08201526005830154610100820152600683015461012082015260078301546001600160a01b038116610140830152600160a01b900460ff16151561016082015261498d90614f9a565b60078301805460ff60a01b1916905560018301549091506149c490859083106149b75760006149bf565b828460010154035b614edf565b6149d2848360020154614edf565b9250929050565b60065483106149e95760006149f0565b6006548390035b6006556007548210614a03576000614a0a565b6007548290035b6007558015614a2e57600a548110614a23576000614a2a565b600a548190035b600a555b613c52615710565b614a3f82615767565b15614a87576000828152601760205260409020548110614a60576000614a73565b6000828152601760205260409020548190035b600083815260176020526040902055611c65565b6000614a91615783565b6001600160401b03166000818152601a60205260409020600201549091508210614abc576000614ad2565b6000818152601a60205260409020600201548290035b6000918252601a6020526040909120600201555050565b614af282615767565b15614b3a576000828152601860205260409020548110614b13576000614b26565b6000828152601860205260409020548190035b600083815260186020526040902055611c65565b6000614b44615783565b6001600160401b03166000818152601b60205260409020600201549091508210614b6f576000614b85565b6000818152601b60205260409020600201548290035b6000918252601b6020526040909120600201555050565b614ba581615795565b158015614bb65750614bb68361550d565b15613c52576001600160a01b0383166000908152601260205260409020548210614be1576000614bfe565b6001600160a01b0383166000908152601260205260409020548290035b6001600160a01b038416600090815260126020526040902055614c20836157b1565b6001600160a01b038416600090815260126020526040902060010155505050565b8015611c65576001600160401b038216600090815260196020526040902054614c6a9082614def565b6001600160401b0383166000908152601960205260409020555050565b600081118015614ca757506041614c9c613efa565b6001600160401b0316115b15614d63576000614cbb86868486886157c9565b600854909150811115614d5d57600854614cdd906064906120a290606e61461e565b8110614cfd57600854614cf8906064906120a290606e61461e565b614cff565b805b90507fb52ab4a425c20017539fcd851fc4ddbb50d17546576353cd51a2d483d80a45b881600660020154614d31613efa565b6040805193845260208401929092526001600160401b031682820152519081900360600190a160088190555b50614d89565b6041614d6d613efa565b6001600160401b03161415614d8957670186cc6acd4b00006008555b5050505050565b60006006600301548260a001516001600160401b031611614dbe578160a001516001600160401b031661163e565b505060095490565b60008160e00151600014614dde578160e0015161163e565b50606001516001600160401b031690565b60008282018381101561464557600080fd5b6000825b82811015614e3f576000818152601a6020526040902060010154670de0b6b3a7640000860281614e3157fe5b049190910190600101614e05565b509392505050565b61016081015160009015614e7c57611cbb614e60613efa565b6001600160401b03168360a001516001600160401b0316615670565b61163e8260c001516001600160401b03168360a001516001600160401b0316615670565b6000614eab8361550d565b614ec557614ec08585846402540be400615826565b614ed6565b614ed685858464028fa6ae00615826565b95945050505050565b6001600160a01b038216614ef257600080fd5b600554614eff9082614def565b6005556001600160a01b038216600090815260208190526040902054614f259082614def565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000816101600151614f9157816040015161163e565b61163e82615848565b6000614fa582615860565b80614fb45750614fb4826145bd565b611cc057611cbb826158bf565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b6020831061503d5780518252601f19909201916020918201910161501e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461509f576040519150601f19603f3d011682016040523d82523d6000602084013e6150a4565b606091505b50915091508180156150d25750805115806150d257508080602001905160208110156150cf57600080fd5b50515b614d8957600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b178152925182516000948594938a169392918291908083835b6020831061515f5780518252601f199092019160209182019101615140565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146151c1576040519150601f19603f3d011682016040523d82523d6000602084013e6151c6565b606091505b50915091508180156151f45750805115806151f457508080602001905160208110156151f157600080fd5b50515b6151fd57600080fd5b505050505050565b6001600160a01b03811660009081526011602052604081205461163e908390600360f81b613033565b6001600160a01b0316600090815260116020526040902080546001019055565b60408051600380825260808201909252606091602082018380368337019050509050828160008151811061527e57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2816001815181106152c057fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081816002815181106152ee57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505092915050565b3b63ffffffff161590565b615327615d13565b6000806153348787613e52565b61533c613f0c565b9050615347876158f5565b6001600160401b0380871660808601819052838216606087015283880190911660a086015260016101608601526020850188905260085491935061538f918891908790614ea0565b835261539961591e565b506020830151600d546153b991670de0b6b3a7640000916120a29161461e565b6101008401526153c88461550d565b1561352a576001600160a01b03841661014084018190526101008401516153ef9190615b0d565b61540386866001600160401b031686615b75565b6101208401529450945094915050565b6001600160a01b03811660009081526010602052604081205461163e908390600160f91b613033565b6001600160a01b0316600090815260106020526040902080546001019055565b6000828152601860205260409020546154759082614def565b6000928352601860205260409092209190915550565b6001600160a01b03166000908152600f6020526040902080546001019055565b6006546154b89084614def565b6006556007546154c89083614def565b6007558015614a2e57600a54614a2a9082614def565b6000828152601760205260409020546154f79082614def565b6000928352601760205260409092209190915550565b6001600160a01b0316151590565b6000620151807f000000000000000000000000000000000000000000000000000000005fa9d80083035b0492915050565b60008282858701612710028161555e57fe5b040195945050505050565b6315dd2ecd9101612710020490565b600081838501612710028161466557fe5b600c54600160e01b900460ff16151560011480156155b95750600c5462019258600160201b90910463ffffffff16105b1561560357600c805463ffffffff1967ffffffff00000000198216600160201b9283900463ffffffff90811660060181169093021790811690821660051901909116179055611cf4565b600c54600160e01b900460ff161580156156295750600c546201925863ffffffff909116105b15611cf457600c805467ffffffff000000001963ffffffff19821663ffffffff928316600601831617908116600160201b9182900483166005190190921602179055611cf4565b6000818311615688576156838284613d6b565b614645565b50600092915050565b6001600160a01b03166000908152601260205260409020600101541590565b6000825b82811015614e3f576000818152601b60205260409020600101548551670de0b6b3a764000002816156e157fe5b0491909101906001016156b4565b600061163e826000015161570284614dc6565b61570b85614d90565b614e01565b600954600754600654600854600a54604080519485526020850193909352838301919091526060830152517fea8ce1d041020595d75f4f48ba3378787b84e61d101465836fa54f1b338a4db59181900360800190a2565b6000615771613efa565b6001600160401b031690911015919050565b6000600161578f613efa565b03905090565b600061579f613efa565b6001600160401b031690911115919050565b60006157bc82615ba6565b611cc057611cbb82615bcd565b6000806157fb846157d98561550d565b6157e8576402540be4006157ef565b64028fa6ae005b64ffffffffff16615c22565b905061581b856120a26305f5e10061581585818d8d614def565b9061461e565b979650505050505050565b6000614ed66402540be4006120a261583e8786615c22565b6158158988615c6c565b600061585382615860565b611cc057611cbb826156ef565b6000808260c001516001600160401b03161161589b5761587e613efa565b6001600160401b031682606001516001600160401b03161161163e565b8160c001516001600160401b031682606001516001600160401b0316119050919050565b60006103e86158cd83615c84565b60016158d885614e47565b0361032002816158e457fe5b046064018360200151028161554557fe5b6001600160a01b0381166000908152600f602052604081205461163e908390600160f81b613033565b6040805163d06ca61f60e01b8152670de0b6b3a76400006004820181815260248301938452600e805460448501819052600095737a250d5630b4cf539739df2c5dacb4c659f2488d9563d06ca61f959492606490910190849080156159ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161598e575b5050935050505060006040518083038186803b1580156159cb57600080fd5b505afa925050508015615a8b57506040513d6000823e601f3d908101601f1916820160405260208110156159fe57600080fd5b8101908080516040519392919084600160201b821115615a1d57600080fd5b908301906020820185811115615a3257600080fd5b82518660208202830111600160201b82111715615a4e57600080fd5b82525081516020918201928201910280838360005b83811015615a7b578181015183820152602001615a63565b5050505090500160405250505060015b615ae757615a97615da9565b80615aa25750615aac565b5050600d54611623565b3d808015615ad6576040519150601f19603f3d011682016040523d82523d6000602084013e615adb565b606091505b50600d54915050611623565b80600281518110615af457fe5b6020026020010151600d81905550600d54915050611623565b6001600160a01b038216600090815260126020526040902054615b309082614def565b6001600160a01b038316600090815260126020526040902055615b52826157b1565b6001600160a01b0390921660009081526012602052604090206001019190915550565b6000615b8082615691565b80615b8c575061016d83105b61476b5761476684846006600201546402540be400615826565b6001600160a01b031660009081526012602052604090205469021e19e0c9bab24000001190565b6001600160a01b038116600090815260126020526040812060010154615c0357615bf5613efa565b6001600160401b031661163e565b506001600160a01b031660009081526012602052604090206001015490565b600081615c4f6107218511615c38576000615c3f565b6107201985015b660150b9a52b11286134c1615cba565b615c63856630aad4df397abe610721615cba565b01019392505050565b6000614645826120a285670de0b6b3a764000061461e565b6000600182608001516001600160401b031611615ca2576001615cab565b60018260800151035b6001600160401b031692915050565b6000611eb66402540be400838611615cdb57615cd6868661461e565b6120a2565b6120a2848661461e565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b60405180610180016040528060008152602001600081526020016000815260200160006001600160401b0316815260200160006001600160401b0316815260200160006001600160401b0316815260200160006001600160401b0316815260200160008152602001600081526020016000815260200160006001600160a01b031681526020016000151581525090565b60e01c90565b600060443d1015615db957611623565b600481823e6308c379a0615dcd8251615da3565b14615dd757611623565b6040513d600319016004823e80513d6001600160401b038160248401118184111715615e065750505050611623565b82840192508251915080821115615e205750505050611623565b503d83016020828401011115615e3857505050611623565b601f01601f191681016020016040529150509056fea264697066735822122077ab368710148891aff560da25363ab814108ed0459319cf37cd25027984ed7964736f6c63430007060033
Verified Source Code Partial Match
Compiler: v0.7.6+commit.7338295f
EVM: istanbul
Optimization: Yes (200 runs)
ERC20.sol 324 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
contract Context {
/**
* @dev returns address executing the method
*/
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
/**
* @dev returns data passed into the method
*/
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
contract ERC20 is Context {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
/**
* @dev initial private
*/
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev 👻 ghost supply - unclaimable
*/
uint256 private _totalSupply = 0.404 ether;
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
constructor (string memory tokenName, string memory tokenSymbol) {
_name = tokenName;
_symbol = tokenSymbol;
_decimals = 18;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the decimals of the token.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
/**
* @dev Returns the total supply of the token.
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Returns the token balance of specific address.
*/
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(
address recipient,
uint256 amount
)
public
returns (bool)
{
_transfer(
_msgSender(),
recipient,
amount
);
return true;
}
/**
* @dev Returns approved balance to be spent by another address
* by using transferFrom method
*/
function allowance(
address owner,
address spender
)
public
view
returns (uint256)
{
return _allowances[owner][spender];
}
/**
* @dev Sets the token allowance to another spender
*/
function approve(
address spender,
uint256 amount
)
public
returns (bool)
{
_approve(
_msgSender(),
spender,
amount
);
return true;
}
/**
* @dev Allows to transfer tokens on senders behalf
* based on allowance approved for the executer
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
)
public
returns (bool)
{
_approve(sender,
_msgSender(), _allowances[sender][_msgSender()].sub(
amount
)
);
_transfer(
sender,
recipient,
amount
);
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* Emits a {Transfer} event.
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
)
internal
virtual
{
require(
sender != address(0x0)
);
require(
recipient != address(0x0)
);
_balances[sender] =
_balances[sender].sub(amount);
_balances[recipient] =
_balances[recipient].add(amount);
emit Transfer(
sender,
recipient,
amount
);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
* Requirements:
*
* - `to` cannot be the zero address.
*/
function _mint(
address account,
uint256 amount
)
internal
virtual
{
require(
account != address(0x0)
);
_totalSupply =
_totalSupply.add(amount);
_balances[account] =
_balances[account].add(amount);
emit Transfer(
address(0x0),
account,
amount
);
}
/**
* @dev Allows to burn tokens if token sender
* wants to reduce totalSupply() of the token
*/
function burn(
uint256 amount
)
external
{
_burn(msg.sender, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(
address account,
uint256 amount
)
internal
virtual
{
require(
account != address(0x0)
);
_balances[account] =
_balances[account].sub(amount);
_totalSupply =
_totalSupply.sub(amount);
emit Transfer(
account,
address(0x0),
amount
);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
)
internal
virtual
{
require(
owner != address(0x0)
);
require(
spender != address(0x0)
);
_allowances[owner][spender] = amount;
emit Approval(
owner,
spender,
amount
);
}
}
import "./SafeMath.sol";
Events.sol 72 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
contract Events {
event StakeStart(
bytes16 indexed stakeID,
address indexed stakerAddress,
address indexed referralAddress,
uint256 stakedAmount,
uint256 stakesShares,
uint256 referralShares,
uint256 startDay,
uint256 lockDays,
uint256 daiEquivalent
);
event StakeEnd(
bytes16 indexed stakeID,
address indexed stakerAddress,
address indexed referralAddress,
uint256 stakedAmount,
uint256 stakesShares,
uint256 referralShares,
uint256 rewardAmount,
uint256 closeDay,
uint256 penaltyAmount
);
event InterestScraped(
bytes16 indexed stakeID,
address indexed stakerAddress,
uint256 scrapeAmount,
uint256 scrapeDay,
uint256 stakersPenalty,
uint256 referrerPenalty,
uint256 currentWiseDay
);
event ReferralCollected(
address indexed staker,
bytes16 indexed stakeID,
address indexed referrer,
bytes16 referrerID,
uint256 rewardAmount
);
event NewGlobals(
uint256 totalShares,
uint256 totalStaked,
uint256 shareRate,
uint256 referrerShares,
uint256 indexed currentWiseDay
);
event NewSharePrice(
uint256 newSharePrice,
uint256 oldSharePrice,
uint64 currentWiseDay
);
event UniswapReserves(
uint112 reserveA,
uint112 reserveB,
uint32 blockTimestampLast
);
event LiquidityGuardStatus(
bool isActive
);
}
Global.sol 86 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./ERC20.sol";
import "./Events.sol";
abstract contract Global is ERC20, Events {
using SafeMath for uint256;
struct Globals {
uint256 totalStaked;
uint256 totalShares;
uint256 sharePrice;
uint256 currentWiseDay;
uint256 referralShares;
uint256 liquidityShares;
}
Globals public globals;
constructor() {
globals.sharePrice = 100E15;
}
function _increaseGlobals(
uint256 _staked,
uint256 _shares,
uint256 _rshares
)
internal
{
globals.totalStaked =
globals.totalStaked.add(_staked);
globals.totalShares =
globals.totalShares.add(_shares);
if (_rshares > 0) {
globals.referralShares =
globals.referralShares.add(_rshares);
}
_logGlobals();
}
function _decreaseGlobals(
uint256 _staked,
uint256 _shares,
uint256 _rshares
)
internal
{
globals.totalStaked =
globals.totalStaked > _staked ?
globals.totalStaked - _staked : 0;
globals.totalShares =
globals.totalShares > _shares ?
globals.totalShares - _shares : 0;
if (_rshares > 0) {
globals.referralShares =
globals.referralShares > _rshares ?
globals.referralShares - _rshares : 0;
}
_logGlobals();
}
function _logGlobals()
private
{
emit NewGlobals(
globals.totalShares,
globals.totalStaked,
globals.sharePrice,
globals.referralShares,
globals.currentWiseDay
);
}
}
Helper.sol 240 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./Timing.sol";
abstract contract Helper is Timing {
using SafeMath for uint256;
function notContract(address _addr) internal view returns (bool) {
uint32 size;
assembly {
size := extcodesize(_addr)
}
return (size == 0);
}
function toBytes16(uint256 x) internal pure returns (bytes16 b) {
return bytes16(bytes32(x));
}
function generateID(address x, uint256 y, bytes1 z) public pure returns (bytes16 b) {
b = toBytes16(
uint256(
keccak256(
abi.encodePacked(x, y, z)
)
)
);
}
function generateStakeID(address _staker) internal view returns (bytes16 stakeID) {
return generateID(_staker, stakeCount[_staker], 0x01);
}
function generateReferralID(address _referrer) internal view returns (bytes16 referralID) {
return generateID(_referrer, referralCount[_referrer], 0x02);
}
function generateLiquidityStakeID(address _staker) internal view returns (bytes16 liquidityStakeID) {
return generateID(_staker, liquidityStakeCount[_staker], 0x03);
}
function stakesPagination(
address _staker,
uint256 _offset,
uint256 _length
)
external
view
returns (bytes16[] memory _stakes)
{
uint256 start = _offset > 0 &&
stakeCount[_staker] > _offset ?
stakeCount[_staker] - _offset : stakeCount[_staker];
uint256 finish = _length > 0 &&
start > _length ?
start - _length : 0;
uint256 i;
_stakes = new bytes16[](start - finish);
for (uint256 _stakeIndex = start; _stakeIndex > finish; _stakeIndex--) {
bytes16 _stakeID = generateID(_staker, _stakeIndex - 1, 0x01);
if (stakes[_staker][_stakeID].stakedAmount > 0) {
_stakes[i] = _stakeID; i++;
}
}
}
function referralsPagination(
address _referrer,
uint256 _offset,
uint256 _length
)
external
view
returns (bytes16[] memory _referrals)
{
uint256 start = _offset > 0 &&
referralCount[_referrer] > _offset ?
referralCount[_referrer] - _offset : referralCount[_referrer];
uint256 finish = _length > 0 &&
start > _length ?
start - _length : 0;
uint256 i;
_referrals = new bytes16[](start - finish);
for (uint256 _rIndex = start; _rIndex > finish; _rIndex--) {
bytes16 _rID = generateID(_referrer, _rIndex - 1, 0x02);
if (_nonZeroAddress(referrerLinks[_referrer][_rID].staker)) {
_referrals[i] = _rID; i++;
}
}
}
function latestStakeID(address _staker) external view returns (bytes16) {
return stakeCount[_staker] == 0 ? bytes16(0) : generateID(_staker, stakeCount[_staker].sub(1), 0x01);
}
function latestReferralID(address _referrer) external view returns (bytes16) {
return referralCount[_referrer] == 0 ? bytes16(0) : generateID(_referrer, referralCount[_referrer].sub(1), 0x02);
}
function latestLiquidityStakeID(address _staker) external view returns (bytes16) {
return liquidityStakeCount[_staker] == 0 ? bytes16(0) : generateID(_staker, liquidityStakeCount[_staker].sub(1), 0x03);
}
function _increaseStakeCount(address _staker) internal {
stakeCount[_staker] = stakeCount[_staker] + 1;
}
function _increaseReferralCount(address _referrer) internal {
referralCount[_referrer] = referralCount[_referrer] + 1;
}
function _increaseLiquidityStakeCount(address _staker) internal {
liquidityStakeCount[_staker] = liquidityStakeCount[_staker] + 1;
}
function _isMatureStake(Stake memory _stake) internal view returns (bool) {
return _stake.closeDay > 0
? _stake.finalDay <= _stake.closeDay
: _stake.finalDay <= _currentWiseDay();
}
function _notCriticalMassReferrer(address _referrer) internal view returns (bool) {
return criticalMass[_referrer].activationDay == 0;
}
function _stakeNotStarted(Stake memory _stake) internal view returns (bool) {
return _stake.closeDay > 0
? _stake.startDay > _stake.closeDay
: _stake.startDay > _currentWiseDay();
}
function _stakeEnded(Stake memory _stake) internal view returns (bool) {
return _stake.isActive == false || _isMatureStake(_stake);
}
function _daysLeft(Stake memory _stake) internal view returns (uint256) {
return _stake.isActive == false
? _daysDiff(_stake.closeDay, _stake.finalDay)
: _daysDiff(_currentWiseDay(), _stake.finalDay);
}
function _daysDiff(uint256 _startDate, uint256 _endDate) internal pure returns (uint256) {
return _startDate > _endDate ? 0 : _endDate.sub(_startDate);
}
function _calculationDay(Stake memory _stake) internal view returns (uint256) {
return _stake.finalDay > globals.currentWiseDay ? globals.currentWiseDay : _stake.finalDay;
}
function _startingDay(Stake memory _stake) internal pure returns (uint256) {
return _stake.scrapeDay == 0 ? _stake.startDay : _stake.scrapeDay;
}
function _notFuture(uint256 _day) internal view returns (bool) {
return _day <= _currentWiseDay();
}
function _notPast(uint256 _day) internal view returns (bool) {
return _day >= _currentWiseDay();
}
function _nonZeroAddress(address _address) internal pure returns (bool) {
return _address != address(0x0);
}
function _getLockDays(Stake memory _stake) internal pure returns (uint256) {
return
_stake.lockDays > 1 ?
_stake.lockDays - 1 : 1;
}
function _preparePath(
address _tokenAddress,
address _wiseAddress
)
internal
pure
returns (address[] memory _path)
{
_path = new address[](3);
_path[0] = _tokenAddress;
_path[1] = WETH;
_path[2] = _wiseAddress;
}
function safeTransfer(
address token,
address to,
uint256 value
)
internal
{
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
0xa9059cbb,
to,
value
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool)))
// 'WISE: transfer failed'
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint value
)
internal
{
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
0x23b872dd,
from,
to,
value
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool)))
// 'WISE: transferFrom failed'
);
}
}
Timing.sol 32 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./Declaration.sol";
abstract contract Timing is Declaration {
function currentWiseDay() public view returns (uint64) {
return _getNow() >= LAUNCH_TIME ? _currentWiseDay() : 0;
}
function _currentWiseDay() internal view returns (uint64) {
return _wiseDayFromStamp(_getNow());
}
function _nextWiseDay() internal view returns (uint64) {
return _currentWiseDay() + 1;
}
function _previousWiseDay() internal view returns (uint64) {
return _currentWiseDay() - 1;
}
function _wiseDayFromStamp(uint256 _timestamp) internal view returns (uint64) {
return uint64((_timestamp - LAUNCH_TIME) / SECONDS_IN_DAY);
}
function _getNow() internal view returns (uint256) {
return block.timestamp;
}
}
SafeMath.sol 40 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
Snapshot.sol 255 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./Helper.sol";
abstract contract Snapshot is Helper {
using SafeMath for uint;
// regular shares
struct SnapShot {
uint256 totalShares;
uint256 inflationAmount;
uint256 scheduledToEnd;
}
// referral shares
struct rSnapShot {
uint256 totalShares;
uint256 inflationAmount;
uint256 scheduledToEnd;
}
// liquidity shares
struct lSnapShot {
uint256 totalShares;
uint256 inflationAmount;
}
mapping(uint256 => SnapShot) public snapshots;
mapping(uint256 => rSnapShot) public rsnapshots;
mapping(uint256 => lSnapShot) public lsnapshots;
modifier snapshotTrigger() {
_dailySnapshotPoint(_currentWiseDay());
_;
}
/**
* @notice allows to activate/deactivate
* liquidity guard manually based on the
* liquidity in UNISWAP pair contract
*/
function liquidityGuardTrigger() public {
(
uint112 reserveA,
uint112 reserveB,
uint32 blockTimestampLast
) = UNISWAP_PAIR.getReserves();
emit UniswapReserves(
reserveA,
reserveB,
blockTimestampLast
);
uint256 onUniswap = UNISWAP_PAIR.token1() == WETH
? reserveA
: reserveB;
uint256 ratio = totalSupply() == 0
? 0
: onUniswap
.mul(200)
.div(totalSupply());
if (ratio < 40 && isLiquidityGuardActive == false) enableLiquidityGuard();
if (ratio > 60 && isLiquidityGuardActive == true) disableLiquidityGuard();
emit LiquidityGuardStatus(
isLiquidityGuardActive
);
}
function enableLiquidityGuard() private {
isLiquidityGuardActive = true;
}
function disableLiquidityGuard() private {
isLiquidityGuardActive = false;
}
/**
* @notice allows volunteer to offload snapshots
* to save on gas during next start/end stake
*/
function manualDailySnapshot()
external
{
_dailySnapshotPoint(_currentWiseDay());
}
/**
* @notice allows volunteer to offload snapshots
* to save on gas during next start/end stake
* in case manualDailySnapshot reach block limit
*/
function manualDailySnapshotPoint(
uint64 _updateDay
)
external
{
require(
_updateDay > 0 &&
_updateDay < _currentWiseDay()
// 'WISE: snapshot day does not exist yet'
);
require(
_updateDay > globals.currentWiseDay
// 'WISE: snapshot already taken for that day'
);
_dailySnapshotPoint(_updateDay);
}
/**
* @notice internal function that offloads
* global values to daily snapshots
* updates globals.currentWiseDay
*/
function _dailySnapshotPoint(
uint64 _updateDay
)
private
{
liquidityGuardTrigger();
uint256 scheduledToEndToday;
uint256 totalStakedToday = globals.totalStaked;
for (uint256 _day = globals.currentWiseDay; _day < _updateDay; _day++) {
// ------------------------------------
// prepare snapshot for regular shares
// reusing scheduledToEndToday variable
scheduledToEndToday = scheduledToEnd[_day] + snapshots[_day - 1].scheduledToEnd;
SnapShot memory snapshot = snapshots[_day];
snapshot.scheduledToEnd = scheduledToEndToday;
snapshot.totalShares =
globals.totalShares > scheduledToEndToday ?
globals.totalShares - scheduledToEndToday : 0;
snapshot.inflationAmount = snapshot.totalShares
.mul(PRECISION_RATE)
.div(
_inflationAmount(
totalStakedToday,
totalSupply(),
totalPenalties[_day],
LIQUIDITY_GUARD.getInflation(
INFLATION_RATE
)
)
);
// store regular snapshot
snapshots[_day] = snapshot;
// ------------------------------------
// prepare snapshot for referrer shares
// reusing scheduledToEndToday variable
scheduledToEndToday = referralSharesToEnd[_day] + rsnapshots[_day - 1].scheduledToEnd;
rSnapShot memory rsnapshot = rsnapshots[_day];
rsnapshot.scheduledToEnd = scheduledToEndToday;
rsnapshot.totalShares =
globals.referralShares > scheduledToEndToday ?
globals.referralShares - scheduledToEndToday : 0;
rsnapshot.inflationAmount = rsnapshot.totalShares
.mul(PRECISION_RATE)
.div(
_referralInflation(
totalStakedToday,
totalSupply()
)
);
// store referral snapshot
rsnapshots[_day] = rsnapshot;
// ------------------------------------
// prepare snapshot for liquidity shares
// reusing scheduledToEndToday variable
lSnapShot memory lsnapshot = lsnapshots[_day];
lsnapshot.totalShares = globals.liquidityShares;
lsnapshot.inflationAmount = lsnapshot.totalShares
.mul(PRECISION_RATE).div(
_liquidityInflation(
totalStakedToday,
totalSupply(),
LIQUIDITY_GUARD.getInflation(
LIQUIDITY_RATE
)
)
);
// store liquidity snapshot
lsnapshots[_day] = lsnapshot;
adjustLiquidityRates();
globals.currentWiseDay++;
}
}
/**
* @notice moves inflation up and down by 0.006%
* from regular shares to liquidity shares
* if the liquidityGuard is active (visa-versa)
*/
function adjustLiquidityRates() private {
if (
isLiquidityGuardActive == true &&
LIQUIDITY_RATE < INFLATION_RATE_MAX
)
{
LIQUIDITY_RATE = LIQUIDITY_RATE + 6;
INFLATION_RATE = INFLATION_RATE - 6;
return;
}
if (
isLiquidityGuardActive == false &&
INFLATION_RATE < INFLATION_RATE_MAX
)
{
INFLATION_RATE = INFLATION_RATE + 6;
LIQUIDITY_RATE = LIQUIDITY_RATE - 6;
return;
}
}
function _inflationAmount(uint256 _totalStaked, uint256 _totalSupply, uint256 _totalPenalties, uint256 _INFLATION_RATE) private pure returns (uint256) {
return (_totalStaked + _totalSupply) * 10000 / _INFLATION_RATE + _totalPenalties;
}
function _referralInflation(uint256 _totalStaked, uint256 _totalSupply) private pure returns (uint256) {
return (_totalStaked + _totalSupply) * 10000 / REFERRALS_RATE;
}
function _liquidityInflation(uint256 _totalStaked, uint256 _totalSupply, uint256 _LIQUIDITY_RATE) private pure returns (uint256) {
return (_totalStaked + _totalSupply) * 10000 / _LIQUIDITY_RATE;
}
}
WiseToken.sol 168 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./LiquidityToken.sol";
contract WiseToken is LiquidityToken {
address public LIQUIDITY_TRANSFORMER;
address public transformerGateKeeper;
constructor() ERC20("Wise Token", "WISE") {
transformerGateKeeper = msg.sender;
}
receive() external payable {
revert();
}
/**
* @notice ability to define liquidity transformer contract
* @dev this method renounce transformerGateKeeper access
* @param _immutableTransformer contract address
*/
function setLiquidityTransfomer(
address _immutableTransformer
)
external
{
require(
transformerGateKeeper == msg.sender
// 'WISE: transformer defined'
);
LIQUIDITY_TRANSFORMER = _immutableTransformer;
transformerGateKeeper = address(0x0);
}
/**
* @notice allows liquidityTransformer to mint supply
* @dev executed from liquidityTransformer upon UNISWAP transfer
* and during reservation payout to contributors and referrers
* @param _investorAddress address for minting WISE tokens
* @param _amount of tokens to mint for _investorAddress
*/
function mintSupply(
address _investorAddress,
uint256 _amount
)
external
{
require(
msg.sender == LIQUIDITY_TRANSFORMER
// 'WISE: wrong transformer'
);
_mint(
_investorAddress,
_amount
);
}
/**
* @notice allows to grant permission to CM referrer status
* @dev called from liquidityTransformer if user referred 50 ETH
* @param _referrer - address that becomes a CM reffer
*/
function giveStatus(
address _referrer
)
external
{
require(
msg.sender == LIQUIDITY_TRANSFORMER
// 'WISE: wrong transformer'
);
criticalMass[_referrer].totalAmount = THRESHOLD_LIMIT;
criticalMass[_referrer].activationDay = _nextWiseDay();
}
/**
* @notice allows to create stake directly with ETH
* if you don't have WISE tokens method will convert
* and use amount returned from UNISWAP to open a stake
* @param _lockDays amount of days it is locked for.
* @param _referrer referrer address for +10% bonus
*/
function createStakeWithETH(
uint64 _lockDays,
address _referrer
)
external
payable
returns (bytes16, uint256, bytes16 referralID)
{
address[] memory path = new address[](2);
path[0] = WETH;
path[1] = address(this);
uint256[] memory amounts =
UNISWAP_ROUTER.swapExactETHForTokens{value: msg.value}(
1,
path,
msg.sender,
block.timestamp + 2 hours
);
return createStake(
amounts[1],
_lockDays,
_referrer
);
}
/**
* @notice allows to create stake with another token
* if you don't have WISE tokens method will convert
* and use amount returned from UNISWAP to open a stake
* @dev the token must have WETH pair on UNISWAP
* @param _tokenAddress any ERC20 token address
* @param _tokenAmount amount to be converted to WISE
* @param _lockDays amount of days it is locked for.
* @param _referrer referrer address for +10% bonus
*/
function createStakeWithToken(
address _tokenAddress,
uint256 _tokenAmount,
uint64 _lockDays,
address _referrer
)
external
returns (bytes16, uint256, bytes16 referralID)
{
ERC20TokenI token = ERC20TokenI(
_tokenAddress
);
token.transferFrom(
msg.sender,
address(this),
_tokenAmount
);
token.approve(
address(UNISWAP_ROUTER),
_tokenAmount
);
address[] memory path = _preparePath(
_tokenAddress,
address(this)
);
uint256[] memory amounts =
UNISWAP_ROUTER.swapExactTokensForTokens(
_tokenAmount,
1,
path,
msg.sender,
block.timestamp + 2 hours
);
return createStake(
amounts[2],
_lockDays,
_referrer
);
}
}
Declaration.sol 190 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./Global.sol";
interface IUniswapV2Factory {
function createPair(
address tokenA,
address tokenB
) external returns (
address pair
);
}
interface IUniswapRouterV2 {
function getAmountsOut(
uint amountIn,
address[] calldata path
) external view returns (
uint[] memory amounts
);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (
uint[] memory amounts
);
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (
uint[] memory amounts
);
}
interface IUniswapV2Pair {
function getReserves() external view returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);
function token1() external view returns (address);
}
interface ILiquidityGuard {
function getInflation(uint32 _amount) external view returns (uint256);
}
interface ERC20TokenI {
function transferFrom(
address _from,
address _to,
uint256 _value
) external returns (
bool success
);
function approve(
address _spender,
uint256 _value
) external returns (
bool success
);
}
abstract contract Declaration is Global {
uint256 constant _decimals = 18;
uint256 constant YODAS_PER_WISE = 10 ** _decimals;
uint32 constant SECONDS_IN_DAY = 86400 seconds;
uint16 constant MIN_LOCK_DAYS = 1;
uint16 constant FORMULA_DAY = 65;
uint16 constant MAX_LOCK_DAYS = 15330; // 42 years
uint16 constant MAX_BONUS_DAYS_A = 1825; // 5 years
uint16 constant MAX_BONUS_DAYS_B = 13505; // 37 years
uint16 constant MIN_REFERRAL_DAYS = 365;
uint32 constant MIN_STAKE_AMOUNT = 1000000;
uint32 constant REFERRALS_RATE = 366816973; // 1.000% (direct value, can be used right away)
uint32 constant INFLATION_RATE_MAX = 103000; // 3.000% (indirect -> checks throgh LiquidityGuard)
uint32 public INFLATION_RATE = 103000; // 3.000% (indirect -> checks throgh LiquidityGuard)
uint32 public LIQUIDITY_RATE = 100006; // 0.006% (indirect -> checks throgh LiquidityGuard)
uint64 constant PRECISION_RATE = 1E18;
uint96 constant THRESHOLD_LIMIT = 10000E18; // $10,000 DAI
uint96 constant DAILY_BONUS_A = 13698630136986302; // 25%:1825 = 0.01369863013 per day;
uint96 constant DAILY_BONUS_B = 370233246945576; // 5%:13505 = 0.00037023324 per day;
uint256 immutable LAUNCH_TIME;
address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
IUniswapRouterV2 public constant UNISWAP_ROUTER = IUniswapRouterV2(
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
);
IUniswapV2Factory public constant UNISWAP_FACTORY = IUniswapV2Factory(
0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
);
ILiquidityGuard public constant LIQUIDITY_GUARD = ILiquidityGuard(
0x9C306CaD86550EC80D77668c0A8bEE6eB34684B6
);
IUniswapV2Pair public UNISWAP_PAIR;
bool public isLiquidityGuardActive;
uint256 public latestDaiEquivalent;
address[] internal _path = [address(this), WETH, DAI];
constructor() {
LAUNCH_TIME = 1604966400; // (10th November 2020 @00:00 GMT == day 0)
}
function createPair() external {
UNISWAP_PAIR = IUniswapV2Pair(
UNISWAP_FACTORY.createPair(
WETH, address(this)
)
);
}
struct Stake {
uint256 stakesShares;
uint256 stakedAmount;
uint256 rewardAmount;
uint64 startDay;
uint64 lockDays;
uint64 finalDay;
uint64 closeDay;
uint256 scrapeDay;
uint256 daiEquivalent;
uint256 referrerShares;
address referrer;
bool isActive;
}
struct ReferrerLink {
address staker;
bytes16 stakeID;
uint256 rewardAmount;
uint256 processedDays;
bool isActive;
}
struct LiquidityStake {
uint256 stakedAmount;
uint256 rewardAmount;
uint64 startDay;
uint64 closeDay;
bool isActive;
}
struct CriticalMass {
uint256 totalAmount;
uint256 activationDay;
}
mapping(address => uint256) public stakeCount;
mapping(address => uint256) public referralCount;
mapping(address => uint256) public liquidityStakeCount;
mapping(address => CriticalMass) public criticalMass;
mapping(address => mapping(bytes16 => uint256)) public scrapes;
mapping(address => mapping(bytes16 => Stake)) public stakes;
mapping(address => mapping(bytes16 => ReferrerLink)) public referrerLinks;
mapping(address => mapping(bytes16 => LiquidityStake)) public liquidityStakes;
mapping(uint256 => uint256) public scheduledToEnd;
mapping(uint256 => uint256) public referralSharesToEnd;
mapping(uint256 => uint256) public totalPenalties;
}
StakingToken.sol 724 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./ReferralToken.sol";
abstract contract StakingToken is ReferralToken {
using SafeMath for uint256;
/**
* @notice A method for a staker to create multiple stakes
* @param _stakedAmount amount of WISE staked.
* @param _lockDays amount of days it is locked for.
* @param _referrer address of the referrer
*/
function createStakeBulk(
uint256[] memory _stakedAmount,
uint64[] memory _lockDays,
address[] memory _referrer
)
external
{
for(uint256 i = 0; i < _stakedAmount.length; i++) {
createStake(
_stakedAmount[i],
_lockDays[i],
_referrer[i]
);
}
}
/**
* @notice A method for a staker to create a stake
* @param _stakedAmount amount of WISE staked.
* @param _lockDays amount of days it is locked for.
* @param _referrer address of the referrer
*/
function createStake(
uint256 _stakedAmount,
uint64 _lockDays,
address _referrer
)
snapshotTrigger
public
returns (bytes16, uint256, bytes16 referralID)
{
require(
msg.sender != _referrer &&
notContract(_referrer)
// 'WISE: invalid referrer'
);
require(
_lockDays >= MIN_LOCK_DAYS &&
_lockDays <= MAX_LOCK_DAYS
// 'WISE: stake is not in range'
);
require(
_stakedAmount >= MIN_STAKE_AMOUNT
// 'WISE: stake is not large enough'
);
(
Stake memory newStake,
bytes16 stakeID,
uint256 _startDay
) =
_createStake(msg.sender, _stakedAmount, _lockDays, _referrer);
if (newStake.referrerShares > 0) {
ReferrerLink memory referrerLink;
referrerLink.staker = msg.sender;
referrerLink.stakeID = stakeID;
referrerLink.isActive = true;
referralID = generateReferralID(_referrer);
referrerLinks[_referrer][referralID] = referrerLink;
_increaseReferralCount(
_referrer
);
_addReferrerSharesToEnd(
newStake.finalDay,
newStake.referrerShares
);
}
stakes[msg.sender][stakeID] = newStake;
_increaseStakeCount(
msg.sender
);
_increaseGlobals(
newStake.stakedAmount,
newStake.stakesShares,
newStake.referrerShares
);
_addScheduledShares(
newStake.finalDay,
newStake.stakesShares
);
emit StakeStart(
stakeID,
msg.sender,
_referrer,
newStake.stakedAmount,
newStake.stakesShares,
newStake.referrerShares,
newStake.startDay,
newStake.lockDays,
newStake.daiEquivalent
);
return (stakeID, _startDay, referralID);
}
/**
* @notice A method for a staker to start a stake
* @param _staker ...
* @param _stakedAmount ...
* @param _lockDays ...
*/
function _createStake(
address _staker,
uint256 _stakedAmount,
uint64 _lockDays,
address _referrer
)
private
returns (
Stake memory _newStake,
bytes16 _stakeID,
uint64 _startDay
)
{
_burn(
_staker,
_stakedAmount
);
_startDay = _nextWiseDay();
_stakeID = generateStakeID(_staker);
_newStake.lockDays = _lockDays;
_newStake.startDay = _startDay;
_newStake.finalDay = _startDay + _lockDays;
_newStake.isActive = true;
_newStake.stakedAmount = _stakedAmount;
_newStake.stakesShares = _stakesShares(
_stakedAmount,
_lockDays,
_referrer,
globals.sharePrice
);
_updateDaiEquivalent();
_newStake.daiEquivalent = latestDaiEquivalent
.mul(_newStake.stakedAmount)
.div(YODAS_PER_WISE);
if (_nonZeroAddress(_referrer)) {
_newStake.referrer = _referrer;
_addCriticalMass(
_newStake.referrer,
_newStake.daiEquivalent
);
_newStake.referrerShares = _referrerShares(
_stakedAmount,
_lockDays,
_referrer
);
}
}
/**
* @notice A method for a staker to remove a stake
* belonging to his address by providing ID of a stake.
* @param _stakeID unique bytes sequence reference to the stake
*/
function endStake(
bytes16 _stakeID
)
snapshotTrigger
external
returns (uint256)
{
(
Stake memory endedStake,
uint256 penaltyAmount
) =
_endStake(
msg.sender,
_stakeID
);
_decreaseGlobals(
endedStake.stakedAmount,
endedStake.stakesShares,
endedStake.referrerShares
);
_removeScheduledShares(
endedStake.finalDay,
endedStake.stakesShares
);
_removeReferrerSharesToEnd(
endedStake.finalDay,
endedStake.referrerShares
);
_removeCriticalMass(
endedStake.referrer,
endedStake.daiEquivalent,
endedStake.startDay
);
_storePenalty(
endedStake.closeDay,
penaltyAmount
);
_sharePriceUpdate(
endedStake.stakedAmount > penaltyAmount ?
endedStake.stakedAmount - penaltyAmount : 0,
endedStake.rewardAmount + scrapes[msg.sender][_stakeID],
endedStake.referrer,
endedStake.lockDays,
endedStake.stakesShares
);
emit StakeEnd(
_stakeID,
msg.sender,
endedStake.referrer,
endedStake.stakedAmount,
endedStake.stakesShares,
endedStake.referrerShares,
endedStake.rewardAmount,
endedStake.closeDay,
penaltyAmount
);
return endedStake.rewardAmount;
}
function _endStake(
address _staker,
bytes16 _stakeID
)
private
returns (
Stake storage _stake,
uint256 _penalty
)
{
require(
stakes[_staker][_stakeID].isActive
// 'WISE: not an active stake'
);
_stake = stakes[_staker][_stakeID];
_stake.closeDay = _currentWiseDay();
_stake.rewardAmount = _calculateRewardAmount(_stake);
_penalty = _calculatePenaltyAmount(_stake);
_stake.isActive = false;
_mint(
_staker,
_stake.stakedAmount > _penalty ?
_stake.stakedAmount - _penalty : 0
);
_mint(
_staker,
_stake.rewardAmount
);
}
/**
* @notice alloes to scrape interest from active stake
* @param _stakeID unique bytes sequence reference to the stake
* @param _scrapeDays amount of days to proccess, 0 = all
*/
function scrapeInterest(
bytes16 _stakeID,
uint64 _scrapeDays
)
external
snapshotTrigger
returns (
uint256 scrapeDay,
uint256 scrapeAmount,
uint256 remainingDays,
uint256 stakersPenalty,
uint256 referrerPenalty
)
{
require(
stakes[msg.sender][_stakeID].isActive
// 'WISE: not an active stake'
);
Stake memory stake = stakes[msg.sender][_stakeID];
scrapeDay = _scrapeDays > 0
? _startingDay(stake).add(_scrapeDays)
: _calculationDay(stake);
scrapeDay = scrapeDay > stake.finalDay
? _calculationDay(stake)
: scrapeDay;
scrapeAmount = _loopRewardAmount(
stake.stakesShares,
_startingDay(stake),
scrapeDay
);
if (_isMatureStake(stake) == false) {
remainingDays = _daysLeft(stake);
stakersPenalty = _stakesShares(
scrapeAmount,
remainingDays,
msg.sender,
globals.sharePrice
);
stake.stakesShares =
stake.stakesShares.sub(stakersPenalty);
_removeScheduledShares(
stake.finalDay,
stakersPenalty
);
if (stake.referrerShares > 0) {
referrerPenalty = _stakesShares(
scrapeAmount,
remainingDays,
address(0x0),
globals.sharePrice
);
stake.referrerShares =
stake.referrerShares.sub(referrerPenalty);
_removeReferrerSharesToEnd(
stake.finalDay,
referrerPenalty
);
}
_decreaseGlobals(
0,
stakersPenalty,
referrerPenalty
);
_sharePriceUpdate(
stake.stakedAmount,
scrapeAmount,
stake.referrer,
stake.lockDays,
stake.stakesShares
);
}
else {
scrapes[msg.sender][_stakeID] =
scrapes[msg.sender][_stakeID].add(scrapeAmount);
_sharePriceUpdate(
stake.stakedAmount,
scrapes[msg.sender][_stakeID],
stake.referrer,
stake.lockDays,
stake.stakesShares
);
}
stake.scrapeDay = scrapeDay;
stakes[msg.sender][_stakeID] = stake;
_mint(
msg.sender,
scrapeAmount
);
emit InterestScraped(
_stakeID,
msg.sender,
scrapeAmount,
scrapeDay,
stakersPenalty,
referrerPenalty,
_currentWiseDay()
);
}
function _addScheduledShares(
uint256 _finalDay,
uint256 _shares
)
internal
{
scheduledToEnd[_finalDay] =
scheduledToEnd[_finalDay].add(_shares);
}
function _removeScheduledShares(
uint256 _finalDay,
uint256 _shares
)
internal
{
if (_notPast(_finalDay)) {
scheduledToEnd[_finalDay] =
scheduledToEnd[_finalDay] > _shares ?
scheduledToEnd[_finalDay] - _shares : 0;
} else {
uint256 _day = _previousWiseDay();
snapshots[_day].scheduledToEnd =
snapshots[_day].scheduledToEnd > _shares ?
snapshots[_day].scheduledToEnd - _shares : 0;
}
}
function _sharePriceUpdate(
uint256 _stakedAmount,
uint256 _rewardAmount,
address _referrer,
uint256 _lockDays,
uint256 _stakeShares
)
private
{
if (_stakeShares > 0 && _currentWiseDay() > FORMULA_DAY) {
uint256 newSharePrice = _getNewSharePrice(
_stakedAmount,
_rewardAmount,
_stakeShares,
_lockDays,
_referrer
);
if (newSharePrice > globals.sharePrice) {
newSharePrice =
newSharePrice < globals.sharePrice.mul(110).div(100) ?
newSharePrice : globals.sharePrice.mul(110).div(100);
emit NewSharePrice(
newSharePrice,
globals.sharePrice,
_currentWiseDay()
);
globals.sharePrice = newSharePrice;
}
return;
}
if (_currentWiseDay() == FORMULA_DAY) {
globals.sharePrice = 110E15;
}
}
function _getNewSharePrice(
uint256 _stakedAmount,
uint256 _rewardAmount,
uint256 _stakeShares,
uint256 _lockDays,
address _referrer
)
private
pure
returns (uint256)
{
uint256 _bonusAmount = _getBonus(
_lockDays, _nonZeroAddress(_referrer) ? 11E9 : 10E9
);
return
_stakedAmount
.add(_rewardAmount)
.mul(_bonusAmount)
.mul(1E8)
.div(_stakeShares);
}
function checkMatureStake(
address _staker,
bytes16 _stakeID
)
external
view
returns (bool isMature)
{
Stake memory stake = stakes[_staker][_stakeID];
isMature = _isMatureStake(stake);
}
function checkStakeByID(
address _staker,
bytes16 _stakeID
)
external
view
returns (
uint256 startDay,
uint256 lockDays,
uint256 finalDay,
uint256 closeDay,
uint256 scrapeDay,
uint256 stakedAmount,
uint256 stakesShares,
uint256 rewardAmount,
uint256 penaltyAmount,
bool isActive,
bool isMature
)
{
Stake memory stake = stakes[_staker][_stakeID];
startDay = stake.startDay;
lockDays = stake.lockDays;
finalDay = stake.finalDay;
closeDay = stake.closeDay;
scrapeDay = stake.scrapeDay;
stakedAmount = stake.stakedAmount;
stakesShares = stake.stakesShares;
rewardAmount = _checkRewardAmount(stake);
penaltyAmount = _calculatePenaltyAmount(stake);
isActive = stake.isActive;
isMature = _isMatureStake(stake);
}
function _stakesShares(
uint256 _stakedAmount,
uint256 _lockDays,
address _referrer,
uint256 _sharePrice
)
private
pure
returns (uint256)
{
return _nonZeroAddress(_referrer)
? _sharesAmount(_stakedAmount, _lockDays, _sharePrice, 11E9)
: _sharesAmount(_stakedAmount, _lockDays, _sharePrice, 10E9);
}
function _sharesAmount(
uint256 _stakedAmount,
uint256 _lockDays,
uint256 _sharePrice,
uint256 _extraBonus
)
private
pure
returns (uint256)
{
return _baseAmount(_stakedAmount, _sharePrice)
.mul(_getBonus(_lockDays, _extraBonus))
.div(10E9);
}
function _getBonus(
uint256 _lockDays,
uint256 _extraBonus
)
private
pure
returns (uint256)
{
return
_regularBonus(_lockDays, DAILY_BONUS_A, MAX_BONUS_DAYS_A) +
_regularBonus(
_lockDays > MAX_BONUS_DAYS_A ?
_lockDays - MAX_BONUS_DAYS_A : 0, DAILY_BONUS_B, MAX_BONUS_DAYS_B
) + _extraBonus;
}
function _regularBonus(
uint256 _lockDays,
uint256 _daily,
uint256 _maxDays
)
private
pure
returns (uint256)
{
return (
_lockDays > _maxDays
? _maxDays.mul(_daily)
: _lockDays.mul(_daily)
).div(10E9);
}
function _baseAmount(
uint256 _stakedAmount,
uint256 _sharePrice
)
private
pure
returns (uint256)
{
return
_stakedAmount
.mul(PRECISION_RATE)
.div(_sharePrice);
}
function _referrerShares(
uint256 _stakedAmount,
uint256 _lockDays,
address _referrer
)
private
view
returns (uint256)
{
return
_notCriticalMassReferrer(_referrer) ||
_lockDays < MIN_REFERRAL_DAYS
? 0
: _sharesAmount(
_stakedAmount,
_lockDays,
globals.sharePrice,
10E9
);
}
function _checkRewardAmount(Stake memory _stake) private view returns (uint256) {
return _stake.isActive ? _detectReward(_stake) : _stake.rewardAmount;
}
function _detectReward(Stake memory _stake) private view returns (uint256) {
return _stakeNotStarted(_stake) ? 0 : _calculateRewardAmount(_stake);
}
function _storePenalty(
uint64 _storeDay,
uint256 _penalty
)
private
{
if (_penalty > 0) {
totalPenalties[_storeDay] =
totalPenalties[_storeDay].add(_penalty);
}
}
function _calculatePenaltyAmount(
Stake memory _stake
)
private
view
returns (uint256)
{
return _stakeNotStarted(_stake) || _isMatureStake(_stake) ? 0 : _getPenalties(_stake);
}
function _getPenalties(Stake memory _stake)
private
view
returns (uint256)
{
return _stake.stakedAmount * (100 + (800 * (_daysLeft(_stake) - 1) / (_getLockDays(_stake)))) / 1000;
}
function _calculateRewardAmount(
Stake memory _stake
)
private
view
returns (uint256)
{
return _loopRewardAmount(
_stake.stakesShares,
_startingDay(_stake),
_calculationDay(_stake)
);
}
function _loopRewardAmount(
uint256 _stakeShares,
uint256 _startDay,
uint256 _finalDay
)
private
view
returns (uint256 _rewardAmount)
{
for (uint256 _day = _startDay; _day < _finalDay; _day++) {
_rewardAmount += _stakeShares * PRECISION_RATE / snapshots[_day].inflationAmount;
}
}
}
ReferralToken.sol 291 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./Snapshot.sol";
abstract contract ReferralToken is Snapshot {
using SafeMath for uint256;
function _addReferrerSharesToEnd(
uint256 _finalDay,
uint256 _shares
)
internal
{
referralSharesToEnd[_finalDay] =
referralSharesToEnd[_finalDay].add(_shares);
}
function _removeReferrerSharesToEnd(
uint256 _finalDay,
uint256 _shares
)
internal
{
if (_notPast(_finalDay)) {
referralSharesToEnd[_finalDay] =
referralSharesToEnd[_finalDay] > _shares ?
referralSharesToEnd[_finalDay] - _shares : 0;
} else {
uint256 _day = _previousWiseDay();
rsnapshots[_day].scheduledToEnd =
rsnapshots[_day].scheduledToEnd > _shares ?
rsnapshots[_day].scheduledToEnd - _shares : 0;
}
}
function _belowThresholdLevel(
address _referrer
)
private
view
returns (bool)
{
return criticalMass[_referrer].totalAmount < THRESHOLD_LIMIT;
}
function _addCriticalMass(
address _referrer,
uint256 _daiEquivalent
)
internal
{
criticalMass[_referrer].totalAmount =
criticalMass[_referrer].totalAmount.add(_daiEquivalent);
criticalMass[_referrer].activationDay = _determineActivationDay(_referrer);
}
function _removeCriticalMass(
address _referrer,
uint256 _daiEquivalent,
uint256 _startDay
)
internal
{
if (
_notFuture(_startDay) == false &&
_nonZeroAddress(_referrer)
) {
criticalMass[_referrer].totalAmount =
criticalMass[_referrer].totalAmount > _daiEquivalent ?
criticalMass[_referrer].totalAmount - _daiEquivalent : 0;
criticalMass[_referrer].activationDay = _determineActivationDay(_referrer);
}
}
function _determineActivationDay(
address _referrer
)
private
view
returns (uint256)
{
return _belowThresholdLevel(_referrer) ? 0 : _activationDay(_referrer);
}
function _activationDay(
address _referrer
)
private
view
returns (uint256)
{
return
criticalMass[_referrer].activationDay > 0 ?
criticalMass[_referrer].activationDay : _currentWiseDay();
}
function _updateDaiEquivalent()
internal
returns (uint256)
{
try UNISWAP_ROUTER.getAmountsOut(
YODAS_PER_WISE, _path
) returns (uint256[] memory results) {
latestDaiEquivalent = results[2];
return latestDaiEquivalent;
} catch Error(string memory) {
return latestDaiEquivalent;
} catch (bytes memory) {
return latestDaiEquivalent;
}
}
function referrerInterest(
bytes16 _referralID,
uint256 _scrapeDays
)
external
snapshotTrigger
{
_referrerInterest(
msg.sender,
_referralID,
_scrapeDays
);
}
function referrerInterestBulk(
bytes16[] memory _referralIDs,
uint256[] memory _scrapeDays
)
external
snapshotTrigger
{
for(uint256 i = 0; i < _referralIDs.length; i++) {
_referrerInterest(
msg.sender,
_referralIDs[i],
_scrapeDays[i]
);
}
}
function _referrerInterest(
address _referrer,
bytes16 _referralID,
uint256 _processDays
)
internal
{
ReferrerLink memory link =
referrerLinks[_referrer][_referralID];
require(
link.isActive == true
);
address staker = link.staker;
bytes16 stakeID = link.stakeID;
Stake memory stake = stakes[staker][stakeID];
uint256 startDay = _determineStartDay(stake, link);
uint256 finalDay = _determineFinalDay(stake);
if (_stakeEnded(stake)) {
if (
_processDays > 0 &&
_processDays < _daysDiff(startDay, finalDay)
)
{
link.processedDays =
link.processedDays.add(_processDays);
finalDay =
startDay.add(_processDays);
} else {
link.isActive = false;
}
} else {
_processDays = _daysDiff(startDay, _currentWiseDay());
link.processedDays =
link.processedDays.add(_processDays);
finalDay =
startDay.add(_processDays);
}
uint256 referralInterest = _checkReferralInterest(
stake,
startDay,
finalDay
);
link.rewardAmount =
link.rewardAmount.add(referralInterest);
referrerLinks[_referrer][_referralID] = link;
_mint(
_referrer,
referralInterest
);
emit ReferralCollected(
staker,
stakeID,
_referrer,
_referralID,
referralInterest
);
}
function checkReferralsByID(
address _referrer,
bytes16 _referralID
)
external
view
returns (
address staker,
bytes16 stakeID,
uint256 referrerShares,
uint256 referralInterest,
bool isActiveReferral,
bool isActiveStake,
bool isMatureStake,
bool isEndedStake
)
{
ReferrerLink memory link = referrerLinks[_referrer][_referralID];
staker = link.staker;
stakeID = link.stakeID;
isActiveReferral = link.isActive;
Stake memory stake = stakes[staker][stakeID];
referrerShares = stake.referrerShares;
referralInterest = _checkReferralInterest(
stake,
_determineStartDay(stake, link),
_determineFinalDay(stake)
);
isActiveStake = stake.isActive;
isEndedStake = _stakeEnded(stake);
isMatureStake = _isMatureStake(stake);
}
function _checkReferralInterest(Stake memory _stake, uint256 _startDay, uint256 _finalDay) internal view returns (uint256 _referralInterest) {
return _notCriticalMassReferrer(_stake.referrer) ? 0 : _getReferralInterest(_stake, _startDay, _finalDay);
}
function _getReferralInterest(Stake memory _stake, uint256 _startDay, uint256 _finalDay) private view returns (uint256 _referralInterest) {
for (uint256 _day = _startDay; _day < _finalDay; _day++) {
_referralInterest += _stake.stakesShares * PRECISION_RATE / rsnapshots[_day].inflationAmount;
}
}
function _determineStartDay(Stake memory _stake, ReferrerLink memory _link) internal view returns (uint256) {
return (
criticalMass[_stake.referrer].activationDay > _stake.startDay ?
criticalMass[_stake.referrer].activationDay : _stake.startDay
).add(_link.processedDays);
}
function _determineFinalDay(
Stake memory _stake
)
internal
view
returns (uint256)
{
return
_stake.closeDay > 0 ?
_stake.closeDay : _calculationDay(_stake);
}
}
LiquidityToken.sol 147 lines
// SPDX-License-Identifier: --🦉--
pragma solidity =0.7.6;
import "./StakingToken.sol";
abstract contract LiquidityToken is StakingToken {
using SafeMath for uint;
/**
* @notice A method for a staker to create a liquidity stake
* @param _liquidityTokens amount of UNI-WISE staked.
*/
function createLiquidityStake(
uint256 _liquidityTokens
)
snapshotTrigger
external
returns (bytes16 liquidityStakeID)
{
require(
isLiquidityGuardActive == true
// WISE: LiquidityGuard is not active
);
safeTransferFrom(
address(UNISWAP_PAIR),
msg.sender,
address(this),
_liquidityTokens
);
LiquidityStake memory newLiquidityStake;
liquidityStakeID = generateLiquidityStakeID(
msg.sender
);
newLiquidityStake.startDay = _nextWiseDay();
newLiquidityStake.stakedAmount = _liquidityTokens;
newLiquidityStake.isActive = true;
globals.liquidityShares =
globals.liquidityShares.add(_liquidityTokens);
liquidityStakes[msg.sender][liquidityStakeID] = newLiquidityStake;
_increaseLiquidityStakeCount(
msg.sender
);
}
/**
* @notice A method for a staker to end a liquidity stake
* @param _liquidityStakeID - identification number
*/
function endLiquidityStake(
bytes16 _liquidityStakeID
)
snapshotTrigger
external
returns (uint256)
{
LiquidityStake memory liquidityStake =
liquidityStakes[msg.sender][_liquidityStakeID];
require(
liquidityStake.isActive
// 'WISE: not an active stake'
);
liquidityStake.isActive = false;
liquidityStake.closeDay = _currentWiseDay();
liquidityStake.rewardAmount = _calculateRewardAmount(
liquidityStake
);
_mint(
msg.sender,
liquidityStake.rewardAmount
);
safeTransfer(
address(UNISWAP_PAIR),
msg.sender,
liquidityStake.stakedAmount
);
globals.liquidityShares =
globals.liquidityShares.sub(liquidityStake.stakedAmount);
liquidityStakes[msg.sender][_liquidityStakeID] = liquidityStake;
return liquidityStake.rewardAmount;
}
/**
* @notice returns full view and details of
* a liquidity stake belonging to caller
* @param _liquidityStakeID - stakeID
*/
function checkLiquidityStakeByID(
address _staker,
bytes16 _liquidityStakeID
)
external
view
returns (
uint256 startDay,
uint256 stakedAmount,
uint256 rewardAmount,
uint256 closeDay,
bool isActive
)
{
LiquidityStake memory stake = liquidityStakes[_staker][_liquidityStakeID];
startDay = stake.startDay;
stakedAmount = stake.stakedAmount;
rewardAmount = _calculateRewardAmount(stake);
closeDay = stake.closeDay;
isActive = stake.isActive;
}
/**
* @notice calculates reward when closing liquidity stake
* @param _liquidityStake - stake instance
*/
function _calculateRewardAmount(
LiquidityStake memory _liquidityStake
)
private
view
returns (uint256 _rewardAmount)
{
uint256 maxCalculationDay = _liquidityStake.startDay + MIN_REFERRAL_DAYS;
uint256 calculationDay =
globals.currentWiseDay < maxCalculationDay ?
globals.currentWiseDay : maxCalculationDay;
for (uint256 _day = _liquidityStake.startDay; _day < calculationDay; _day++) {
_rewardAmount += _liquidityStake.stakedAmount * PRECISION_RATE / lsnapshots[_day].inflationAmount;
}
}
}
Read Contract
INFLATION_RATE 0xb381a811 → uint32
LIQUIDITY_GUARD 0xb543c4ba → address
LIQUIDITY_RATE 0x3697e979 → uint32
LIQUIDITY_TRANSFORMER 0x60e4c651 → address
UNISWAP_FACTORY 0xc74c0fac → address
UNISWAP_PAIR 0x6ba631cf → address
UNISWAP_ROUTER 0xd8264920 → address
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
checkLiquidityStakeByID 0x10748592 → uint256, uint256, uint256, uint256, bool
checkMatureStake 0x779e2e18 → bool
checkReferralsByID 0x89201d4e → address, bytes16, uint256, uint256, bool, bool, bool, bool
checkStakeByID 0xa4ed0550 → uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool, bool
criticalMass 0x3b58afe7 → uint256, uint256
currentWiseDay 0x48e4ccab → uint64
decimals 0x313ce567 → uint8
generateID 0xbf58f6d2 → bytes16
globals 0xc3124525 → uint256, uint256, uint256, uint256, uint256, uint256
isLiquidityGuardActive 0x02cbb266 → bool
latestDaiEquivalent 0x005ada7f → uint256
latestLiquidityStakeID 0x75c3fa4f → bytes16
latestReferralID 0x5b202387 → bytes16
latestStakeID 0xae3d1de2 → bytes16
liquidityStakeCount 0x601f37ac → uint256
liquidityStakes 0xdf0618d2 → uint256, uint256, uint64, uint64, bool
lsnapshots 0xe3073bfb → uint256, uint256
name 0x06fdde03 → string
referralCount 0xdb74559b → uint256
referralSharesToEnd 0xbe21ff70 → uint256
referralsPagination 0xe7881cda → bytes16[]
referrerLinks 0xc172628e → address, bytes16, uint256, uint256, bool
rsnapshots 0x8649102b → uint256, uint256, uint256
scheduledToEnd 0xc23d6564 → uint256
scrapes 0x20429fac → uint256
snapshots 0xd6565a2d → uint256, uint256, uint256
stakeCount 0x33060d90 → uint256
stakes 0xe1d033e9 → uint256, uint256, uint256, uint64, uint64, uint64, uint64, uint256, uint256, uint256, address, bool
stakesPagination 0x23672d8a → bytes16[]
symbol 0x95d89b41 → string
totalPenalties 0xbba85e1f → uint256
totalSupply 0x18160ddd → uint256
transformerGateKeeper 0x8a263060 → address
Write Contract 21 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address spender
uint256 amount
returns: bool
burn 0x42966c68
uint256 amount
createLiquidityStake 0xce8f9f00
uint256 _liquidityTokens
returns: bytes16
createPair 0x9e78fb4f
No parameters
createStake 0xdf2d02b1
uint256 _stakedAmount
uint64 _lockDays
address _referrer
returns: bytes16, uint256, bytes16
createStakeBulk 0x763241d3
uint256[] _stakedAmount
uint64[] _lockDays
address[] _referrer
createStakeWithETH 0x1c0b37e1
uint64 _lockDays
address _referrer
returns: bytes16, uint256, bytes16
createStakeWithToken 0xd1cf9098
address _tokenAddress
uint256 _tokenAmount
uint64 _lockDays
address _referrer
returns: bytes16, uint256, bytes16
endLiquidityStake 0xa50af895
bytes16 _liquidityStakeID
returns: uint256
endStake 0x99c2def4
bytes16 _stakeID
returns: uint256
giveStatus 0x4dfc7a03
address _referrer
liquidityGuardTrigger 0x87da6274
No parameters
manualDailySnapshot 0x613fc9fd
No parameters
manualDailySnapshotPoint 0xa91b19f2
uint64 _updateDay
mintSupply 0xe742806a
address _investorAddress
uint256 _amount
referrerInterest 0x4f47b16d
bytes16 _referralID
uint256 _scrapeDays
referrerInterestBulk 0xfc527bf5
bytes16[] _referralIDs
uint256[] _scrapeDays
scrapeInterest 0x9b57ab12
bytes16 _stakeID
uint64 _scrapeDays
returns: uint256, uint256, uint256, uint256, uint256
setLiquidityTransfomer 0xd8d44a29
address _immutableTransformer
transfer 0xa9059cbb
address recipient
uint256 amount
returns: bool
transferFrom 0x23b872dd
address sender
address recipient
uint256 amount
returns: bool
Token Balances (3)
View Transfers →Recent Transactions
No transactions found for this address