Address Contract Partially Verified
Address
0x8532A2eCd64b3006D7Bfbb92F684eE022B1d4d35
Balance
0 ETH
Nonce
1
Code Size
22433 bytes
Creator
0x20dC7DA7...7A87 at tx 0xab59cd96...2854c2
Indexed Transactions
0 (1 on-chain, 1.7% indexed)
Contract Bytecode
22433 bytes
0x608060405234801561001057600080fd5b50600436106102745760003560e01c8063936c347711610151578063cd2ed8fb116100c3578063e4e1e53811610087578063e4e1e538146109f9578063f1b8a9b714610a2b578063f77c479114610a51578063f8b2cb4f14610a59578063f8d6aed414610a7f578063fde924f714610aba57610274565b8063cd2ed8fb14610969578063cf5e7bd314610971578063d4cadf6814610997578063d73dd6231461099f578063dd62ed3e146109cb57610274565b8063b02f0b7311610115578063b02f0b73146107f9578063ba9530a61461086e578063be3bbd2e146108a9578063c1762b1514610901578063c1f1b1b51461093d578063cc77828d1461096157610274565b8063936c34771461078f578063948d8ce61461079757806395d89b41146107bd5780639a86139b146107c5578063a9059cbb146107cd57610274565b80633fdddaa2116101ea57806370a08231116101ae57806370a082311461066c5780638187f516146106925780638a5c57df146106b85780638c28cbe81461073b5780638d4e40831461076157806392eefe9b1461076957610274565b80633fdddaa2146104d457806346ab38f1146105065780634d128b77146105385780635e7d6c3d14610582578063661884631461064057610274565b806318160ddd1161023c57806318160ddd146103d257806323b872dd146103da578063255de7bb146104105780632f37b62414610473578063313ce5671461049957806334e19907146104b757610274565b80630553e1561461027957806306fdde03146102a7578063095ea7b3146103245780631446a7ff1461036457806315e84af9146103a4575b600080fd5b6102a56004803603604081101561028f57600080fd5b506001600160a01b038135169060200135610ac2565b005b6102af610cc9565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102e95781810151838201526020016102d1565b50505050905090810190601f1680156103165780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103506004803603604081101561033a57600080fd5b506001600160a01b038135169060200135610d5f565b604080519115158252519081900360200190f35b6103926004803603604081101561037a57600080fd5b506001600160a01b0381358116916020013516610db4565b60408051918252519081900360200190f35b610392600480360360408110156103ba57600080fd5b506001600160a01b0381358116916020013516610f09565b610392611055565b610350600480360360608110156103f057600080fd5b506001600160a01b0381358116916020810135909116906040013561105b565b61045a600480360360c081101561042657600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359091169060808101359060a00135611318565b6040805192835260208301919091528051918290030190f35b6103506004803603602081101561048957600080fd5b50356001600160a01b03166118a2565b6104a16118c0565b6040805160ff9092168252519081900360200190f35b6102a5600480360360208110156104cd57600080fd5b50356118c9565b6102a5600480360360608110156104ea57600080fd5b506001600160a01b038135169060208101359060400135611ac6565b6103926004803603606081101561051c57600080fd5b506001600160a01b038135169060208101359060400135611e9c565b61045a600480360360c081101561054e57600080fd5b506001600160a01b038135811691602081013582169160408201359160608101359091169060808101359060a0013561218f565b6102a56004803603604081101561059857600080fd5b810190602081018135600160201b8111156105b257600080fd5b8201836020820111156105c457600080fd5b803590602001918460208302840111600160201b831117156105e557600080fd5b919390929091602081019035600160201b81111561060257600080fd5b82018360208201111561061457600080fd5b803590602001918460208302840111600160201b8311171561063557600080fd5b5090925090506126fb565b6103506004803603604081101561065657600080fd5b506001600160a01b03813516906020013561282c565b6103926004803603602081101561068257600080fd5b50356001600160a01b0316612904565b6102a5600480360360208110156106a857600080fd5b50356001600160a01b031661291f565b6102a5600480360360608110156106ce57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156106fd57600080fd5b82018360208201111561070f57600080fd5b803590602001918460208302840111600160201b8311171561073057600080fd5b509092509050612a5d565b6102a56004803603602081101561075157600080fd5b50356001600160a01b0316612d75565b610350612f29565b6102a56004803603602081101561077f57600080fd5b50356001600160a01b0316612f32565b610392613070565b610392600480360360208110156107ad57600080fd5b50356001600160a01b03166130c5565b6102af61318f565b6103926131f0565b610350600480360360408110156107e357600080fd5b506001600160a01b0381351690602001356131fd565b6102a56004803603604081101561080f57600080fd5b81359190810190604081016020820135600160201b81111561083057600080fd5b82018360208201111561084257600080fd5b803590602001918460208302840111600160201b8311171561086357600080fd5b509092509050613375565b610392600480360360c081101561088457600080fd5b5080359060208101359060408101359060608101359060808101359060a0013561367b565b6108b1613701565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108ed5781810151838201526020016108d5565b505050509050019250505060405180910390f35b6103926004803603608081101561091757600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356137f9565b610945613ae7565b604080516001600160a01b039092168252519081900360200190f35b6108b1613b45565b610392613b93565b6102a56004803603602081101561098757600080fd5b50356001600160a01b0316613b99565b610392613ee9565b610350600480360360408110156109b557600080fd5b506001600160a01b038135169060200135613f3e565b610392600480360360408110156109e157600080fd5b506001600160a01b0381358116916020013516613fbf565b6102a560048036036060811015610a0f57600080fd5b506001600160a01b038135169060208101359060400135613fea565b61039260048036036020811015610a4157600080fd5b50356001600160a01b0316614241565b610945614316565b61039260048036036020811015610a6f57600080fd5b50356001600160a01b0316614325565b610392600480360360c0811015610a9557600080fd5b5080359060208101359060408101359060608101359060808101359060a001356143ef565b610350614472565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615610b6e576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600754336001600160a01b0390911614610bd3576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60095460ff1615610c1e576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b600a5460021115610c67576040805162461bcd60e51b815260206004820152600e60248201526d4552525f4d494e5f544f4b454e5360901b604482015290519081900360640190fd5b6009805461ff001960ff199091166001171661010017905560008115610c8d5781610c98565b68056bc75e2d631000005b9050610ca381614480565b610cad838261448c565b610cb96001848361449a565b50506005805461ff001916905550565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610d555780601f10610d2a57610100808354040283529160200191610d55565b820191906000526020600020905b815481529060010190602001808311610d3857829003601f168201915b5050505050905090565b3360008181526001602090815260408083206001600160a01b0387168085529083528184208690558151868152915193949093909260008051602061574d833981519152928290030190a35060015b92915050565b600554600090610100900460ff1615610e02576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b602052604090205460ff16610e5f576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600b602052604090205460ff16610ebc576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600b60205260408082209285168252812060038084015460028086015492840154908401549394610f0094929392906148b4565b95945050505050565b600554600090610100900460ff1615610f57576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b602052604090205460ff16610fb4576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600b602052604090205460ff16611011576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600b6020526040808220928516825290206003808301546002808501549284015490840154600854610f00949291906148b4565b60025490565b6005546040805163f99031a760e01b815233600482015290516000926201000090046001600160a01b03169163f99031a7916024808301926020929190829003018186803b1580156110ac57600080fd5b505afa1580156110c0573d6000803e3d6000fd5b505050506040513d60208110156110d657600080fd5b50518061115f57506005546040805163f99031a760e01b81526001600160a01b0386811660048301529151620100009093049091169163f99031a791602480820192602092909190829003018186803b15801561113257600080fd5b505afa158015611146573d6000803e3d6000fd5b505050506040513d602081101561115c57600080fd5b50515b6111a4576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d5d2125511531254d5607a1b604482015290519081900360640190fd5b336001600160a01b03851614806111de57506001600160a01b03841660009081526001602090815260408083203384529091529020548211155b611227576040805162461bcd60e51b815260206004820152601560248201527422a9292fa12a27a5a2a72fa120a22fa1a0a62622a960591b604482015290519081900360640190fd5b611232848484614919565b336001600160a01b0385161480159061127057506001600160a01b038416600090815260016020908152604080832033845290915290205460001914155b156112f2576001600160a01b03841660009081526001602090815260408083203384529091529020546112a39083614a29565b6001600160a01b038581166000908152600160209081526040808320338085529083529281902085905580519485525192871693919260008051602061574d8339815191529281900390910190a35b6001600160a01b038316301461130d5761130d848484614a8b565b5060015b9392505050565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156113b5576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600b602052604090205460ff16611421576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600b602052604090205460ff1661147e576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600954610100900460ff166114d0576040805162461bcd60e51b81526020600482015260136024820152724552525f535741505f4e4f545f5055424c494360681b604482015290519081900360640190fd5b6001600160a01b038088166000908152600b602052604080822092881682529020600382015461150c906002670de0b6b3a76400005b04614b89565b881115611553576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b6000611575896115706115696008546006614c52565b6001614b89565b614b89565b9050600061159884600301548560020154856003015486600201546008546148b4565b9050868111156115e5576040805162461bcd60e51b81526020600482015260136024820152724552525f4241445f4c494d49545f505249434560681b604482015290519081900360640190fd5b61160584600301548560020154856003015486600201548e60085461367b565b95508786101561164c576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b60006116588b84614a29565b9050611668856003015482614d5a565b856003018190555061167e846003015488614a29565b6003808601829055860154600280880154908701546008546116a19491906148b4565b9550818610156116ea576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b87861115611731576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4c494d49545f505249434560881b604482015290519081900360640190fd5b61173b8b88614c52565b821115611781576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b896001600160a01b03168c6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d433788e8b604051808381526020018281526020019250505060405180910390a46117e98c338d614da7565b6117f48a3389614db3565b6118788c600560029054906101000a90046001600160a01b03166001600160a01b0316636611f5286040518163ffffffff1660e01b815260040160206040518083038186803b15801561184657600080fd5b505afa15801561185a573d6000803e3d6000fd5b505050506040513d602081101561187057600080fd5b505185614db3565b6118858d8d8c8e8b614dbe565b50505050506005805461ff00191690559097909650945050505050565b6001600160a01b03166000908152600b602052604090205460ff1690565b60055460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611975576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560095460ff16156119cf576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6007546001600160a01b03163314611a23576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b64e8d4a51000811015611a6b576040805162461bcd60e51b815260206004820152600b60248201526a4552525f4d494e5f46454560a81b604482015290519081900360640190fd5b67016345785d8a0000811115611ab6576040805162461bcd60e51b815260206004820152600b60248201526a4552525f4d41585f46454560a81b604482015290519081900360640190fd5b6008556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611b72576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600754336001600160a01b0390911614611bd7576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b602052604090205460ff16611c34576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60095460ff1615611c7f576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b670de0b6b3a7640000811015611ccd576040805162461bcd60e51b815260206004820152600e60248201526d11549497d3525397d5d15251d21560921b604482015290519081900360640190fd5b6802b5e3af16b1880000811115611d1c576040805162461bcd60e51b815260206004820152600e60248201526d11549497d3505617d5d15251d21560921b604482015290519081900360640190fd5b620f4240821015611d66576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4d494e5f42414c414e434560881b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b602052604090206002015480821115611dfd57611d9f600c54611d9a8484614a29565b614d5a565b600c8190556802b5e3af16b18800001015611df8576040805162461bcd60e51b815260206004820152601460248201527311549497d3505617d513d5105317d5d15251d21560621b604482015290519081900360640190fd5b611e1e565b80821015611e1e57611e1a600c54611e158385614a29565b614a29565b600c555b6001600160a01b0384166000908152600b602052604090206002810183905560030180549084905580841115611e6757611e628533611e5d8785614a29565b614da7565b611e8a565b80841015611e8a576000611e7b8286614a29565b9050611e88863383614db3565b505b50506005805461ff0019169055505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611f4a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560095460ff16611fa4576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600b602052604090205460ff16612001576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600b6020526040902060038101546002808301549054600c5460085461203b94939291908990614eb7565b915082821015612082576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600b602052604090206003908101546120b791670de0b6b3a76400005b04600101614b89565b8211156120ff576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b61210d816003015483614a29565b60038201556040805183815290516001600160a01b0387169133917fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9181900360200190a361215c3385614f7b565b61216584614f85565b612170853384614db3565b61217c6000338661449a565b506005805461ff00191690559392505050565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561222c576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600b602052604090205460ff16612298576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600b602052604090205460ff166122f5576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600954610100900460ff16612347576040805162461bcd60e51b81526020600482015260136024820152724552525f535741505f4e4f545f5055424c494360681b604482015290519081900360640190fd5b6001600160a01b038088166000908152600b60205260408082209288168252902060038082015461238091670de0b6b3a76400006120ae565b8611156123c8576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b60006123e983600301548460020154846003015485600201546008546148b4565b905085811115612436576040805162461bcd60e51b81526020600482015260136024820152724552525f4241445f4c494d49545f505249434560681b604482015290519081900360640190fd5b61245683600301548460020154846003015485600201548b6008546143ef565b94508885111561249c576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b60006124b2866115706115696008546006614c52565b90506124c2846003015482614d5a565b84600301819055506124d8836003015489614a29565b6003808501829055850154600280870154908601546008546124fb9491906148b4565b945081851015612544576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b8685111561258b576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4c494d49545f505249434560881b604482015290519081900360640190fd5b6125958689614c52565b8211156125db576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b886001600160a01b03168b6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378898c604051808381526020018281526020019250505060405180910390a46126438b3388614da7565b61264e89338a614db3565b6126d28b600560029054906101000a90046001600160a01b03166001600160a01b0316636611f5286040518163ffffffff1660e01b815260040160206040518083038186803b1580156126a057600080fd5b505afa1580156126b4573d6000803e3d6000fd5b505050506040513d60208110156126ca57600080fd5b505183614db3565b6126df8c8c8b898c614dbe565b505050506005805461ff00191690559097909650945050505050565b6007546001600160a01b0316331461274f576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6006546001600160a01b031615612826576006546040805163694710c760e11b815260048101918252604481018690526001600160a01b039092169163d28e218e9187918791879187919081906024810190606401876020880280828437600083820152601f01601f19169091018481038352858152602090810191508690860280828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b15801561280d57600080fd5b505af1158015612821573d6000803e3d6000fd5b505050505b50505050565b3360009081526001602090815260408083206001600160a01b038616845290915281205480831115612881573360009081526001602090815260408083206001600160a01b03881684529091528120556128b0565b61288b8184614a29565b3360009081526001602090815260408083206001600160a01b03891684529091529020555b3360008181526001602090815260408083206001600160a01b03891680855290835292819020548151908152905192939260008051602061574d833981519152929181900390910190a35060019392505050565b6001600160a01b031660009081526020819052604090205490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156129cb576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600754336001600160a01b0390911614612a30576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03929092169190911790556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612b09576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560095460ff16612b63576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6000612b6d611055565b90506000612b7b8583614c52565b905080612bc1576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b60005b600a54811015612d42576000600a8281548110612bdd57fe5b60009182526020808320909101546001600160a01b0316808352600b909152604082206003015490925090612c128583614b89565b905080612c58576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b878785818110612c6457fe5b90506020020135811115612cae576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b6020526040902060030154612cd49082614d5a565b6001600160a01b0384166000818152600b60209081526040918290206003019390935580518481529051919233927f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9281900390910190a3612d37833383614da7565b505050600101612bc4565b50612d4c85614480565b612d56868661448c565b612d626001878761449a565b50506005805461ff001916905550505050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612e21576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0381166000908152600b602052604090205460ff16612e8d576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b158015612ed357600080fd5b505afa158015612ee7573d6000803e3d6000fd5b505050506040513d6020811015612efd57600080fd5b50516001600160a01b039091166000908152600b60205260409020600301556005805461ff0019169055565b60095460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612fde576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600754336001600160a01b0390911614613043576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b03929092169190911790556005805461ff0019169055565b600554600090610100900460ff16156130be576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b50600c5490565b600554600090610100900460ff1615613113576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600b602052604090205460ff16613170576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600b602052604090206002015490565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610d555780601f10610d2a57610100808354040283529160200191610d55565b6542524f4e5a4560d01b90565b6005546040805163f99031a760e01b815233600482015290516000926201000090046001600160a01b03169163f99031a7916024808301926020929190829003018186803b15801561324e57600080fd5b505afa158015613262573d6000803e3d6000fd5b505050506040513d602081101561327857600080fd5b50518061330157506005546040805163f99031a760e01b81526001600160a01b0386811660048301529151620100009093049091169163f99031a791602480820192602092909190829003018186803b1580156132d457600080fd5b505afa1580156132e8573d6000803e3d6000fd5b505050506040513d60208110156132fe57600080fd5b50515b613346576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d5d2125511531254d5607a1b604482015290519081900360640190fd5b613351338484614919565b6001600160a01b038316301461336c5761336c338484614a8b565b50600192915050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613421576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560095460ff1661347b576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6000613485611055565b905060006134938583614c52565b9050806134d9576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b6134e33386614f7b565b6134ec85614f85565b60005b600a5481101561366e576000600a828154811061350857fe5b60009182526020808320909101546001600160a01b0316808352600b90915260408220600301549092509061353d8583614b89565b905080613583576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b87878581811061358f57fe5b905060200201358110156135da576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b60205260409020600301546136009082614a29565b6001600160a01b0384166000818152600b60209081526040918290206003019390935580518481529051919233927fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9281900390910190a3613663833383614db3565b5050506001016134ef565b50611e8a6000338761449a565b6000806136888786614c52565b9050600061369e670de0b6b3a764000085614a29565b90506136aa8582614b89565b905060006136c18a6136bc8c85614d5a565b614c52565b905060006136cf8285614f8e565b905060006136e5670de0b6b3a764000083614a29565b90506136f18a82614b89565b9c9b505050505050505050505050565b600554606090610100900460ff161561374f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60095460ff1661379a576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b600a805480602002602001604051908101604052809291908181526020018280548015610d5557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116137d2575050505050905090565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156138a7576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560095460ff16613901576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600b602052604090205460ff1661395e576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600b602052604090206003015461398e906002670de0b6b3a7640000611506565b8311156139d5576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b6001600160a01b0384166000908152600b6020526040902060038101546002808301549054600c54600854613a0f9493929190899061509c565b915082821015613a56576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b613a64816003015485614d5a565b60038201556040805185815290516001600160a01b0387169133917f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9181900360200190a3613ab282614480565b613abc868361448c565b613ac7853386614da7565b613ad36001878461449a565b506005805461ff0019169055949350505050565b600554600090610100900460ff1615613b35576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b506006546001600160a01b031690565b600554606090610100900460ff161561379a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b600a5490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613c45576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600754336001600160a01b0390911614613caa576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0381166000908152600b602052604090205460ff16613d07576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60095460ff1615613d52576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6001600160a01b0381166000908152600b602052604090206003810154600c546002909201549091613d8391614a29565b600c556001600160a01b0382166000908152600b6020526040902060010154600a80546000198101919082908110613db757fe5b600091825260209091200154600a80546001600160a01b039092169184908110613ddd57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600b6000600a8581548110613e1d57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902060010155600a805480613e5057fe5b60008281526020808220600019908401810180546001600160a01b031916905590920190925560408051608081018252838152808301848152818301858152606083018681526001600160a01b038b168752600b909552929094209051815460ff19169015151781559251600184015551600283015551600390910155613ed8843385614db3565b50506005805461ff00191690555050565b600554600090610100900460ff1615613f37576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b5060085490565b3360009081526001602090815260408083206001600160a01b0386168452909152812054613f6c9083614d5a565b3360008181526001602090815260408083206001600160a01b03891680855290835292819020859055805194855251919360008051602061574d833981519152929081900390910190a350600192915050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26007546001600160a01b0316331461409f576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600b602052604090205460ff16156140fc576040805162461bcd60e51b815260206004820152600c60248201526b11549497d254d7d093d5539160a21b604482015290519081900360640190fd5b60095460ff1615614147576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b600a5460081161418f576040805162461bcd60e51b815260206004820152600e60248201526d4552525f4d41585f544f4b454e5360901b604482015290519081900360640190fd5b604080516080810182526001808252600a805460208085019182526000858701818152606087018281526001600160a01b038c16808452600b9094529782209651875460ff1916901515178755925186860155915160028601559451600390940193909355805491820181559091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b031916909117905561423c838383611ac6565b505050565b600554600090610100900460ff161561428f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600b602052604090205460ff166142ec576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600b6020526040902060020154600c54611311908290614c52565b6007546001600160a01b031681565b600554600090610100900460ff1615614373576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600b602052604090205460ff166143d0576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600b602052604090206003015490565b6000806143fc8588614c52565b9050600061440a8786614a29565b905060006144188883614c52565b905060006144268285614f8e565b905061443a81670de0b6b3a7640000614a29565b905061444e670de0b6b3a764000087614a29565b945061446361445d8c83614b89565b86614c52565b9b9a5050505050505050505050565b600954610100900460ff1690565b61448981615138565b50565b61449682826151ad565b5050565b6006546001600160a01b03161561459d5760018315151461452b5760065460408051633953208d60e21b81526000600482018190526001600160a01b038681166024840152604483018690529251929093169263e54c82349260648084019382900301818387803b15801561450e57600080fd5b505af1158015614522573d6000803e3d6000fd5b5050505061459d565b6006546040805163cf33fc2960e01b81526000600482018190526001600160a01b038681166024840152604483018690529251929093169263cf33fc299260648084019382900301818387803b15801561458457600080fd5b505af1158015614598573d6000803e3d6000fd5b505050505b60055460408051633b736e5160e11b815281516000936201000090046001600160a01b0316926376e6dca2926004808201939182900301818787803b1580156145e557600080fd5b505af11580156145f9573d6000803e3d6000fd5b505050506040513d604081101561460f57600080fd5b505190506001600160a01b0381161561282657600a546040805182815260208084028201019091528291606091908015614653578160200160208202803883390190505b5090506060600a80549050604051908082528060200260200182016040528015614687578160200160208202803883390190505b50905060005b600a5481101561474d57600b6000600a83815481106146a857fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206003015483518490839081106146de57fe5b60200260200101818152505061472e600b6000600a84815481106146fe57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902060020154600c54614c52565b82828151811061473a57fe5b602090810291909101015260010161468d565b50826001600160a01b031663eda6851087600a85858a8d6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b031681526020018060200180602001806020018681526020018515151515815260200184810384528981815481526020019150805480156147f257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116147d4575b50508481038352885181528851602091820191808b01910280838360005b83811015614828578181015183820152602001614810565b50505050905001848103825287818151815260200191508051906020019060200280838360005b8381101561486757818101518382015260200161484f565b505050509050019950505050505050505050600060405180830381600087803b15801561489357600080fd5b505af11580156148a7573d6000803e3d6000fd5b5050505050505050505050565b6000806148c18787614c52565b905060006148cf8686614c52565b905060006148dd8383614c52565b905060006148ff670de0b6b3a76400006136bc670de0b6b3a764000089614a29565b905061490b8282614b89565b9a9950505050505050505050565b6001600160a01b03831660009081526020819052604090205481111561497d576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b6001600160a01b0383166000908152602081905260409020546149a09082614a29565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546149cf9082614d5a565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000806000614a3885856151b8565b915091508015614a83576040805162461bcd60e51b81526020600482015260116024820152704552525f5355425f554e444552464c4f5760781b604482015290519081900360640190fd5b509392505050565b60055460408051633b736e5160e11b815281516000936201000090046001600160a01b0316926376e6dca2926004808201939182900301818787803b158015614ad357600080fd5b505af1158015614ae7573d6000803e3d6000fd5b505050506040513d6040811015614afd57600080fd5b505190506001600160a01b038116156128265760408051630a6c953560e01b81526001600160a01b03868116600483015285811660248301526044820185905291518392831691630a6c953591606480830192600092919082900301818387803b158015614b6a57600080fd5b505af1158015614b7e573d6000803e3d6000fd5b505050505050505050565b6000828202831580614ba3575082848281614ba057fe5b04145b614be7576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6706f05b59d3b20000810181811015614c3a576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6000670de0b6b3a7640000825b049695505050505050565b600081614c95576040805162461bcd60e51b815260206004820152600c60248201526b4552525f4449565f5a45524f60a01b604482015290519081900360640190fd5b670de0b6b3a76400008302831580614cbd5750670de0b6b3a7640000848281614cba57fe5b04145b614d01576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b60028304810181811015614d4f576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b6000848281614c4757fe5b600082820183811015611311576040805162461bcd60e51b815260206004820152601060248201526f4552525f4144445f4f564552464c4f5760801b604482015290519081900360640190fd5b61423c838330846151dd565b61423c8383836152c6565b60055460408051633b736e5160e11b815281516000936201000090046001600160a01b0316926376e6dca2926004808201939182900301818787803b158015614e0657600080fd5b505af1158015614e1a573d6000803e3d6000fd5b505050506040513d6040811015614e3057600080fd5b506020015190506001600160a01b03811615614eaf5760408051635fd8b58560e01b81526001600160a01b03888116600483015287811660248301526044820186905286811660648301526084820185905291518392831691635fd8b5859160a480830192600092919082900301818387803b15801561489357600080fd5b505050505050565b600080614ec48786614c52565b90506000614eda85670de0b6b3a7640000614b89565b90506000614ee88883614a29565b90506000614ef6828a614c52565b90506000614f1582614f10670de0b6b3a764000088614c52565b614f8e565b90506000614f23828e614b89565b90506000614f318e83614a29565b90506000614f50614f4a670de0b6b3a76400008a614a29565b8b614b89565b9050614f6882611570670de0b6b3a764000084614a29565b9f9e505050505050505050505050505050565b61449682826153ae565b614489816153b9565b60006001831015614fde576040805162461bcd60e51b81526020600482015260156024820152744552525f42504f575f424153455f544f4f5f4c4f5760581b604482015290519081900360640190fd5b671bc16d674ec7ffff831115615034576040805162461bcd60e51b815260206004820152601660248201527508aa4a4be84a09eaebe8482a68abea89e9ebe90928e960531b604482015290519081900360640190fd5b600061503f83615489565b9050600061504d8483614a29565b905060006150638661505e856154a4565b6154b2565b905081615074579250610dae915050565b600061508587846305f5e100615509565b90506150918282614b89565b979650505050505050565b6000806150a98786614c52565b905060006150c86150c2670de0b6b3a764000084614a29565b85614b89565b905060006150e286611570670de0b6b3a764000085614a29565b905060006150f08b83614d5a565b905060006150fe828d614c52565b9050600061510c8287614f8e565b9050600061511a828d614b89565b9050615126818d614a29565b9e9d5050505050505050505050505050565b306000908152602081905260409020546151529082614d5a565b3060009081526020819052604090205560025461516f9082614d5a565b60025560408051828152905130916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b614496308383614919565b6000808284106151ce57505080820360006151d6565b505081810360015b9250929050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091018252602081810180516001600160e01b03166323b872dd60e01b179052825180840190935260158352741b1bddcb5b195d995b0818d85b1b0819985a5b1959605a1b908301529060609061526690879084906155e7565b805190915015614eaf5780806020019051602081101561528557600080fd5b5051614eaf576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd081cdd58d8d9595960aa1b604482015290519081900360640190fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091018252602081810180516001600160e01b031663a9059cbb60e01b179052825180840190935260158352741b1bddcb5b195d995b0818d85b1b0819985a5b1959605a1b908301529060609061534790869084906155e7565b8051909150156153a75780806020019051602081101561536657600080fd5b50516153a7576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd081cdd58d8d9595960aa1b604482015290519081900360640190fd5b5050505050565b614496823083614919565b30600090815260208190526040902054811115615414576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b3060009081526020819052604090205461542e9082614a29565b3060009081526020819052604090205560025461544b9082614a29565b60025560408051828152905160009130917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b6000670de0b6b3a764000061549d836154a4565b0292915050565b670de0b6b3a7640000900490565b600080600283066154cb57670de0b6b3a76400006154cd565b835b90506002830492505b8215611311576154e68485614b89565b935060028306156154fe576154fb8185614b89565b90505b6002830492506154d6565b600082818061552087670de0b6b3a76400006151b8565b9092509050670de0b6b3a764000080600060015b8884106155d8576000670de0b6b3a7640000820290506000806155688a61556385670de0b6b3a7640000614a29565b6151b8565b9150915061557a87611570848c614b89565b96506155868784614c52565b965086615595575050506155d8565b871561559f579315935b80156155a9579315935b84156155c0576155b98688614a29565b95506155cd565b6155ca8688614d5a565b95505b505050600101615534565b50909998505050505050505050565b60606155f48484846155fc565b949350505050565b606060006060856001600160a01b0316856040518082805190602001908083835b6020831061563c5780518252601f19909201916020918201910161561d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461569e576040519150601f19603f3d011682016040523d82523d6000602084013e6156a3565b606091505b509150915081156156b75791506113119050565b8051156156c75780518082602001fd5b8360405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156157115781810151838201526020016156f9565b50505050905090810190601f16801561573e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fdfe8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a265627a7a72315820fd21d9371582197fc87c1b381e7d91ba5734722eead574cc377e9823377f998d64736f6c634300050c0032
Verified Source Code Partial Match
Compiler: v0.5.12+commit.7709ece9
EVM: petersburg
Optimization: Yes (200 runs)
MNum.sol 163 lines
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity 0.5.12;
import "./MConst.sol";
contract MNum is MConst {
function btoi(uint a)
internal pure
returns (uint)
{
return a / BONE;
}
function bfloor(uint a)
internal pure
returns (uint)
{
return btoi(a) * BONE;
}
function badd(uint a, uint b)
internal pure
returns (uint)
{
uint c = a + b;
require(c >= a, "ERR_ADD_OVERFLOW");
return c;
}
function bsub(uint a, uint b)
internal pure
returns (uint)
{
(uint c, bool flag) = bsubSign(a, b);
require(!flag, "ERR_SUB_UNDERFLOW");
return c;
}
function bsubSign(uint a, uint b)
internal pure
returns (uint, bool)
{
if (a >= b) {
return (a - b, false);
} else {
return (b - a, true);
}
}
function bmul(uint a, uint b)
internal pure
returns (uint)
{
uint c0 = a * b;
require(a == 0 || c0 / a == b, "ERR_MUL_OVERFLOW");
uint c1 = c0 + (BONE / 2);
require(c1 >= c0, "ERR_MUL_OVERFLOW");
uint c2 = c1 / BONE;
return c2;
}
function bdiv(uint a, uint b)
internal pure
returns (uint)
{
require(b != 0, "ERR_DIV_ZERO");
uint c0 = a * BONE;
require(a == 0 || c0 / a == BONE, "ERR_DIV_INTERNAL"); // bmul overflow
uint c1 = c0 + (b / 2);
require(c1 >= c0, "ERR_DIV_INTERNAL"); // badd require
uint c2 = c1 / b;
return c2;
}
// DSMath.wpow
function bpowi(uint a, uint n)
internal pure
returns (uint)
{
uint z = n % 2 != 0 ? a : BONE;
for (n /= 2; n != 0; n /= 2) {
a = bmul(a, a);
if (n % 2 != 0) {
z = bmul(z, a);
}
}
return z;
}
// Compute b^(e.w) by splitting it into (b^e)*(b^0.w).
// Use `bpowi` for `b^e` and `bpowK` for k iterations
// of approximation of b^0.w
function bpow(uint base, uint exp)
internal pure
returns (uint)
{
require(base >= MIN_BPOW_BASE, "ERR_BPOW_BASE_TOO_LOW");
require(base <= MAX_BPOW_BASE, "ERR_BPOW_BASE_TOO_HIGH");
uint whole = bfloor(exp);
uint remain = bsub(exp, whole);
uint wholePow = bpowi(base, btoi(whole));
if (remain == 0) {
return wholePow;
}
uint partialResult = bpowApprox(base, remain, BPOW_PRECISION);
return bmul(wholePow, partialResult);
}
function bpowApprox(uint base, uint exp, uint precision)
internal pure
returns (uint)
{
// term 0:
uint a = exp;
(uint x, bool xneg) = bsubSign(base, BONE);
uint term = BONE;
uint sum = term;
bool negative = false;
// term(k) = numer / denom
// = (product(a - i - 1, i=1-->k) * x^k) / (k!)
// each iteration, multiply previous term by (a-(k-1)) * x / k
// continue until term is less than precision
for (uint i = 1; term >= precision; i++) {
uint bigK = i * BONE;
(uint c, bool cneg) = bsubSign(a, bsub(bigK, BONE));
term = bmul(term, bmul(c, x));
term = bdiv(term, bigK);
if (term == 0) break;
if (xneg) negative = !negative;
if (cneg) negative = !negative;
if (negative) {
sum = bsub(sum, term);
} else {
sum = badd(sum, term);
}
}
return sum;
}
}
MMath.sol 188 lines
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity 0.5.12;
import "./MNum.sol";
contract MMath is MBronze, MConst, MNum {
/**********************************************************************************************
// calcSpotPrice //
// sP = spotPrice //
// bI = tokenBalanceIn ( bI / wI ) 1 //
// bO = tokenBalanceOut sP = ----------- * ---------- //
// wI = tokenWeightIn ( bO / wO ) ( 1 - sF ) //
// wO = tokenWeightOut //
// sF = swapFee //
**********************************************************************************************/
function calcSpotPrice(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint swapFee
)
internal pure
returns (uint spotPrice)
{
uint numer = bdiv(tokenBalanceIn, tokenWeightIn);
uint denom = bdiv(tokenBalanceOut, tokenWeightOut);
uint ratio = bdiv(numer, denom);
uint scale = bdiv(BONE, bsub(BONE, swapFee));
return (spotPrice = bmul(ratio, scale));
}
/**********************************************************************************************
// calcOutGivenIn //
// aO = tokenAmountOut //
// bO = tokenBalanceOut //
// bI = tokenBalanceIn / / bI \ (wI / wO) \ //
// aI = tokenAmountIn aO = bO * | 1 - | -------------------------- | ^ | //
// wI = tokenWeightIn \ \ ( bI + ( aI * ( 1 - sF )) / / //
// wO = tokenWeightOut //
// sF = swapFee //
**********************************************************************************************/
function calcOutGivenIn(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenAmountIn,
uint swapFee
)
public pure
returns (uint tokenAmountOut)
{
uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
uint adjustedIn = bsub(BONE, swapFee);
adjustedIn = bmul(tokenAmountIn, adjustedIn);
uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
uint foo = bpow(y, weightRatio);
uint bar = bsub(BONE, foo);
tokenAmountOut = bmul(tokenBalanceOut, bar);
return tokenAmountOut;
}
/**********************************************************************************************
// calcInGivenOut //
// aI = tokenAmountIn //
// bO = tokenBalanceOut / / bO \ (wO / wI) \ //
// bI = tokenBalanceIn bI * | | ------------ | ^ - 1 | //
// aO = tokenAmountOut aI = \ \ ( bO - aO ) / / //
// wI = tokenWeightIn -------------------------------------------- //
// wO = tokenWeightOut ( 1 - sF ) //
// sF = swapFee //
**********************************************************************************************/
function calcInGivenOut(
uint tokenBalanceIn,
uint tokenWeightIn,
uint tokenBalanceOut,
uint tokenWeightOut,
uint tokenAmountOut,
uint swapFee
)
public pure
returns (uint tokenAmountIn)
{
uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
uint diff = bsub(tokenBalanceOut, tokenAmountOut);
uint y = bdiv(tokenBalanceOut, diff);
uint foo = bpow(y, weightRatio);
foo = bsub(foo, BONE);
tokenAmountIn = bsub(BONE, swapFee);
tokenAmountIn = bdiv(bmul(tokenBalanceIn, foo), tokenAmountIn);
return tokenAmountIn;
}
/**********************************************************************************************
// calcPoolOutGivenSingleIn //
// pAo = poolAmountOut / \ //
// tAi = tokenAmountIn /// / // wI \ \\ \ wI \ //
// wI = tokenWeightIn //| tAi *| 1 - || 1 - -- | * sF || + tBi \ -- \ //
// tW = totalWeight pAo=|| \ \ \\ tW / // | ^ tW | * pS - pS //
// tBi = tokenBalanceIn \\ ------------------------------------- / / //
// pS = poolSupply \\ tBi / / //
// sF = swapFee \ / //
**********************************************************************************************/
function calcPoolOutGivenSingleIn(
uint tokenBalanceIn,
uint tokenWeightIn,
uint poolSupply,
uint totalWeight,
uint tokenAmountIn,
uint swapFee
)
internal pure
returns (uint poolAmountOut)
{
// Charge the trading fee for the proportion of tokenAi
/// which is implicitly traded to the other pool tokens.
// That proportion is (1- weightTokenIn)
// tokenAiAfterFee = tAi * (1 - (1-weightTi) * poolFee);
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BONE, zaz));
uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);
uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);
// uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;
uint poolRatio = bpow(tokenInRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
poolAmountOut = bsub(newPoolSupply, poolSupply);
return poolAmountOut;
}
/**********************************************************************************************
// calcSingleOutGivenPoolIn //
// tAo = tokenAmountOut / / \\ //
// bO = tokenBalanceOut / // pS - (pAi * (1 - eF)) \ / 1 \ \\ //
// pAi = poolAmountIn | bO - || ----------------------- | ^ | --------- | * b0 || //
// ps = poolSupply \ \\ pS / \(wO / tW)/ // //
// wI = tokenWeightIn tAo = \ \ // //
// tW = totalWeight / / wO \ \ //
// sF = swapFee * | 1 - | 1 - ---- | * sF | //
// eF = exitFee \ \ tW / / //
**********************************************************************************************/
function calcSingleOutGivenPoolIn(
uint tokenBalanceOut,
uint tokenWeightOut,
uint poolSupply,
uint totalWeight,
uint poolAmountIn,
uint swapFee
)
internal pure
returns (uint tokenAmountOut)
{
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
// charge exit fee on the pool token side
// pAiAfterExitFee = pAi*(1-exitFee)
uint poolAmountInAfterExitFee = bmul(poolAmountIn, BONE);
uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
// newBalTo = poolRatio^(1/weightTo) * balTo;
uint tokenOutRatio = bpow(poolRatio, bdiv(BONE, normalizedWeight));
uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);
uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);
// charge swap fee on the output token side
//uint tAo = tAoBeforeSwapFee * (1 - (1-weightTo) * swapFee)
uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BONE, zaz));
return tokenAmountOut;
}
}
MPool.sol 752 lines
pragma solidity 0.5.12;
import "./MToken.sol";
import "./MMath.sol";
interface IMFactory {
function isWhiteList(address w) external view returns (bool);
function getMining() external returns (address lpMiningAdr, address swapMiningAdr);
function getFeeTo() external view returns (address);
}
interface IMining {
// pair
function addLiquidity(bool isGp, address _user, uint256 _amount) external;
function removeLiquidity(bool isGp, address _user, uint256 _amount) external;
function updateGPInfo(address[] calldata gps, uint256[] calldata amounts) external;
// lp mining
function onTransferLiquidity(address from, address to, uint256 lpAmount) external;
function claimLiquidityShares(address user, address[] calldata tokens, uint256[] calldata balances, uint256[] calldata weights, uint256 amount, bool _add) external;
// swap mining
function claimSwapShare(address user, address tokenIn, uint256 amountIn, address tokenOut, uint256 amountOut) external;
}
contract MPool is MBronze, MToken, MMath {
struct Record {
bool bound; // is token bound to pool
uint index; // private
uint denorm; // denormalized weight
uint balance;
}
event LOG_SWAP(
address indexed caller,
address indexed tokenIn,
address indexed tokenOut,
uint256 tokenAmountIn,
uint256 tokenAmountOut
);
event LOG_JOIN(
address indexed caller,
address indexed tokenIn,
uint256 tokenAmountIn
);
event LOG_EXIT(
address indexed caller,
address indexed tokenOut,
uint256 tokenAmountOut
);
event LOG_CALL(
bytes4 indexed sig,
address indexed caller,
bytes data
) anonymous;
modifier _logs_() {
emit LOG_CALL(msg.sig, msg.sender, msg.data);
_;
}
modifier _lock_() {
require(!_mutex, "ERR_REENTRY");
_mutex = true;
_;
_mutex = false;
}
modifier _viewlock_() {
require(!_mutex, "ERR_REENTRY");
_;
}
bool private _mutex;
IMFactory private _factory; // MFactory address to push token exitFee to and check whitelist from factory
IMining private _pair;
address public controller; // has CONTROL role
// `setSwapFee` and `finalize` require CONTROL
// `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`
uint private _swapFee;
bool private _finalized;
bool private _publicSwap; // true if PUBLIC can call SWAP functions
address[] private _tokens;
mapping(address => Record) private _records;
uint private _totalWeight;
constructor() public {
controller = msg.sender;
_factory = IMFactory(msg.sender);
_swapFee = MIN_FEE;
_publicSwap = false;
_finalized = false;
}
function isPublicSwap()
external view
returns (bool)
{
return _publicSwap;
}
function isFinalized()
external view
returns (bool)
{
return _finalized;
}
function isBound(address t)
external view
returns (bool)
{
return _records[t].bound;
}
function getNumTokens()
external view
returns (uint)
{
return _tokens.length;
}
function getCurrentTokens()
external view _viewlock_
returns (address[] memory tokens)
{
return _tokens;
}
function getFinalTokens()
external view
_viewlock_
returns (address[] memory tokens)
{
require(_finalized, "ERR_NOT_FINALIZED");
return _tokens;
}
function getDenormalizedWeight(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound, "ERR_NOT_BOUND");
return _records[token].denorm;
}
function getTotalDenormalizedWeight()
external view
_viewlock_
returns (uint)
{
return _totalWeight;
}
function getNormalizedWeight(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound, "ERR_NOT_BOUND");
uint denorm = _records[token].denorm;
return bdiv(denorm, _totalWeight);
}
function getBalance(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound, "ERR_NOT_BOUND");
return _records[token].balance;
}
function getSwapFee()
external view
_viewlock_
returns (uint)
{
return _swapFee;
}
function getPair()
external view
_viewlock_
returns (address)
{
return address(_pair);
}
function setSwapFee(uint swapFee)
external
_logs_
_lock_
{
require(!_finalized, "ERR_IS_FINALIZED");
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
require(swapFee >= MIN_FEE, "ERR_MIN_FEE");
require(swapFee <= MAX_FEE, "ERR_MAX_FEE");
_swapFee = swapFee;
}
function setController(address manager)
external
_logs_
_lock_
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
controller = manager;
}
function setPair(IMining pair)
external
_logs_
_lock_
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
_pair = pair;
}
function finalize(address beneficiary, uint fixPoolSupply)
external
_logs_
_lock_
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
require(!_finalized, "ERR_IS_FINALIZED");
require(_tokens.length >= MIN_BOUND_TOKENS, "ERR_MIN_TOKENS");
_finalized = true;
_publicSwap = true;
uint256 supply = fixPoolSupply == 0 ? INIT_POOL_SUPPLY : fixPoolSupply;
_mintPoolShare(supply);
_pushPoolShare(beneficiary, supply);
_lpChanging(true, beneficiary, supply);
}
function bind(address token, uint balance, uint denorm)
external
_logs_
// _lock_ Bind does not lock because it jumps to `rebind`, which does
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
require(!_records[token].bound, "ERR_IS_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
require(_tokens.length < MAX_BOUND_TOKENS, "ERR_MAX_TOKENS");
_records[token] = Record({
bound: true,
index: _tokens.length,
denorm: 0, // balance and denorm will be validated
balance: 0 // and set by `rebind`
});
_tokens.push(token);
rebind(token, balance, denorm);
}
function rebind(address token, uint balance, uint denorm)
public
_logs_
_lock_
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
require(denorm >= MIN_WEIGHT, "ERR_MIN_WEIGHT");
require(denorm <= MAX_WEIGHT, "ERR_MAX_WEIGHT");
require(balance >= MIN_BALANCE, "ERR_MIN_BALANCE");
// Adjust the denorm and totalWeight
uint oldWeight = _records[token].denorm;
if (denorm > oldWeight) {
_totalWeight = badd(_totalWeight, bsub(denorm, oldWeight));
require(_totalWeight <= MAX_TOTAL_WEIGHT, "ERR_MAX_TOTAL_WEIGHT");
} else if (denorm < oldWeight) {
_totalWeight = bsub(_totalWeight, bsub(oldWeight, denorm));
}
_records[token].denorm = denorm;
// Adjust the balance record and actual token balance
uint oldBalance = _records[token].balance;
_records[token].balance = balance;
if (balance > oldBalance) {
_pullUnderlying(token, msg.sender, bsub(balance, oldBalance));
} else if (balance < oldBalance) {
uint tokenBalanceWithdrawn = bsub(oldBalance, balance);
_pushUnderlying(token, msg.sender, tokenBalanceWithdrawn);
}
}
function unbind(address token)
external
_logs_
_lock_
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
uint tokenBalance = _records[token].balance;
_totalWeight = bsub(_totalWeight, _records[token].denorm);
// Swap the token-to-unbind with the last token,
// then delete the last token
uint index = _records[token].index;
uint last = _tokens.length - 1;
_tokens[index] = _tokens[last];
_records[_tokens[index]].index = index;
_tokens.pop();
_records[token] = Record({
bound: false,
index: 0,
denorm: 0,
balance: 0
});
_pushUnderlying(token, msg.sender, tokenBalance);
}
// Absorb any tokens that have been sent to this contract into the pool
function gulp(address token)
external
_logs_
_lock_
{
require(_records[token].bound, "ERR_NOT_BOUND");
_records[token].balance = IERC20(token).balanceOf(address(this));
}
function getSpotPrice(address tokenIn, address tokenOut)
external view
_viewlock_
returns (uint spotPrice)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
Record storage outRecord = _records[tokenOut];
return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, _swapFee);
}
function getSpotPriceSansFee(address tokenIn, address tokenOut)
external view
_viewlock_
returns (uint spotPrice)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
Record storage outRecord = _records[tokenOut];
return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, 0);
}
function joinPool(address beneficiary, uint poolAmountOut, uint[] calldata maxAmountsIn)
external
_logs_
_lock_
{
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = totalSupply();
uint ratio = bdiv(poolAmountOut, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountIn = bmul(ratio, bal);
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountsIn[i], "ERR_LIMIT_IN");
_records[t].balance = badd(_records[t].balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, t, tokenAmountIn);
_pullUnderlying(t, msg.sender, tokenAmountIn);
}
_mintPoolShare(poolAmountOut);
_pushPoolShare(beneficiary, poolAmountOut);
_lpChanging(true, beneficiary, poolAmountOut);
}
function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut)
external
_logs_
_lock_
{
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = totalSupply();
uint ratio = bdiv(poolAmountIn, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(poolAmountIn);
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountOut = bmul(ratio, bal);
require(tokenAmountOut != 0, "ERR_MATH_APPROX");
require(tokenAmountOut >= minAmountsOut[i], "ERR_LIMIT_OUT");
_records[t].balance = bsub(_records[t].balance, tokenAmountOut);
emit LOG_EXIT(msg.sender, t, tokenAmountOut);
_pushUnderlying(t, msg.sender, tokenAmountOut);
}
_lpChanging(false, msg.sender, poolAmountIn);
}
function swapExactAmountIn(
address user,
address tokenIn,
uint tokenAmountIn,
address tokenOut,
uint minAmountOut,
uint maxPrice
)
external
_logs_
_lock_
returns (uint tokenAmountOut, uint spotPriceAfter)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(_publicSwap, "ERR_SWAP_NOT_PUBLIC");
Record storage inRecord = _records[address(tokenIn)];
Record storage outRecord = _records[address(tokenOut)];
require(tokenAmountIn <= bmul(inRecord.balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
uint256 factoryFee = bmul(tokenAmountIn, bmul(bdiv(_swapFee, 6), 1));
uint spotPriceBefore = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceBefore <= maxPrice, "ERR_BAD_LIMIT_PRICE");
tokenAmountOut = calcOutGivenIn(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
tokenAmountIn,
_swapFee
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
uint inAfterFee = bsub(tokenAmountIn, factoryFee);
inRecord.balance = badd(inRecord.balance, inAfterFee);
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
spotPriceAfter = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX");
require(spotPriceAfter <= maxPrice, "ERR_LIMIT_PRICE");
require(spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOut), "ERR_MATH_APPROX");
emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
_pushUnderlying(tokenIn, _factory.getFeeTo(), factoryFee);
_swapMining(user, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);
return (tokenAmountOut, spotPriceAfter);
}
function swapExactAmountOut(
address user,
address tokenIn,
uint maxAmountIn,
address tokenOut,
uint tokenAmountOut,
uint maxPrice
)
external
_logs_
_lock_
returns (uint tokenAmountIn, uint spotPriceAfter)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(_publicSwap, "ERR_SWAP_NOT_PUBLIC");
Record storage inRecord = _records[address(tokenIn)];
Record storage outRecord = _records[address(tokenOut)];
require(tokenAmountOut <= bmul(outRecord.balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO");
uint spotPriceBefore = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceBefore <= maxPrice, "ERR_BAD_LIMIT_PRICE");
tokenAmountIn = calcInGivenOut(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
tokenAmountOut,
_swapFee
);
require(tokenAmountIn <= maxAmountIn, "ERR_LIMIT_IN");
uint256 factoryFee = bmul(tokenAmountIn, bmul(bdiv(_swapFee, 6), 1));
inRecord.balance = badd(inRecord.balance, factoryFee);
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
spotPriceAfter = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX");
require(spotPriceAfter <= maxPrice, "ERR_LIMIT_PRICE");
require(spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOut), "ERR_MATH_APPROX");
emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
_pushUnderlying(tokenIn, _factory.getFeeTo(), factoryFee);
_swapMining(user, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);
return (tokenAmountIn, spotPriceAfter);
}
function joinswapExternAmountIn(address beneficiary, address tokenIn, uint tokenAmountIn, uint minPoolAmountOut)
external
_logs_
_lock_
returns (uint poolAmountOut)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
Record storage inRecord = _records[tokenIn];
poolAmountOut = calcPoolOutGivenSingleIn(
inRecord.balance,
inRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountIn,
_swapFee
);
require(poolAmountOut >= minPoolAmountOut, "ERR_LIMIT_OUT");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);
_mintPoolShare(poolAmountOut);
_pushPoolShare(beneficiary, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_lpChanging(true, beneficiary, poolAmountOut);
return poolAmountOut;
}
function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut)
external
_logs_
_lock_
returns (uint tokenAmountOut)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage outRecord = _records[tokenOut];
tokenAmountOut = calcSingleOutGivenPoolIn(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
poolAmountIn,
_swapFee
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO");
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(poolAmountIn);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
_lpChanging(false, msg.sender, poolAmountIn);
return tokenAmountOut;
}
function updatePairGPInfo(address[] calldata gps, uint[] calldata shares)
external
{
require(msg.sender == controller, "ERR_NOT_CONTROLLER");
if (address(_pair) != address(0))
{
_pair.updateGPInfo(gps, shares);
}
}
// ==
// 'Underlying' token-manipulation functions make external calls but are NOT locked
// You must `_lock_` or otherwise ensure reentry-safety
function _pullUnderlying(address erc20, address from, uint amount)
internal
{
safeTransferFrom(IERC20(erc20), from, address(this), amount);
}
function _pushUnderlying(address erc20, address to, uint amount)
internal
{
safeTransfer(IERC20(erc20), to, amount);
}
function _pullPoolShare(address from, uint amount)
internal
{
_pull(from, amount);
}
function _pushPoolShare(address to, uint amount)
internal
{
_push(to, amount);
}
function _mintPoolShare(uint amount)
internal
{
_mint(amount);
}
function _burnPoolShare(uint amount)
internal
{
_burn(amount);
}
function _lpChanging(bool add, address user, uint256 amount)
internal
{
if (address(_pair) != address(0))
{
add == true ? _pair.addLiquidity(false, user, amount) : _pair.removeLiquidity(false, user, amount);
}
(address lpMiningAdr, ) = _factory.getMining();
if (lpMiningAdr != address(0))
{
IMining mining = IMining(lpMiningAdr);
uint256[] memory balances = new uint256[](_tokens.length);
uint256[] memory weights = new uint256[](_tokens.length);
for (uint i = 0; i < _tokens.length; i++) {
balances[i] = _records[_tokens[i]].balance;
weights[i] = bdiv(_records[_tokens[i]].denorm, _totalWeight);
}
mining.claimLiquidityShares(user, _tokens, balances, weights, amount, add);
}
}
function _swapMining(address user, address tokenIn, address tokenOut, uint256 tokenAmountIn, uint256 tokenAmountOut)
internal
{
( ,address swapMiningAdr) = _factory.getMining();
if (swapMiningAdr != address(0)){
IMining mining = IMining(swapMiningAdr);
mining.claimSwapShare(user, tokenIn, tokenAmountIn, tokenOut, tokenAmountOut);
}
}
function _transferLiquidity(address src, address dst, uint amt) internal {
(address lpMiningAdr, ) = _factory.getMining();
if (lpMiningAdr != address(0)){
IMining mining = IMining(lpMiningAdr);
mining.onTransferLiquidity(src, dst, amt);
}
}
function transfer(address dst, uint amt) external returns (bool) {
require(_factory.isWhiteList(msg.sender) || _factory.isWhiteList(dst), "ERR_NOT_WHITELIST");
_move(msg.sender, dst, amt);
if(dst != address(this)){
_transferLiquidity(msg.sender, dst, amt);
}
return true;
}
function transferFrom(address src, address dst, uint amt) external returns (bool) {
require(_factory.isWhiteList(msg.sender) || _factory.isWhiteList(dst), "ERR_NOT_WHITELIST");
require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_BTOKEN_BAD_CALLER");
_move(src, dst, amt);
if (msg.sender != src && _allowance[src][msg.sender] != uint256(-1)) {
_allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt);
emit Approval(msg.sender, dst, _allowance[src][msg.sender]);
}
if(dst != address(this)){
_transferLiquidity(src, dst, amt);
}
return true;
}
}
MColor.sol 28 lines
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity 0.5.12;
contract MColor {
function getColor()
external view
returns (bytes32);
}
contract MBronze is MColor {
function getColor()
external view
returns (bytes32) {
return bytes32("BRONZE");
}
}
MConst.sol 40 lines
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity 0.5.12;
import "./MColor.sol";
contract MConst is MBronze {
uint internal constant BONE = 10**18;
uint internal constant MIN_BOUND_TOKENS = 2;
uint internal constant MAX_BOUND_TOKENS = 8;
uint internal constant MIN_FEE = BONE / 10**6;
uint internal constant MAX_FEE = BONE / 10;
uint internal constant MIN_WEIGHT = BONE;
uint internal constant MAX_WEIGHT = BONE * 50;
uint internal constant MAX_TOTAL_WEIGHT = BONE * 50;
uint internal constant MIN_BALANCE = BONE / 10**12;
uint internal constant INIT_POOL_SUPPLY = BONE * 100;
uint internal constant MIN_BPOW_BASE = 1 wei;
uint internal constant MAX_BPOW_BASE = (2 * BONE) - 1 wei;
uint internal constant BPOW_PRECISION = BONE / 10**10;
uint internal constant MAX_IN_RATIO = BONE / 2;
uint internal constant MAX_OUT_RATIO = (BONE / 3) + 1 wei;
}
MToken.sol 181 lines
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity 0.5.12;
import "./MNum.sol";
// Highly opinionated token implementation
interface IERC20 {
event Approval(address indexed src, address indexed dst, uint amt);
event Transfer(address indexed src, address indexed dst, uint amt);
function totalSupply() external view returns (uint);
function balanceOf(address whom) external view returns (uint);
function allowance(address src, address dst) external view returns (uint);
function approve(address dst, uint amt) external returns (bool);
function transfer(address dst, uint amt) external returns (bool);
function transferFrom(
address src, address dst, uint amt
) external returns (bool);
}
contract MTokenBase is MNum {
mapping(address => uint) internal _balance;
mapping(address => mapping(address=>uint)) internal _allowance;
uint internal _totalSupply;
event Approval(address indexed src, address indexed dst, uint amt);
event Transfer(address indexed src, address indexed dst, uint amt);
function _mint(uint amt) internal {
_balance[address(this)] = badd(_balance[address(this)], amt);
_totalSupply = badd(_totalSupply, amt);
emit Transfer(address(0), address(this), amt);
}
function _burn(uint amt) internal {
require(_balance[address(this)] >= amt, "ERR_INSUFFICIENT_BAL");
_balance[address(this)] = bsub(_balance[address(this)], amt);
_totalSupply = bsub(_totalSupply, amt);
emit Transfer(address(this), address(0), amt);
}
function _move(address src, address dst, uint amt) internal {
require(_balance[src] >= amt, "ERR_INSUFFICIENT_BAL");
_balance[src] = bsub(_balance[src], amt);
_balance[dst] = badd(_balance[dst], amt);
emit Transfer(src, dst, amt);
}
function _push(address to, uint amt) internal {
_move(address(this), to, amt);
}
function _pull(address from, uint amt) internal {
_move(from, address(this), amt);
}
}
contract MToken is MTokenBase, IERC20 {
string private _name = "Mercurity Pool Token";
string private _symbol = "MPT";
uint8 private _decimals = 18;
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns(uint8) {
return _decimals;
}
function allowance(address src, address dst) external view returns (uint) {
return _allowance[src][dst];
}
function balanceOf(address whom) external view returns (uint) {
return _balance[whom];
}
function totalSupply() public view returns (uint) {
return _totalSupply;
}
function approve(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = amt;
emit Approval(msg.sender, dst, amt);
return true;
}
function increaseApproval(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = badd(_allowance[msg.sender][dst], amt);
emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
return true;
}
function decreaseApproval(address dst, uint amt) external returns (bool) {
uint oldValue = _allowance[msg.sender][dst];
if (amt > oldValue) {
_allowance[msg.sender][dst] = 0;
} else {
_allowance[msg.sender][dst] = bsub(oldValue, amt);
}
emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
return true;
}
function transfer(address dst, uint amt) external returns (bool) {
_move(msg.sender, dst, amt);
return true;
}
function transferFrom(address src, address dst, uint amt) external returns (bool) {
require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_BTOKEN_BAD_CALLER");
_move(src, dst, amt);
if (msg.sender != src && _allowance[src][msg.sender] != uint256(-1)) {
_allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt);
emit Approval(msg.sender, dst, _allowance[src][msg.sender]);
}
return true;
}
function safeTransfer(IERC20 token, address to , uint256 amount) internal {
bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);
bytes memory returndata = functionCall(address(token), data, "low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "not succeed");
}
}
function safeTransferFrom(IERC20 token, address from, address to , uint256 amount) internal {
bytes memory data = abi.encodeWithSelector(token.transferFrom.selector, from, to, amount);
bytes memory returndata = functionCall(address(token), data, "low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "not succeed");
}
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.call(data);// value: weiValue }(data);
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
Read Contract
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
calcInGivenOut 0xf8d6aed4 → uint256
calcOutGivenIn 0xba9530a6 → uint256
controller 0xf77c4791 → address
decimals 0x313ce567 → uint8
getBalance 0xf8b2cb4f → uint256
getColor 0x9a86139b → bytes32
getCurrentTokens 0xcc77828d → address[]
getDenormalizedWeight 0x948d8ce6 → uint256
getFinalTokens 0xbe3bbd2e → address[]
getNormalizedWeight 0xf1b8a9b7 → uint256
getNumTokens 0xcd2ed8fb → uint256
getPair 0xc1f1b1b5 → address
getSpotPrice 0x15e84af9 → uint256
getSpotPriceSansFee 0x1446a7ff → uint256
getSwapFee 0xd4cadf68 → uint256
getTotalDenormalizedWeight 0x936c3477 → uint256
isBound 0x2f37b624 → bool
isFinalized 0x8d4e4083 → bool
isPublicSwap 0xfde924f7 → bool
name 0x06fdde03 → string
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
Write Contract 20 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address dst
uint256 amt
returns: bool
bind 0xe4e1e538
address token
uint256 balance
uint256 denorm
decreaseApproval 0x66188463
address dst
uint256 amt
returns: bool
exitPool 0xb02f0b73
uint256 poolAmountIn
uint256[] minAmountsOut
exitswapPoolAmountIn 0x46ab38f1
address tokenOut
uint256 poolAmountIn
uint256 minAmountOut
returns: uint256
finalize 0x0553e156
address beneficiary
uint256 fixPoolSupply
gulp 0x8c28cbe8
address token
increaseApproval 0xd73dd623
address dst
uint256 amt
returns: bool
joinPool 0x8a5c57df
address beneficiary
uint256 poolAmountOut
uint256[] maxAmountsIn
joinswapExternAmountIn 0xc1762b15
address beneficiary
address tokenIn
uint256 tokenAmountIn
uint256 minPoolAmountOut
returns: uint256
rebind 0x3fdddaa2
address token
uint256 balance
uint256 denorm
setController 0x92eefe9b
address manager
setPair 0x8187f516
address pair
setSwapFee 0x34e19907
uint256 swapFee
swapExactAmountIn 0x255de7bb
address user
address tokenIn
uint256 tokenAmountIn
address tokenOut
uint256 minAmountOut
uint256 maxPrice
returns: uint256, uint256
swapExactAmountOut 0x4d128b77
address user
address tokenIn
uint256 maxAmountIn
address tokenOut
uint256 tokenAmountOut
uint256 maxPrice
returns: uint256, uint256
transfer 0xa9059cbb
address dst
uint256 amt
returns: bool
transferFrom 0x23b872dd
address src
address dst
uint256 amt
returns: bool
unbind 0xcf5e7bd3
address token
updatePairGPInfo 0x5e7d6c3d
address[] gps
uint256[] shares
Token Balances (1) $22.62
View Transfers →| Token | Balance | Price | Value |
|---|---|---|---|
| WETH | 0.0115 | $1,966.72 | $22.62 |
Recent Transactions
This address has 1 on-chain transactions, but only 1.7% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →