Address Contract Partially Verified
Address
0x95C4B6C7CfF608c0CA048df8b81a484aA377172B
Balance
0 ETH
Nonce
1
Code Size
22537 bytes
Creator
0x9424B141...76Bd at tx 0x6b47a1da...60a30a
Indexed Transactions
0
Contract Bytecode
22537 bytes
0x608060405234801561001057600080fd5b50600436106103eb5760003560e01c80638d4e40831161021a578063bc694ea211610135578063d73dd623116100c8578063ec09302111610097578063f8b2cb4f1161007c578063f8b2cb4f14610cac578063f8d6aed414610cd2578063fde924f714610d0d576103eb565b8063ec09302114610c7e578063f1b8a9b714610c86576103eb565b8063d73dd62314610bf2578063dd62ed3e14610c1e578063e4a28a52146104f1578063e4e1e53814610c4c576103eb565b8063cc77828d11610104578063cc77828d14610bb4578063cd2ed8fb14610bbc578063cf5e7bd314610bc4578063d4cadf6814610bea576103eb565b8063bc694ea214610b4c578063be3bbd2e14610b54578063c36596a614610565578063c6580d1214610bac576103eb565b8063a221ee49116101ad578063b7b800a41161017c578063b7b800a414610af9578063ba019dab14610b01578063ba9530a614610b09578063bc063e1a14610b44576103eb565b8063a221ee4914610a19578063a9059cbb14610a4e578063b02f0b7314610a7a578063b0e0d13614610af1576103eb565b8063948d8ce6116101e9578063948d8ce6146109db57806395d89b4114610a01578063992e2a9214610a095780639a86139b14610a11576103eb565b80638d4e40831461099d57806392eefe9b146109a5578063936c3477146109cb5780639381cd2b146109d3576103eb565b806349b595521161030a57806376c7a3c71161029d5780638656b6531161026c5780638656b653146108f9578063867378c514610934578063892980121461093c5780638c28cbe814610977576103eb565b806376c7a3c71461081d5780637c5e9ea4146108255780638201aa3f1461087e57806382f652ad146108be576103eb565b80635db34277116102d95780635db342771461076757806366188463146107995780636d06dfa0146107c557806370a08231146107f7576103eb565b806349b595521461068e5780634bb278f3146106ad5780634f69c0d4146106b55780635c1bbaf71461072c576103eb565b8063218b538211610382578063313ce56711610351578063313ce567146105ed57806334e199071461060b5780633fdddaa21461062a57806346ab38f11461065c576103eb565b8063218b53821461056557806323b872dd1461056d5780632f37b624146105a35780633018205f146105c9576103eb565b80631446a7ff116103be5780631446a7ff146104f957806315e84af91461052757806318160ddd14610555578063189d00ca1461055d576103eb565b806302c96748146103f057806306fdde0314610434578063095ea7b3146104b157806309a3bbe4146104f1575b600080fd5b6104226004803603606081101561040657600080fd5b506001600160a01b038135169060208101359060400135610d15565b60408051918252519081900360200190f35b61043c611081565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561047657818101518382015260200161045e565b50505050905090810190601f1680156104a35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104dd600480360360408110156104c757600080fd5b506001600160a01b038135169060200135611117565b604080519115158252519081900360200190f35b61042261117e565b6104226004803603604081101561050f57600080fd5b506001600160a01b038135811691602001351661118b565b6104226004803603604081101561053d57600080fd5b506001600160a01b03813581169160200135166112e0565b61042261142c565b610422611432565b610422611446565b6104dd6004803603606081101561058357600080fd5b506001600160a01b03813581169160208101359091169060400135611452565b6104dd600480360360208110156105b957600080fd5b50356001600160a01b03166115c6565b6105d16115e4565b604080516001600160a01b039092168252519081900360200190f35b6105f5611642565b6040805160ff9092168252519081900360200190f35b6106286004803603602081101561062157600080fd5b503561164b565b005b6106286004803603606081101561064057600080fd5b506001600160a01b03813516906020810135906040013561186c565b6104226004803603606081101561067257600080fd5b506001600160a01b038135169060208101359060400135611cae565b610628600480360360208110156106a457600080fd5b50351515611fb9565b610628612157565b610628600480360360408110156106cb57600080fd5b813591908101906040810160208201356401000000008111156106ed57600080fd5b8201836020820111156106ff57600080fd5b8035906020019184602083028401116401000000008311171561072157600080fd5b509092509050612378565b610422600480360360c081101561074257600080fd5b5080359060208101359060408101359060608101359060808101359060a00135612671565b6104226004803603606081101561077d57600080fd5b506001600160a01b038135169060208101359060400135612729565b6104dd600480360360408110156107af57600080fd5b506001600160a01b038135169060200135612a19565b610422600480360360608110156107db57600080fd5b506001600160a01b038135169060208101359060400135612b03565b6104226004803603602081101561080d57600080fd5b50356001600160a01b0316612e21565b610422612e3c565b610865600480360360a081101561083b57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060800135612e4e565b6040805192835260208301919091528051918290030190f35b610865600480360360a081101561089457600080fd5b506001600160a01b038135811691602081013591604082013516906060810135906080013561333f565b610422600480360360c08110156108d457600080fd5b5080359060208101359060408101359060608101359060808101359060a00135613818565b610422600480360360c081101561090f57600080fd5b5080359060208101359060408101359060608101359060808101359060a001356138d7565b610422613978565b610422600480360360c081101561095257600080fd5b5080359060208101359060408101359060608101359060808101359060a0013561398c565b6106286004803603602081101561098d57600080fd5b50356001600160a01b0316613a3c565b6104dd613c09565b610628600480360360208110156109bb57600080fd5b50356001600160a01b0316613c12565b610422613d5d565b610422613db2565b610422600480360360208110156109f157600080fd5b50356001600160a01b0316613dbf565b61043c613e89565b610422613eea565b610422613ef6565b610422600480360360a0811015610a2f57600080fd5b5080359060208101359060408101359060608101359060800135613f1a565b6104dd60048036036040811015610a6457600080fd5b506001600160a01b038135169060200135613f7f565b61062860048036036040811015610a9057600080fd5b81359190810190604081016020820135640100000000811115610ab257600080fd5b820183602082011115610ac457600080fd5b80359060200191846020830284011164010000000083111715610ae657600080fd5b509092509050613f95565b6104226142dc565b6104226142e1565b6104226142e6565b610422600480360360c0811015610b1f57600080fd5b5080359060208101359060408101359060608101359060808101359060a001356142eb565b61042261436c565b61042261437c565b610b5c614388565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610b98578181015183820152602001610b80565b505050509050019250505060405180910390f35b610422614480565b610b5c614485565b6104226144d3565b61062860048036036020811015610bda57600080fd5b50356001600160a01b03166144d9565b610422614868565b6104dd60048036036040811015610c0857600080fd5b506001600160a01b0381351690602001356148bd565b61042260048036036040811015610c3457600080fd5b506001600160a01b0381358116916020013516614950565b61062860048036036060811015610c6257600080fd5b506001600160a01b03813516906020810135906040013561497b565b610422614bff565b61042260048036036020811015610c9c57600080fd5b50356001600160a01b0316614c0f565b61042260048036036020811015610cc257600080fd5b50356001600160a01b0316614ceb565b610422600480360360c0811015610ce857600080fd5b5080359060208101359060408101359060608101359060808101359060a00135614db5565b6104dd614e38565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615610dc3576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16610e1d576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16610e7a576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a60205260409020600390810154610eaf91670de0b6b3a76400005b04600101614e48565b831115610f03576040805162461bcd60e51b815260206004820152601160248201527f4552525f4d41585f4f55545f524154494f000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754610f3d94939291908990613818565b915081610f83576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b82821115610fc7576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b610fd5816003015485614f2b565b60038201556000610fe68382614e48565b6040805187815290519192506001600160a01b0388169133917fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed919081900360200190a36110343384614f99565b6110466110418483614f2b565b614fa7565b600554611062906201000090046001600160a01b031682614fb3565b61106d863387614fbd565b50506005805461ff00191690559392505050565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561110d5780601f106110e25761010080835404028352916020019161110d565b820191906000526020600020905b8154815290600101906020018083116110f057829003601f168201915b5050505050905090565b3360008181526001602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b6802b5e3af16b188000081565b600554600090610100900460ff16156111d9576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff16611236576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16611293576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600a602052604080822092851682528120600380840154600280860154928401549084015493946112d79492939290613f1a565b95945050505050565b600554600090610100900460ff161561132e576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff1661138b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff166113e8576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600a60205260408082209285168252902060038083015460028085015492840154908401546007546112d794929190613f1a565b60025490565b6402540be400670de0b6b3a76400005b0481565b670de0b6b3a764000081565b6000336001600160a01b038516148061148e57506001600160a01b03841660009081526001602090815260408083203384529091529020548211155b6114df576040805162461bcd60e51b815260206004820152601560248201527f4552525f42544f4b454e5f4241445f43414c4c45520000000000000000000000604482015290519081900360640190fd5b6114ea8484846150af565b336001600160a01b0385161480159061152857506001600160a01b038416600090815260016020908152604080832033845290915290205460001914155b156115bc576001600160a01b038416600090815260016020908152604080832033845290915290205461155b9083614f2b565b6001600160a01b03858116600090815260016020908152604080832033808552908352928190208590558051948552519287169391927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a35b5060019392505050565b6001600160a01b03166000908152600a602052604090205460ff1690565b600554600090610100900460ff1615611632576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b506006546001600160a01b031690565b60055460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156116f7576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1615611751576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6006546001600160a01b031633146117a5576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b64e8d4a510008110156117ff576040805162461bcd60e51b815260206004820152600b60248201527f4552525f4d494e5f464545000000000000000000000000000000000000000000604482015290519081900360640190fd5b67016345785d8a000081111561185c576040805162461bcd60e51b815260206004820152600b60248201527f4552525f4d41585f464545000000000000000000000000000000000000000000604482015290519081900360640190fd5b6007556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611918576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b039091161461197d576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff166119da576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60085460ff1615611a25576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b670de0b6b3a7640000811015611a82576040805162461bcd60e51b815260206004820152600e60248201527f4552525f4d494e5f574549474854000000000000000000000000000000000000604482015290519081900360640190fd5b6802b5e3af16b1880000811115611ae0576040805162461bcd60e51b815260206004820152600e60248201527f4552525f4d41585f574549474854000000000000000000000000000000000000604482015290519081900360640190fd5b620f4240821015611b38576040805162461bcd60e51b815260206004820152600f60248201527f4552525f4d494e5f42414c414e43450000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090206002015480821115611bd857611b71600b54611b6c8484614f2b565b6151c8565b600b8190556802b5e3af16b18800001015611bd3576040805162461bcd60e51b815260206004820152601460248201527f4552525f4d41585f544f54414c5f574549474854000000000000000000000000604482015290519081900360640190fd5b611bf9565b80821015611bf957611bf5600b54611bf08385614f2b565b614f2b565b600b555b6001600160a01b0384166000908152600a602052604090206002810183905560030180549084905580841115611c4257611c3d8533611c388785614f2b565b615222565b611c9c565b80841015611c9c576000611c568286614f2b565b90506000611c65826000614e48565b9050611c7b8733611c768585614f2b565b614fbd565b600554611c999088906201000090046001600160a01b031683614fbd565b50505b50506005805461ff0019169055505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611d5c576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16611db6576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16611e13576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754611e4d9493929190899061398c565b915082821015611e94576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a60205260409020600390810154611ec491670de0b6b3a7640000610ea6565b821115611f18576040805162461bcd60e51b815260206004820152601160248201527f4552525f4d41585f4f55545f524154494f000000000000000000000000000000604482015290519081900360640190fd5b611f26816003015483614f2b565b60038201556000611f378582614e48565b6040805185815290519192506001600160a01b0388169133917fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed919081900360200190a3611f853386614f99565b611f926110418683614f2b565b600554611fae906201000090046001600160a01b031682614fb3565b61106d863385614fbd565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612065576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16156120bf576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6006546001600160a01b03163314612113576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60068054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9092169190911790556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612203576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b0390911614612268576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60085460ff16156122b3576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6009546002111561230b576040805162461bcd60e51b815260206004820152600e60248201527f4552525f4d494e5f544f4b454e53000000000000000000000000000000000000604482015290519081900360640190fd5b6008805460ff19166001179055600680547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b17905561235868056bc75e2d63100000615294565b61236b3368056bc75e2d63100000614fb3565b6005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612424576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1661247e576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b600061248861142c565b90506000612496858361529d565b9050806124dc576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b60005b60095481101561265d576000600982815481106124f857fe5b60009182526020808320909101546001600160a01b0316808352600a90915260408220600301549092509061252d8583614e48565b905080612573576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b87878581811061257f57fe5b905060200201358111156125c9576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a60205260409020600301546125ef90826151c8565b6001600160a01b0384166000818152600a60209081526040918290206003019390935580518481529051919233927f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9281900390910190a3612652833383615222565b5050506001016124df565b5061266785615294565b611c9c3386614fb3565b60008061267e878661529d565b9050600061268c87866151c8565b9050600061269a828961529d565b905060006126b0670de0b6b3a76400008561529d565b905060006126be83836153d0565b905060006126cc828e614e48565b905060006126da828f614f2b565b905060006126f96126f3670de0b6b3a76400008a614f2b565b8b614e48565b905061271682612711670de0b6b3a764000084614f2b565b61529d565b9f9e505050505050505050505050505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156127d7576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16612831576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff1661288e576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a60205260409020600301546128c0906002670de0b6b3a76400005b04614e48565b831115612914576040805162461bcd60e51b815260206004820152601060248201527f4552525f4d41585f494e5f524154494f00000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b5460075461294e949392919089906138d7565b915082821015612995576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6129a38160030154856151c8565b60038201556040805185815290516001600160a01b0387169133917f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9181900360200190a36129f182615294565b6129fb3383614fb3565b612a06853386615222565b506005805461ff00191690559392505050565b3360009081526001602090815260408083206001600160a01b038616845290915281205480831115612a6e573360009081526001602090815260408083206001600160a01b0388168452909152812055612a9d565b612a788184614f2b565b3360009081526001602090815260408083206001600160a01b03891684529091529020555b3360008181526001602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612bb1576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16612c0b576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16612c68576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754612ca294939291908990612671565b915081612ce8576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b82821115612d2c576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a6020526040902060030154612d5c906002670de0b6b3a76400006128ba565b821115612db0576040805162461bcd60e51b815260206004820152601060248201527f4552525f4d41585f494e5f524154494f00000000000000000000000000000000604482015290519081900360640190fd5b612dbe8160030154836151c8565b60038201556040805183815290516001600160a01b0387169133917f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9181900360200190a3612e0c84615294565b612e163385614fb3565b612a06853384615222565b6001600160a01b031660009081526020819052604090205490565b620f4240670de0b6b3a7640000611442565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612eeb576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600a602052604090205460ff16612f57576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a602052604090205460ff16612fb4576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600654600160a01b900460ff16613012576040805162461bcd60e51b815260206004820152601360248201527f4552525f535741505f4e4f545f5055424c494300000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038088166000908152600a60205260408082209288168252902060038082015461304b91670de0b6b3a7640000610ea6565b86111561309f576040805162461bcd60e51b815260206004820152601160248201527f4552525f4d41585f4f55545f524154494f000000000000000000000000000000604482015290519081900360640190fd5b60006130c08360030154846002015484600301548560020154600754613f1a565b905085811115613117576040805162461bcd60e51b815260206004820152601360248201527f4552525f4241445f4c494d49545f505249434500000000000000000000000000604482015290519081900360640190fd5b61313783600301548460020154846003015485600201548b600754614db5565b94508885111561317d576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b61318b8360030154866151c8565b83600301819055506131a1826003015488614f2b565b6003808401829055840154600280860154908501546007546131c4949190613f1a565b93508084101561320d576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b85841115613262576040805162461bcd60e51b815260206004820152600f60248201527f4552525f4c494d49545f50524943450000000000000000000000000000000000604482015290519081900360640190fd5b61326c858861529d565b8111156132b2576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b876001600160a01b03168a6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378888b604051808381526020018281526020019250505060405180910390a461331a8a3387615222565b613325883389614fbd565b5050506005805461ff001916905590969095509350505050565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156133dc576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600a602052604090205460ff16613448576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a602052604090205460ff166134a5576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600654600160a01b900460ff16613503576040805162461bcd60e51b815260206004820152601360248201527f4552525f535741505f4e4f545f5055424c494300000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038088166000908152600a602052604080822092881682529020600382015461353d906002670de0b6b3a76400006128ba565b881115613591576040805162461bcd60e51b815260206004820152601060248201527f4552525f4d41585f494e5f524154494f00000000000000000000000000000000604482015290519081900360640190fd5b60006135b28360030154846002015484600301548560020154600754613f1a565b905085811115613609576040805162461bcd60e51b815260206004820152601360248201527f4552525f4241445f4c494d49545f505249434500000000000000000000000000604482015290519081900360640190fd5b61362983600301548460020154846003015485600201548d6007546142eb565b945086851015613670576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b61367e83600301548a6151c8565b8360030181905550613694826003015486614f2b565b6003808401829055840154600280860154908501546007546136b7949190613f1a565b935080841015613700576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b85841115613755576040805162461bcd60e51b815260206004820152600f60248201527f4552525f4c494d49545f50524943450000000000000000000000000000000000604482015290519081900360640190fd5b61375f898661529d565b8111156137a5576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b876001600160a01b03168a6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d433788c89604051808381526020018281526020019250505060405180910390a461380d8a338b615222565b613325883387614fbd565b600080613825878661529d565b9050600061383b670de0b6b3a764000083614f2b565b905060006138498286614e48565b9050600061386387612711670de0b6b3a764000085614f2b565b905060006138718c83614f2b565b9050600061387f828e61529d565b9050600061388d82886153d0565b9050600061389b828e614e48565b905060006138a98e83614f2b565b90506138c281612711670de0b6b3a76400006000614f2b565b99505050505050505050509695505050505050565b6000806138e4878661529d565b905060006139036138fd670de0b6b3a764000084614f2b565b85614e48565b905060006139228661391d670de0b6b3a764000085614f2b565b614e48565b905060006139308b836151c8565b9050600061393e828d61529d565b9050600061394c82876153d0565b9050600061395a828d614e48565b9050613966818d614f2b565b9e9d5050505050505050505050505050565b64e8d4a51000670de0b6b3a7640000611442565b600080613999878661529d565b905060006139b48561391d670de0b6b3a76400006000614f2b565b905060006139c28883614f2b565b905060006139d0828a61529d565b905060006139ef826139ea670de0b6b3a76400008861529d565b6153d0565b905060006139fd828e614e48565b90506000613a0b8e83614f2b565b90506000613a246126f3670de0b6b3a76400008a614f2b565b90506127168261391d670de0b6b3a764000084614f2b565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613ae8576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0381166000908152600a602052604090205460ff16613b54576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b158015613bb357600080fd5b505afa158015613bc7573d6000803e3d6000fd5b505050506040513d6020811015613bdd57600080fd5b50516001600160a01b039091166000908152600a60205260409020600301556005805461ff0019169055565b60085460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613cbe576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b0390911614613d23576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6006805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790556005805461ff0019169055565b600554600090610100900460ff1615613dab576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b50600b5490565b68056bc75e2d6310000081565b600554600090610100900460ff1615613e0d576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16613e6a576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600a602052604090206002015490565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561110d5780601f106110e25761010080835404028352916020019161110d565b6704a03ce68d21555681565b7f42524f4e5a45000000000000000000000000000000000000000000000000000090565b600080613f27878761529d565b90506000613f35868661529d565b90506000613f43838361529d565b90506000613f65670de0b6b3a7640000612711670de0b6b3a764000089614f2b565b9050613f718282614e48565b9a9950505050505050505050565b6000613f8c3384846150af565b50600192915050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615614041576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1661409b576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b60006140a561142c565b905060006140b4856000614e48565b905060006140c28683614f2b565b905060006140d0828561529d565b905080614116576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b6141203388614f99565b60055461413c906201000090046001600160a01b031684614fb3565b61414582614fa7565b60005b6009548110156142c75760006009828154811061416157fe5b60009182526020808320909101546001600160a01b0316808352600a9091526040822060030154909250906141968583614e48565b9050806141dc576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b8989858181106141e857fe5b90506020020135811015614233576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a60205260409020600301546142599082614f2b565b6001600160a01b0384166000818152600a60209081526040918290206003019390935580518481529051919233927fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9281900390910190a36142bc833383614fbd565b505050600101614148565b50506005805461ff0019169055505050505050565b600881565b600281565b600181565b6000806142f8878661529d565b9050600061430e670de0b6b3a764000085614f2b565b905061431a8582614e48565b9050600061432c8a6127118c856151c8565b9050600061433a82856153d0565b90506000614350670de0b6b3a764000083614f2b565b905061435c8a82614e48565b9c9b505050505050505050505050565b600a670de0b6b3a7640000611442565b671bc16d674ec7ffff81565b600554606090610100900460ff16156143d6576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60085460ff16614421576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b600980548060200260200160405190810160405280929190818152602001828054801561110d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311614459575050505050905090565b600081565b600554606090610100900460ff1615614421576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60095490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615614585576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b03909116146145ea576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff16614647576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60085460ff1615614692576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a6020526040812060030154906146b98282614e48565b600b546001600160a01b0385166000908152600a60205260409020600201549192506146e491614f2b565b600b556001600160a01b0383166000908152600a602052604090206001015460098054600019810191908290811061471857fe5b600091825260209091200154600980546001600160a01b03909216918490811061473e57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600a60006009858154811061477e57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206001015560098054806147b157fe5b600082815260208082206000199084018101805473ffffffffffffffffffffffffffffffffffffffff1916905590920190925560408051608081018252838152808301848152818301858152606083018681526001600160a01b038c168752600a909552929094209051815460ff1916901515178155925160018401555160028301555160039091015561484a8533611c768787614f2b565b600554611c9c9086906201000090046001600160a01b031685614fbd565b600554600090610100900460ff16156148b6576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b5060075490565b3360009081526001602090815260408083206001600160a01b03861684529091528120546148eb90836151c8565b3360008181526001602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26006546001600160a01b03163314614a30576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff1615614a9e576040805162461bcd60e51b815260206004820152600c60248201527f4552525f49535f424f554e440000000000000000000000000000000000000000604482015290519081900360640190fd5b60085460ff1615614ae9576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b600954600811614b40576040805162461bcd60e51b815260206004820152600e60248201527f4552525f4d41585f544f4b454e53000000000000000000000000000000000000604482015290519081900360640190fd5b6040805160808101825260018082526009805460208085019182526000858701818152606087018281526001600160a01b038c16808452600a9094529782209651875460ff1916901515178755925186860155915160028601559451600390940193909355805491820181559091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af01805473ffffffffffffffffffffffffffffffffffffffff19169091179055614bfa83838361186c565b505050565b6002670de0b6b3a7640000611442565b600554600090610100900460ff1615614c5d576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16614cba576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a6020526040902060020154600b54614ce490829061529d565b9392505050565b600554600090610100900460ff1615614d39576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16614d96576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600a602052604090206003015490565b600080614dc2858861529d565b90506000614dd08786614f2b565b90506000614dde888361529d565b90506000614dec82856153d0565b9050614e0081670de0b6b3a7640000614f2b565b9050614e14670de0b6b3a764000087614f2b565b9450614e29614e238c83614e48565b8661529d565b9b9a5050505050505050505050565b600654600160a01b900460ff1690565b6000828202831580614e62575082848281614e5f57fe5b04145b614eb3576040805162461bcd60e51b815260206004820152601060248201527f4552525f4d554c5f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b6706f05b59d3b20000810181811015614f13576040805162461bcd60e51b815260206004820152601060248201527f4552525f4d554c5f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b6000670de0b6b3a7640000825b049695505050505050565b6000806000614f3a85856154ed565b915091508015614f91576040805162461bcd60e51b815260206004820152601160248201527f4552525f5355425f554e444552464c4f57000000000000000000000000000000604482015290519081900360640190fd5b509392505050565b614fa38282615512565b5050565b614fb08161551d565b50565b614fa382826155f6565b604080517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015260248201849052915160009286169163a9059cbb91604480830192602092919082900301818787803b15801561502957600080fd5b505af115801561503d573d6000803e3d6000fd5b505050506040513d602081101561505357600080fd5b50519050806150a9576040805162461bcd60e51b815260206004820152600f60248201527f4552525f45524332305f46414c53450000000000000000000000000000000000604482015290519081900360640190fd5b50505050565b6001600160a01b03831660009081526020819052604090205481111561511c576040805162461bcd60e51b815260206004820152601460248201527f4552525f494e53554646494349454e545f42414c000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03831660009081526020819052604090205461513f9082614f2b565b6001600160a01b03808516600090815260208190526040808220939093559084168152205461516e90826151c8565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600082820183811015614ce4576040805162461bcd60e51b815260206004820152601060248201527f4552525f4144445f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301523060248301526044820184905291516000928616916323b872dd91606480830192602092919082900301818787803b15801561502957600080fd5b614fb081615601565b6000816152f1576040805162461bcd60e51b815260206004820152600c60248201527f4552525f4449565f5a45524f0000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a764000083028315806153195750670de0b6b3a764000084828161531657fe5b04145b61536a576040805162461bcd60e51b815260206004820152601060248201527f4552525f4449565f494e5445524e414c00000000000000000000000000000000604482015290519081900360640190fd5b600283048101818110156153c5576040805162461bcd60e51b815260206004820152601060248201527f4552525f4449565f494e5445524e414c00000000000000000000000000000000604482015290519081900360640190fd5b6000848281614f2057fe5b60006001831015615428576040805162461bcd60e51b815260206004820152601560248201527f4552525f42504f575f424153455f544f4f5f4c4f570000000000000000000000604482015290519081900360640190fd5b671bc16d674ec7ffff831115615485576040805162461bcd60e51b815260206004820152601660248201527f4552525f42504f575f424153455f544f4f5f4849474800000000000000000000604482015290519081900360640190fd5b600061549083615676565b9050600061549e8483614f2b565b905060006154b4866154af85615691565b61569f565b9050816154c5579250611178915050565b60006154d687846305f5e1006156f6565b90506154e28282614e48565b979650505050505050565b600080828410615503575050808203600061550b565b505081810360015b9250929050565b614fa38230836150af565b30600090815260208190526040902054811115615581576040805162461bcd60e51b815260206004820152601460248201527f4552525f494e53554646494349454e545f42414c000000000000000000000000604482015290519081900360640190fd5b3060009081526020819052604090205461559b9082614f2b565b306000908152602081905260409020556002546155b89082614f2b565b60025560408051828152905160009130917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b614fa33083836150af565b3060009081526020819052604090205461561b90826151c8565b3060009081526020819052604090205560025461563890826151c8565b60025560408051828152905130916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b6000670de0b6b3a764000061568a83615691565b0292915050565b670de0b6b3a7640000900490565b600080600283066156b857670de0b6b3a76400006156ba565b835b90506002830492505b8215614ce4576156d38485614e48565b935060028306156156eb576156e88185614e48565b90505b6002830492506156c3565b600082818061570d87670de0b6b3a76400006154ed565b9092509050670de0b6b3a764000080600060015b8884106157c5576000670de0b6b3a7640000820290506000806157558a61575085670de0b6b3a7640000614f2b565b6154ed565b915091506157678761391d848c614e48565b9650615773878461529d565b965086615782575050506157c5565b871561578c579315935b8015615796579315935b84156157ad576157a68688614f2b565b95506157ba565b6157b786886151c8565b95505b505050600101615721565b5090999850505050505050505056fea265627a7a7231582008be3d1ae8df326becfb0d7fa15f3da56c3488a4813f666aa4154f7433e2a31e64736f6c634300050c0032
Verified Source Code Partial Match
Compiler: v0.5.12+commit.7709ece9
EVM: petersburg
Optimization: Yes (2000 runs)
BNum.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 "./BConst.sol";
contract BNum is BConst {
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;
}
}
BMath.sol 271 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 "./BNum.sol";
contract BMath is BBronze, BConst, BNum {
/**********************************************************************************************
// 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
)
public 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
)
public 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;
}
/**********************************************************************************************
// calcSingleInGivenPoolOut //
// tAi = tokenAmountIn //(pS + pAo)\ / 1 \\ //
// pS = poolSupply || --------- | ^ | --------- || * bI - bI //
// pAo = poolAmountOut \\ pS / \(wI / tW)// //
// bI = balanceIn tAi = -------------------------------------------- //
// wI = weightIn / wI \ //
// tW = totalWeight | 1 - ---- | * sF //
// sF = swapFee \ tW / //
**********************************************************************************************/
function calcSingleInGivenPoolOut(
uint tokenBalanceIn,
uint tokenWeightIn,
uint poolSupply,
uint totalWeight,
uint poolAmountOut,
uint swapFee
)
public pure
returns (uint tokenAmountIn)
{
uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
uint newPoolSupply = badd(poolSupply, poolAmountOut);
uint poolRatio = bdiv(newPoolSupply, poolSupply);
//uint newBalTi = poolRatio^(1/weightTi) * balTi;
uint boo = bdiv(BONE, normalizedWeight);
uint tokenInRatio = bpow(poolRatio, boo);
uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn);
uint tokenAmountInAfterFee = bsub(newTokenBalanceIn, tokenBalanceIn);
// Do reverse order of fees charged in joinswap_ExternAmountIn, this way
// ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```
//uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;
uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);
tokenAmountIn = bdiv(tokenAmountInAfterFee, bsub(BONE, zar));
return tokenAmountIn;
}
/**********************************************************************************************
// 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
)
public 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, bsub(BONE, EXIT_FEE));
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;
}
/**********************************************************************************************
// calcPoolInGivenSingleOut //
// pAi = poolAmountIn // / tAo \\ / wO \ \ //
// bO = tokenBalanceOut // | bO - -------------------------- |\ | ---- | \ //
// tAo = tokenAmountOut pS - || \ 1 - ((1 - (tO / tW)) * sF)/ | ^ \ tW / * pS | //
// ps = poolSupply \\ -----------------------------------/ / //
// wO = tokenWeightOut pAi = \\ bO / / //
// tW = totalWeight ------------------------------------------------------------- //
// sF = swapFee ( 1 - eF ) //
// eF = exitFee //
**********************************************************************************************/
function calcPoolInGivenSingleOut(
uint tokenBalanceOut,
uint tokenWeightOut,
uint poolSupply,
uint totalWeight,
uint tokenAmountOut,
uint swapFee
)
public pure
returns (uint poolAmountIn)
{
// charge swap fee on the output token side
uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
//uint tAoBeforeSwapFee = tAo / (1 - (1-weightTo) * swapFee) ;
uint zoo = bsub(BONE, normalizedWeight);
uint zar = bmul(zoo, swapFee);
uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BONE, zar));
uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);
uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);
//uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;
uint poolRatio = bpow(tokenOutRatio, normalizedWeight);
uint newPoolSupply = bmul(poolRatio, poolSupply);
uint poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);
// charge exit fee on the pool token side
// pAi = pAiAfterExitFee/(1-exitFee)
poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BONE, EXIT_FEE));
return poolAmountIn;
}
}
BPool.sol 739 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 "./BToken.sol";
import "./BMath.sol";
contract BPool is BBronze, BToken, BMath {
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;
address private _factory; // BFactory address to push token exitFee to
address private _controller; // has CONTROL role
bool private _publicSwap; // true if PUBLIC can call SWAP functions
// `setSwapFee` and `finalize` require CONTROL
// `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`
uint private _swapFee;
bool private _finalized;
address[] private _tokens;
mapping(address=>Record) private _records;
uint private _totalWeight;
constructor() public {
_controller = msg.sender;
_factory = 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 getController()
external view
_viewlock_
returns (address)
{
return _controller;
}
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 setPublicSwap(bool public_)
external
_logs_
_lock_
{
require(!_finalized, "ERR_IS_FINALIZED");
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
_publicSwap = public_;
}
function finalize()
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;
_mintPoolShare(INIT_POOL_SUPPLY);
_pushPoolShare(msg.sender, INIT_POOL_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) {
// In this case liquidity is being withdrawn, so charge EXIT_FEE
uint tokenBalanceWithdrawn = bsub(oldBalance, balance);
uint tokenExitFee = bmul(tokenBalanceWithdrawn, EXIT_FEE);
_pushUnderlying(token, msg.sender, bsub(tokenBalanceWithdrawn, tokenExitFee));
_pushUnderlying(token, _factory, tokenExitFee);
}
}
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;
uint tokenExitFee = bmul(tokenBalance, EXIT_FEE);
_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, bsub(tokenBalance, tokenExitFee));
_pushUnderlying(token, _factory, tokenExitFee);
}
// 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(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(msg.sender, poolAmountOut);
}
function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut)
external
_logs_
_lock_
{
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = totalSupply();
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
uint pAiAfterExitFee = bsub(poolAmountIn, exitFee);
uint ratio = bdiv(pAiAfterExitFee, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
_pullPoolShare(msg.sender, poolAmountIn);
_pushPoolShare(_factory, exitFee);
_burnPoolShare(pAiAfterExitFee);
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);
}
}
function swapExactAmountIn(
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");
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");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
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);
return (tokenAmountOut, spotPriceAfter);
}
function swapExactAmountOut(
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");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
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);
return (tokenAmountIn, spotPriceAfter);
}
function joinswapExternAmountIn(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(msg.sender, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
return poolAmountOut;
}
function joinswapPoolAmountOut(address tokenIn, uint poolAmountOut, uint maxAmountIn)
external
_logs_
_lock_
returns (uint tokenAmountIn)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
tokenAmountIn = calcSingleInGivenPoolOut(
inRecord.balance,
inRecord.denorm,
_totalSupply,
_totalWeight,
poolAmountOut,
_swapFee
);
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountIn, "ERR_LIMIT_IN");
require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
return tokenAmountIn;
}
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);
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(bsub(poolAmountIn, exitFee));
_pushPoolShare(_factory, exitFee);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
return tokenAmountOut;
}
function exitswapExternAmountOut(address tokenOut, uint tokenAmountOut, uint maxPoolAmountIn)
external
_logs_
_lock_
returns (uint poolAmountIn)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO");
Record storage outRecord = _records[tokenOut];
poolAmountIn = calcPoolInGivenSingleOut(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountOut,
_swapFee
);
require(poolAmountIn != 0, "ERR_MATH_APPROX");
require(poolAmountIn <= maxPoolAmountIn, "ERR_LIMIT_IN");
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(bsub(poolAmountIn, exitFee));
_pushPoolShare(_factory, exitFee);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
return poolAmountIn;
}
// ==
// '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
{
bool xfer = IERC20(erc20).transferFrom(from, address(this), amount);
require(xfer, "ERR_ERC20_FALSE");
}
function _pushUnderlying(address erc20, address to, uint amount)
internal
{
bool xfer = IERC20(erc20).transfer(to, amount);
require(xfer, "ERR_ERC20_FALSE");
}
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);
}
}
BColor.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 BColor {
function getColor()
external view
returns (bytes32);
}
contract BBronze is BColor {
function getColor()
external view
returns (bytes32) {
return bytes32("BRONZE");
}
}
BConst.sol 41 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 "./BColor.sol";
contract BConst is BBronze {
uint public constant BONE = 10**18;
uint public constant MIN_BOUND_TOKENS = 2;
uint public constant MAX_BOUND_TOKENS = 8;
uint public constant MIN_FEE = BONE / 10**6;
uint public constant MAX_FEE = BONE / 10;
uint public constant EXIT_FEE = 0;
uint public constant MIN_WEIGHT = BONE;
uint public constant MAX_WEIGHT = BONE * 50;
uint public constant MAX_TOTAL_WEIGHT = BONE * 50;
uint public constant MIN_BALANCE = BONE / 10**12;
uint public constant INIT_POOL_SUPPLY = BONE * 100;
uint public constant MIN_BPOW_BASE = 1 wei;
uint public constant MAX_BPOW_BASE = (2 * BONE) - 1 wei;
uint public constant BPOW_PRECISION = BONE / 10**10;
uint public constant MAX_IN_RATIO = BONE / 2;
uint public constant MAX_OUT_RATIO = (BONE / 3) + 1 wei;
}
BToken.sol 140 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 "./BNum.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 BTokenBase is BNum {
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 BToken is BTokenBase, IERC20 {
string private _name = "Balancer Pool Token";
string private _symbol = "BPT";
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;
}
}
Read Contract
BONE 0xc36596a6 → uint256
BPOW_PRECISION 0x189d00ca → uint256
EXIT_FEE 0xc6580d12 → uint256
INIT_POOL_SUPPLY 0x9381cd2b → uint256
MAX_BOUND_TOKENS 0xb0e0d136 → uint256
MAX_BPOW_BASE 0xbc694ea2 → uint256
MAX_FEE 0xbc063e1a → uint256
MAX_IN_RATIO 0xec093021 → uint256
MAX_OUT_RATIO 0x992e2a92 → uint256
MAX_TOTAL_WEIGHT 0x09a3bbe4 → uint256
MAX_WEIGHT 0xe4a28a52 → uint256
MIN_BALANCE 0x867378c5 → uint256
MIN_BOUND_TOKENS 0xb7b800a4 → uint256
MIN_BPOW_BASE 0xba019dab → uint256
MIN_FEE 0x76c7a3c7 → uint256
MIN_WEIGHT 0x218b5382 → uint256
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
calcInGivenOut 0xf8d6aed4 → uint256
calcOutGivenIn 0xba9530a6 → uint256
calcPoolInGivenSingleOut 0x82f652ad → uint256
calcPoolOutGivenSingleIn 0x8656b653 → uint256
calcSingleInGivenPoolOut 0x5c1bbaf7 → uint256
calcSingleOutGivenPoolIn 0x89298012 → uint256
calcSpotPrice 0xa221ee49 → uint256
decimals 0x313ce567 → uint8
getBalance 0xf8b2cb4f → uint256
getColor 0x9a86139b → bytes32
getController 0x3018205f → address
getCurrentTokens 0xcc77828d → address[]
getDenormalizedWeight 0x948d8ce6 → uint256
getFinalTokens 0xbe3bbd2e → address[]
getNormalizedWeight 0xf1b8a9b7 → uint256
getNumTokens 0xcd2ed8fb → uint256
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 21 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
exitswapExternAmountOut 0x02c96748
address tokenOut
uint256 tokenAmountOut
uint256 maxPoolAmountIn
returns: uint256
exitswapPoolAmountIn 0x46ab38f1
address tokenOut
uint256 poolAmountIn
uint256 minAmountOut
returns: uint256
finalize 0x4bb278f3
No parameters
gulp 0x8c28cbe8
address token
increaseApproval 0xd73dd623
address dst
uint256 amt
returns: bool
joinPool 0x4f69c0d4
uint256 poolAmountOut
uint256[] maxAmountsIn
joinswapExternAmountIn 0x5db34277
address tokenIn
uint256 tokenAmountIn
uint256 minPoolAmountOut
returns: uint256
joinswapPoolAmountOut 0x6d06dfa0
address tokenIn
uint256 poolAmountOut
uint256 maxAmountIn
returns: uint256
rebind 0x3fdddaa2
address token
uint256 balance
uint256 denorm
setController 0x92eefe9b
address manager
setPublicSwap 0x49b59552
bool public_
setSwapFee 0x34e19907
uint256 swapFee
swapExactAmountIn 0x8201aa3f
address tokenIn
uint256 tokenAmountIn
address tokenOut
uint256 minAmountOut
uint256 maxPrice
returns: uint256, uint256
swapExactAmountOut 0x7c5e9ea4
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
Recent Transactions
No transactions found for this address