commit 5dcf7287016630372971c32774e828449d87edb1
parent d6e71424f3aeb60309beffee5fc7264b36f4a16a
Author: nolash <dev@holbrook.no>
Date: Sat, 5 Jun 2021 11:58:35 +0200
Add singlecap contract + runner for all test combos
Diffstat:
13 files changed, 787 insertions(+), 15 deletions(-)
diff --git a/python/erc20_demurrage_token/data/DemurrageTokenMultiCap.bin b/python/erc20_demurrage_token/data/DemurrageTokenMultiCap.bin
@@ -0,0 +1 @@
+60e06040523480156200001157600080fd5b5060405162003d6c38038062003d6c833981810160405281019062000037919062000496565b33600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555086600590805190602001906200010a9291906200032f565b508560069080519060200190620001239291906200032f565b508460ff166007819055504260808181525050603c836200014591906200076c565b60a08181525050620f42406d04ee2d6d415b85acef81000000006200016b91906200076c565b600260006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506001600260106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508360c0818152505060006200020a6000620f424060006001620002a3640100000000026401000000009004565b905060008190806001815401808255809150506001900390600052602060002001600090919091909150558160098190555082600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560ff16600a6200028f91906200062f565b600a819055505050505050505050620009b3565b60008073fffff00000000000000000000000000000000000608c60ff16869060020a021660010281179050710fffffffff00000000000000000000000000606860ff16879060020a0216600102811790506cffffffffffffffffff00000000602060ff16859060020a02166001028117905063ffffffff83166001028117905080915050949350505050565b8280546200033d906200084e565b90600052602060002090601f016020900481019282620003615760008555620003ad565b82601f106200037c57805160ff1916838001178555620003ad565b82800160010185558215620003ad579182015b82811115620003ac5782518255916020019190600101906200038f565b5b509050620003bc9190620003c0565b5090565b5b80821115620003db576000816000905550600101620003c1565b5090565b6000620003f6620003f0846200059e565b62000575565b9050828152602081018484840111156200040f57600080fd5b6200041c84828562000818565b509392505050565b600081519050620004358162000965565b92915050565b600082601f8301126200044d57600080fd5b81516200045f848260208601620003df565b91505092915050565b60008151905062000479816200097f565b92915050565b600081519050620004908162000999565b92915050565b600080600080600080600060e0888a031215620004b257600080fd5b600088015167ffffffffffffffff811115620004cd57600080fd5b620004db8a828b016200043b565b975050602088015167ffffffffffffffff811115620004f957600080fd5b620005078a828b016200043b565b96505060406200051a8a828b016200047f565b95505060606200052d8a828b0162000468565b9450506080620005408a828b0162000468565b93505060a0620005538a828b0162000424565b92505060c0620005668a828b0162000468565b91505092959891949750929550565b60006200058162000594565b90506200058f828262000884565b919050565b6000604051905090565b600067ffffffffffffffff821115620005bc57620005bb62000918565b5b620005c78262000947565b9050602081019050919050565b6000808291508390505b60018511156200062657808604811115620005fe57620005fd620008ba565b5b60018516156200060e5780820291505b80810290506200061e8562000958565b9450620005de565b94509492505050565b60006200063c8262000801565b9150620006498362000801565b9250620006787fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000680565b905092915050565b60008262000692576001905062000765565b81620006a2576000905062000765565b8160018114620006bb5760028114620006c657620006fc565b600191505062000765565b60ff841115620006db57620006da620008ba565b5b8360020a915084821115620006f557620006f4620008ba565b5b5062000765565b5060208310610133831016604e8410600b8410161715620007365782820a90508381111562000730576200072f620008ba565b5b62000765565b620007458484846001620005d4565b925090508184048111156200075f576200075e620008ba565b5b81810290505b9392505050565b6000620007798262000801565b9150620007868362000801565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615620007c257620007c1620008ba565b5b828202905092915050565b6000620007da82620007e1565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015620008385780820151818401526020810190506200081b565b8381111562000848576000848401525b50505050565b600060028204905060018216806200086757607f821691505b602082108114156200087e576200087d620008e9565b5b50919050565b6200088f8262000947565b810181811067ffffffffffffffff82111715620008b157620008b062000918565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b6000600282049050919050565b6200097081620007cd565b81146200097c57600080fd5b50565b6200098a8162000801565b81146200099657600080fd5b50565b620009a4816200080b565b8114620009b057600080fd5b50565b60805160a05160c05161334a62000a2260003960008181610cd101528181610f2c015281816110bd01528181611def0152818161247101526124a90152600081816113bc01528181611d9d0152611e8a0152600081816113e801528181611eab0152611ef0015261334a6000f3fe608060405234801561001057600080fd5b5060043610610265576000357c0100000000000000000000000000000000000000000000000000000000900480636a2d094e11610158578063983b2d56116100d5578063e3ab207a11610099578063e3ab207a146107ec578063e54d63f71461081c578063e80952951461084c578063eda4e6d61461086a578063f2fde38b1461088857610265565b8063983b2d56146107205780639da7d8ba14610750578063a2119e2f14610780578063a9059cbb1461079e578063b470aade146107ce57610265565b806379ba50971161011c57806379ba50971461068a5780638da5cb5b146106a85780638f1df6bc146106c65780638f770ad0146106e457806395d89b411461070257610265565b80636a2d094e146105ac5780636d5055a6146105dc5780636ffa8a051461060c57806370a082311461063c578063731f237c1461066c57610265565b806331333487116101e6578063449a52f8116101aa578063449a52f8146104ce57806347a50517146104fe5780634abfbba21461052e578063573cc5071461055e5780636787a9be1461057c57610265565b806331333487146103f0578063313ce5671461042057806335b16eb81461043e57806340452d911461046e57806340fc89f51461049e57610265565b80631989c6a81161022d5780631989c6a814610324578063216ea5ec14610342578063229ba1971461037257806323b872dd146103905780633092afd5146103c057610265565b806301ffc9a71461026a57806306fdde031461029a578063095ea7b3146102b857806309f28f3c146102e857806318160ddd14610306575b600080fd5b610284600480360381019061027f9190612bf2565b6108b8565b6040516102919190612dc0565b60405180910390f35b6102a2610a63565b6040516102af9190612df6565b60405180910390f35b6102d260048036038101906102cd9190612b8d565b610af1565b6040516102df9190612dc0565b60405180910390f35b6102f0610c15565b6040516102fd9190612e78565b60405180910390f35b61030e610c37565b60405161031b9190612eae565b60405180910390f35b61032c610c3d565b6040516103399190612eae565b60405180910390f35b61035c60048036038101906103579190612c6d565b610c49565b6040516103699190612eae565b60405180910390f35b61037a610ccf565b6040516103879190612eae565b60405180910390f35b6103aa60048036038101906103a59190612b3e565b610cf3565b6040516103b79190612dc0565b60405180910390f35b6103da60048036038101906103d59190612b15565b610e1d565b6040516103e79190612dc0565b60405180910390f35b61040a60048036038101906104059190612c6d565b610f10565b6040516104179190612eae565b60405180910390f35b610428610fc1565b6040516104359190612eae565b60405180910390f35b61045860048036038101906104539190612b15565b610fc7565b6040516104659190612dc0565b60405180910390f35b61048860048036038101906104839190612c44565b6111ed565b6040516104959190612ddb565b60405180910390f35b6104b860048036038101906104b39190612bc9565b611211565b6040516104c59190612eae565b60405180910390f35b6104e860048036038101906104e39190612b8d565b611242565b6040516104f59190612dc0565b60405180910390f35b61051860048036038101906105139190612b15565b611360565b6040516105259190612eae565b60405180910390f35b61054860048036038101906105439190612c44565b6113b8565b6040516105559190612eae565b60405180910390f35b610566611418565b6040516105739190612eae565b60405180910390f35b61059660048036038101906105919190612c44565b61141e565b6040516105a39190612eae565b60405180910390f35b6105c660048036038101906105c19190612c44565b61148a565b6040516105d39190612eae565b60405180910390f35b6105f660048036038101906105f19190612b15565b6114ab565b6040516106039190612eae565b60405180910390f35b61062660048036038101906106219190612bc9565b611516565b6040516106339190612eae565b60405180910390f35b61065660048036038101906106519190612b15565b611549565b6040516106639190612eae565b60405180910390f35b61067461162a565b6040516106819190612dc0565b60405180910390f35b6106926117d8565b60405161069f9190612dc0565b60405180910390f35b6106b061197f565b6040516106bd9190612da5565b60405180910390f35b6106ce6119a5565b6040516106db9190612dc0565b60405180910390f35b6106ec611b5c565b6040516106f99190612eae565b60405180910390f35b61070a611b62565b6040516107179190612df6565b60405180910390f35b61073a60048036038101906107359190612b15565b611bf0565b6040516107479190612dc0565b60405180910390f35b61076a60048036038101906107659190612bc9565b611cad565b6040516107779190612eae565b60405180910390f35b610788611cd9565b6040516107959190612e78565b60405180910390f35b6107b860048036038101906107b39190612b8d565b611cfb565b6040516107c59190612dc0565b60405180910390f35b6107d6611d9b565b6040516107e39190612eae565b60405180910390f35b61080660048036038101906108019190612bc9565b611dbf565b6040516108139190612eae565b60405180910390f35b61083660048036038101906108319190612c6d565b611dd3565b6040516108439190612eae565b60405180910390f35b610854611e84565b6040516108619190612e78565b60405180910390f35b610872611eee565b60405161087f9190612eae565b60405180910390f35b6108a2600480360381019061089d9190612b15565b611f12565b6040516108af9190612dc0565b60405180910390f35b600063c6bb4b707c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561090d5760019050610a5e565b63449a52f87c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156109605760019050610a5e565b6301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156109b35760019050610a5e565b639493f8b27c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610a065760019050610a5e565b6337a47be47c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610a595760019050610a5e565b600090505b919050565b60058054610a709061310d565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9c9061310d565b8015610ae95780601f10610abe57610100808354040283529160200191610ae9565b820191906000526020600020905b815481529060010190602001808311610acc57829003601f168201915b505050505081565b600080610afc6119a5565b50610b0633610fc7565b50610b108361141e565b905080600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610b9e9190612ee5565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051610c029190612eae565b60405180910390a3600191505092915050565b600260009054906101000a90046fffffffffffffffffffffffffffffffff1681565b60085481565b60008080549050905090565b600080600080851415610c91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8890612e18565b60405180910390fd5b838510610c9d57600080fd5b8484610ca99190612f3b565b91508482610cb79190612f6c565b90508084610cc59190612ffa565b9250505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000610d006119a5565b50610d0a33610fc7565b50610d148461141e565b915081600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610d9f57600080fd5b610daa868684611fb4565b90508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86604051610e099190612eae565b60405180910390a380925050509392505050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610ea657503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b610eaf57600080fd5b6000600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060019050919050565b6000806000620f424091506d04ee2d6d415b85acef81000000007f0000000000000000000000000000000000000000000000000000000000000000610f559190612f3b565b905060005b84811015610f9c57620f42408284610f729190612f6c565b610f7c9190612f3b565b83610f879190612ffa565b92508080610f949061313f565b915050610f5a565b50620f42408583610fad9190612f6c565b610fb79190612f3b565b9250505092915050565b60075481565b600080600080600080600080610fdc896114ab565b915060008214806110065750610ff0611e84565b6fffffffffffffffffffffffffffffffff168210155b1561101b5760009750505050505050506111e8565b600060018361102a9190612ffa565b81548110611061577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154965061107787611211565b945060008514156110925760009750505050505050506111e8565b61109b87611cad565b95506110a687611516565b90506d04ee2d6d415b85acef8100000000620f42407f00000000000000000000000000000000000000000000000000000000000000006110e69190612f3b565b86886110f29190612f3b565b6110fc9190612f6c565b6111069190612f3b565b9350620f424081856111189190612f6c565b6111229190612f3b565b92506cffffffff00000000000000000019600102600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254169250508190555061118c8984612058565b50818973ffffffffffffffffffffffffffffffffffffffff167f9a2a887706623ad3ff7fc85652deeceabe9fe1e00466c597972079ee91ea40d3856040516111d49190612eae565b60405180910390a360019750505050505050505b919050565b600081815481106111fd57600080fd5b906000526020600020016000915090505481565b6000606860ff16710fffffffff00000000000000000000000000836001900416908060020a82049150509050919050565b600080600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661129b57600080fd5b600954600854846112ac9190612ee5565b11156112b757600080fd5b6112bf6119a5565b5082905082600860008282546112d59190612ee5565b925050819055506112e68482612058565b508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8856040516113449190612eae565b60405180910390a36113546121b4565b50600191505092915050565b600068ffffffffffffffffff600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460019004169050919050565b60007f0000000000000000000000000000000000000000000000000000000000000000826113e69190612f6c565b7f00000000000000000000000000000000000000000000000000000000000000006114119190612ee5565b9050919050565b600a5481565b6000600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16620f42406d04ee2d6d415b85acef81000000008461146f9190612f6c565b6114799190612f6c565b6114839190612f3b565b9050919050565b6000603c824261149a9190612ffa565b6114a49190612f3b565b9050919050565b6000604860ff166cffffffff000000000000000000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546001900416908060020a82049150509050919050565b6000608c60ff1673fffff00000000000000000000000000000000000836001900416908060020a82049150509050919050565b60008060008061155885611360565b9250600260109054906101000a90046fffffffffffffffffffffffffffffffff16611581611e84565b61158b9190612fc6565b6fffffffffffffffffffffffffffffffff1690506115d9600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1682610f10565b6fffffffffffffffffffffffffffffffff169150620f42406d04ee2d6d415b85acef810000000061160a9190612f6c565b82846116169190612f6c565b6116209190612f3b565b9350505050919050565b600080600080600061163a611e84565b9350600260109054906101000a90046fffffffffffffffffffffffffffffffff16846116669190612fc6565b92506000836fffffffffffffffffffffffffffffffff1614156116905760009450505050506117d5565b600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1691506116df82846fffffffffffffffffffffffffffffffff16610f10565b600260006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555083600260106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555081836fffffffffffffffffffffffffffffffff16856fffffffffffffffffffffffffffffffff167fa0717e54e02bd9829db5e6e998aec0ae9de796b8d150a3cc46a92ab869697755600260009054906101000a90046fffffffffffffffffffffffffffffffff166040516117c49190612e93565b60405180910390a460019450505050505b90565b600080600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461183557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35090565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008060008060008060008060006119be61229c565b995060006001028a14156119df5760009a5050505050505050505050611b59565b6119e88a611dbf565b97506001886119f79190612ee5565b9050611a02886113b8565b9150611a0c61162a565b50600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff169450611a498261148a565b92506000831115611a7e576d04ee2d6d415b85acef8100000000611a6d8685611dd3565b611a779190612f3b565b9350611a9b565b6d04ee2d6d415b85acef810000000085611a989190612f3b565b93505b611aaa600085600854846123cc565b98506000899080600181540180825580915050600190039060005260206000200160009091909190915055611ade8a611211565b96506000871415611af957611af28a612458565b9550611b13565b611b0587600854610c49565b9550611b11868961264b565b505b7f55d243082e019fce4009ccea5368b92e436c17586a1e793c7deda16df4e5d67581604051611b429190612eae565b60405180910390a160019a50505050505050505050505b90565b60095481565b60068054611b6f9061310d565b80601f0160208091040260200160405190810160405280929190818152602001828054611b9b9061310d565b8015611be85780601f10611bbd57610100808354040283529160200191611be8565b820191906000526020600020905b815481529060010190602001808311611bcb57829003601f168201915b505050505081565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c4c57600080fd5b6001600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060019050919050565b6000602060ff166cffffffffffffffffff00000000836001900416908060020a82049150509050919050565b600260109054906101000a90046fffffffffffffffffffffffffffffffff1681565b6000806000611d086119a5565b50611d1233610fc7565b50611d1c8461141e565b9150611d29338684611fb4565b90508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86604051611d889190612eae565b60405180910390a3809250505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600063ffffffff8260019004169050919050565b6000806000620f424091506d04ee2d6d415b85acef81000000007f0000000000000000000000000000000000000000000000000000000000000000611e189190612f3b565b905060005b84811015611e5f57620f42408284611e359190612f6c565b611e3f9190612f3b565b83611e4a9190612ee5565b92508080611e579061313f565b915050611e1d565b50620f42408583611e709190612f6c565b611e7a9190612f3b565b9250505092915050565b600060017f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000042611ed59190612ffa565b611edf9190612f3b565b611ee99190612ee5565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f6e57600080fd5b81600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550919050565b600080611fc18584612781565b50611fcc8484612058565b50611fd5611e84565b6fffffffffffffffffffffffffffffffff169050600a548310158015612003575080612000866114ab565b14155b801561203b57508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b1561204c5761204a85826128b2565b505b60019150509392505050565b600080600080600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460019004905060008514156120b957600093505050506121ae565b6120c286611360565b925084836120d09190612ee5565b91508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1611612140576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213790612e58565b60405180910390fd5b68ffffffffffffffffff198116905068ffffffffffffffffff82168117905080600102600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600193505050505b92915050565b600080600060016000805490506121cb9190612ffa565b81548110612202577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001546001900490506cffffffffffffffffff000000001981169050602060ff166008549060020a0281179050806001026000600160008054905061224f9190612ffa565b81548110612286577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200181905550600191505090565b60008060008060016000805490506122b49190612ffa565b815481106122eb577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015491503073ffffffffffffffffffffffffffffffffffffffff1663e80952956040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561235a57600080fd5b505afa15801561236e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123929190612c1b565b6fffffffffffffffffffffffffffffffff1690506123af82611dbf565b81116123c3576000600102925050506123c9565b81925050505b90565b60008073fffff00000000000000000000000000000000000608c60ff16869060020a021660010281179050710fffffffff00000000000000000000000000606860ff16879060020a0216600102811790506cffffffffffffffffff00000000602060ff16859060020a02166001028117905063ffffffff83166001028117905080915050949350505050565b600080600080600061246986611cad565b9350620f42407f00000000000000000000000000000000000000000000000000000000000000008561249b9190612f6c565b6124a59190612f3b565b91507f0000000000000000000000000000000000000000000000000000000000000000620f4240836124d79190612f6c565b6124e19190612f3b565b9050838110156125f9576124f486611dbf565b9250710fffffffff0000000000000000000000000019600102600060018561251c9190612ffa565b81548110612553577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160008282541692505081905550606860ff1660019060020a027f80000000000000000000000000000000000000000000000000000000000000001760010260006001856125aa9190612ffa565b815481106125e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001600082825417925050819055505b61263e600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166d04ee2d6d415b85acef8100000000846126399190612f3b565b612058565b5081945050505050919050565b600080600084141561266157600091505061277b565b7f800000000000000000000000000000000000000000000000000000000000000060010260006001856126949190612ffa565b815481106126cb577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020016000828254179250508190555061273b60006001856126f49190612ffa565b8154811061272b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154611cad565b9050612774600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858361276f9190612ffa565b612058565b5060019150505b92915050565b600080600080600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460019004905060008514156127e257600093505050506128ac565b6127eb86611360565b925084831015612830576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161282790612e38565b60405180910390fd5b848361283c9190612ffa565b915068ffffffffffffffffff198116905068ffffffffffffffffff82168117905080600102600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600193505050505b92915050565b60006cffffffff00000000000000000019600102600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825416925050819055506cffffffff000000000000000000604860ff16839060020a0216600102600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254179250508190555061298361298e565b506001905092915050565b600080600080600060016000805490506129a89190612ffa565b815481106129df577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154925060016129f784611211565b612a019190612ee5565b905082600190049150710fffffffff000000000000000000000000001982169150710fffffffff00000000000000000000000000606860ff16829060020a0216821791508160010260006001600080549050612a5d9190612ffa565b81548110612a94577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055506001935050505090565b600081359050612abb816132a1565b92915050565b600081359050612ad0816132b8565b92915050565b600081359050612ae5816132cf565b92915050565b600081519050612afa816132e6565b92915050565b600081359050612b0f816132fd565b92915050565b600060208284031215612b2757600080fd5b6000612b3584828501612aac565b91505092915050565b600080600060608486031215612b5357600080fd5b6000612b6186828701612aac565b9350506020612b7286828701612aac565b9250506040612b8386828701612b00565b9150509250925092565b60008060408385031215612ba057600080fd5b6000612bae85828601612aac565b9250506020612bbf85828601612b00565b9150509250929050565b600060208284031215612bdb57600080fd5b6000612be984828501612ac1565b91505092915050565b600060208284031215612c0457600080fd5b6000612c1284828501612ad6565b91505092915050565b600060208284031215612c2d57600080fd5b6000612c3b84828501612aeb565b91505092915050565b600060208284031215612c5657600080fd5b6000612c6484828501612b00565b91505092915050565b60008060408385031215612c8057600080fd5b6000612c8e85828601612b00565b9250506020612c9f85828601612b00565b9150509250929050565b612cb28161302e565b82525050565b612cc181613040565b82525050565b612cd08161304c565b82525050565b6000612ce182612ec9565b612ceb8185612ed4565b9350612cfb8185602086016130da565b612d0481613215565b840191505092915050565b6000612d1c601183612ed4565b9150612d2782613226565b602082019050919050565b6000612d3f600d83612ed4565b9150612d4a8261324f565b602082019050919050565b6000612d62600d83612ed4565b9150612d6d82613278565b602082019050919050565b612d8181613082565b82525050565b612d90816130c8565b82525050565b612d9f816130be565b82525050565b6000602082019050612dba6000830184612ca9565b92915050565b6000602082019050612dd56000830184612cb8565b92915050565b6000602082019050612df06000830184612cc7565b92915050565b60006020820190508181036000830152612e108184612cd6565b905092915050565b60006020820190508181036000830152612e3181612d0f565b9050919050565b60006020820190508181036000830152612e5181612d32565b9050919050565b60006020820190508181036000830152612e7181612d55565b9050919050565b6000602082019050612e8d6000830184612d78565b92915050565b6000602082019050612ea86000830184612d87565b92915050565b6000602082019050612ec36000830184612d96565b92915050565b600081519050919050565b600082825260208201905092915050565b6000612ef0826130be565b9150612efb836130be565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612f3057612f2f613188565b5b828201905092915050565b6000612f46826130be565b9150612f51836130be565b925082612f6157612f606131b7565b5b828204905092915050565b6000612f77826130be565b9150612f82836130be565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612fbb57612fba613188565b5b828202905092915050565b6000612fd182613082565b9150612fdc83613082565b925082821015612fef57612fee613188565b5b828203905092915050565b6000613005826130be565b9150613010836130be565b92508282101561302357613022613188565b5b828203905092915050565b60006130398261309e565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60006fffffffffffffffffffffffffffffffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006130d382613082565b9050919050565b60005b838110156130f85780820151818401526020810190506130dd565b83811115613107576000848401525b50505050565b6000600282049050600182168061312557607f821691505b60208210811415613139576131386131e6565b5b50919050565b600061314a826130be565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561317d5761317c613188565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f8301169050919050565b7f4552525f4e554d50415254535f5a45524f000000000000000000000000000000600082015250565b7f4552525f4f5645525350454e4400000000000000000000000000000000000000600082015250565b7f4552525f574f554c445752415000000000000000000000000000000000000000600082015250565b6132aa8161302e565b81146132b557600080fd5b50565b6132c18161304c565b81146132cc57600080fd5b50565b6132d881613056565b81146132e357600080fd5b50565b6132ef81613082565b81146132fa57600080fd5b50565b613306816130be565b811461331157600080fd5b5056fea2646970667358221220c5feb6b1114a2cab184be4920704db0d3d14a87b8c092f786f96263d39c1457b64736f6c63430008040033
+\ No newline at end of file
diff --git a/python/erc20_demurrage_token/data/DemurrageTokenMultiCap.json b/python/erc20_demurrage_token/data/DemurrageTokenMultiCap.json
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"uint256","name":"_taxLevelMinute","type":"uint256"},{"internalType":"uint256","name":"_periodMinutes","type":"uint256"},{"internalType":"address","name":"_defaultSinkAddress","type":"address"},{"internalType":"uint256","name":"_supplyCap","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_foo","type":"bytes32"}],"name":"Debug","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_period","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_periodCount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_oldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAmount","type":"uint256"}],"name":"Decayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_period","type":"uint256"}],"name":"Period","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"},{"indexed":true,"internalType":"uint256","name":"_period","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Redistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"accountPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actualPeriod","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"addMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"applyDemurrage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"applyRedistributionOnAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"baseBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"changePeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"decayBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"demurrageAmount","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_target","type":"uint256"}],"name":"demurrageCycles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"demurragePeriod","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodCount","type":"uint256"}],"name":"getPeriodTimeDelta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"growBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumParticipantSpend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redistributionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"redistributions","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numParts","type":"uint256"},{"internalType":"uint256","name":"_sumWhole","type":"uint256"}],"name":"remainder","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"removeMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"toBaseAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionDemurrageModifier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionParticipants","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
diff --git a/python/erc20_demurrage_token/data/DemurrageTokenSingleCap.bin b/python/erc20_demurrage_token/data/DemurrageTokenSingleCap.bin
@@ -0,0 +1 @@
+60e06040523480156200001157600080fd5b5060405162003a6638038062003a66833981810160405281019062000037919062000496565b33600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555086600590805190602001906200010a9291906200032f565b508560069080519060200190620001239291906200032f565b508460ff166007819055504260808181525050603c836200014591906200076c565b60a08181525050620f42406d04ee2d6d415b85acef81000000006200016b91906200076c565b600260006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506001600260106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508360c0818152505060006200020a6000620f424060006001620002a3640100000000026401000000009004565b905060008190806001815401808255809150506001900390600052602060002001600090919091909150558160098190555082600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560ff16600a6200028f91906200062f565b600a819055505050505050505050620009b3565b60008073fffff00000000000000000000000000000000000608c60ff16869060020a021660010281179050710fffffffff00000000000000000000000000606860ff16879060020a0216600102811790506cffffffffffffffffff00000000602060ff16859060020a02166001028117905063ffffffff83166001028117905080915050949350505050565b8280546200033d906200084e565b90600052602060002090601f016020900481019282620003615760008555620003ad565b82601f106200037c57805160ff1916838001178555620003ad565b82800160010185558215620003ad579182015b82811115620003ac5782518255916020019190600101906200038f565b5b509050620003bc9190620003c0565b5090565b5b80821115620003db576000816000905550600101620003c1565b5090565b6000620003f6620003f0846200059e565b62000575565b9050828152602081018484840111156200040f57600080fd5b6200041c84828562000818565b509392505050565b600081519050620004358162000965565b92915050565b600082601f8301126200044d57600080fd5b81516200045f848260208601620003df565b91505092915050565b60008151905062000479816200097f565b92915050565b600081519050620004908162000999565b92915050565b600080600080600080600060e0888a031215620004b257600080fd5b600088015167ffffffffffffffff811115620004cd57600080fd5b620004db8a828b016200043b565b975050602088015167ffffffffffffffff811115620004f957600080fd5b620005078a828b016200043b565b96505060406200051a8a828b016200047f565b95505060606200052d8a828b0162000468565b9450506080620005408a828b0162000468565b93505060a0620005538a828b0162000424565b92505060c0620005668a828b0162000468565b91505092959891949750929550565b60006200058162000594565b90506200058f828262000884565b919050565b6000604051905090565b600067ffffffffffffffff821115620005bc57620005bb62000918565b5b620005c78262000947565b9050602081019050919050565b6000808291508390505b60018511156200062657808604811115620005fe57620005fd620008ba565b5b60018516156200060e5780820291505b80810290506200061e8562000958565b9450620005de565b94509492505050565b60006200063c8262000801565b9150620006498362000801565b9250620006787fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000680565b905092915050565b60008262000692576001905062000765565b81620006a2576000905062000765565b8160018114620006bb5760028114620006c657620006fc565b600191505062000765565b60ff841115620006db57620006da620008ba565b5b8360020a915084821115620006f557620006f4620008ba565b5b5062000765565b5060208310610133831016604e8410600b8410161715620007365782820a90508381111562000730576200072f620008ba565b5b62000765565b620007458484846001620005d4565b925090508184048111156200075f576200075e620008ba565b5b81810290505b9392505050565b6000620007798262000801565b9150620007868362000801565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615620007c257620007c1620008ba565b5b828202905092915050565b6000620007da82620007e1565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015620008385780820151818401526020810190506200081b565b8381111562000848576000848401525b50505050565b600060028204905060018216806200086757607f821691505b602082108114156200087e576200087d620008e9565b5b50919050565b6200088f8262000947565b810181811067ffffffffffffffff82111715620008b157620008b062000918565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b6000600282049050919050565b6200097081620007cd565b81146200097c57600080fd5b50565b6200098a8162000801565b81146200099657600080fd5b50565b620009a4816200080b565b8114620009b057600080fd5b50565b60805160a05160c05161304b62000a1b60003960008181610cc701528181610f1801528181611c26015281816122a801526122e001526000818161123001528181611bd40152611cc101526000818161125c01528181611ce20152611d27015261304b6000f3fe608060405234801561001057600080fd5b5060043610610265576000357c0100000000000000000000000000000000000000000000000000000000900480636a2d094e11610158578063983b2d56116100d5578063e3ab207a11610099578063e3ab207a146107ec578063e54d63f71461081c578063e80952951461084c578063eda4e6d61461086a578063f2fde38b1461088857610265565b8063983b2d56146107205780639da7d8ba14610750578063a2119e2f14610780578063a9059cbb1461079e578063b470aade146107ce57610265565b806379ba50971161011c57806379ba50971461068a5780638da5cb5b146106a85780638f1df6bc146106c65780638f770ad0146106e457806395d89b411461070257610265565b80636a2d094e146105ac5780636d5055a6146105dc5780636ffa8a051461060c57806370a082311461063c578063731f237c1461066c57610265565b806331333487116101e6578063449a52f8116101aa578063449a52f8146104ce57806347a50517146104fe5780634abfbba21461052e578063573cc5071461055e5780636787a9be1461057c57610265565b806331333487146103f0578063313ce5671461042057806335b16eb81461043e57806340452d911461046e57806340fc89f51461049e57610265565b80631989c6a81161022d5780631989c6a814610324578063216ea5ec14610342578063229ba1971461037257806323b872dd146103905780633092afd5146103c057610265565b806301ffc9a71461026a57806306fdde031461029a578063095ea7b3146102b857806309f28f3c146102e857806318160ddd14610306575b600080fd5b610284600480360381019061027f91906128f3565b6108b8565b6040516102919190612ac1565b60405180910390f35b6102a2610a63565b6040516102af9190612af7565b60405180910390f35b6102d260048036038101906102cd919061288e565b610af1565b6040516102df9190612ac1565b60405180910390f35b6102f0610c0b565b6040516102fd9190612b79565b60405180910390f35b61030e610c2d565b60405161031b9190612baf565b60405180910390f35b61032c610c33565b6040516103399190612baf565b60405180910390f35b61035c6004803603810190610357919061296e565b610c3f565b6040516103699190612baf565b60405180910390f35b61037a610cc5565b6040516103879190612baf565b60405180910390f35b6103aa60048036038101906103a5919061283f565b610ce9565b6040516103b79190612ac1565b60405180910390f35b6103da60048036038101906103d59190612816565b610e09565b6040516103e79190612ac1565b60405180910390f35b61040a6004803603810190610405919061296e565b610efc565b6040516104179190612baf565b60405180910390f35b610428610fad565b6040516104359190612baf565b60405180910390f35b61045860048036038101906104539190612816565b610fb3565b6040516104659190612ac1565b60405180910390f35b61048860048036038101906104839190612945565b611061565b6040516104959190612adc565b60405180910390f35b6104b860048036038101906104b391906128ca565b611085565b6040516104c59190612baf565b60405180910390f35b6104e860048036038101906104e3919061288e565b6110b6565b6040516104f59190612ac1565b60405180910390f35b61051860048036038101906105139190612816565b6111d4565b6040516105259190612baf565b60405180910390f35b61054860048036038101906105439190612945565b61122c565b6040516105559190612baf565b60405180910390f35b61056661128c565b6040516105739190612baf565b60405180910390f35b61059660048036038101906105919190612945565b611292565b6040516105a39190612baf565b60405180910390f35b6105c660048036038101906105c19190612945565b6112fe565b6040516105d39190612baf565b60405180910390f35b6105f660048036038101906105f19190612816565b61131f565b6040516106039190612baf565b60405180910390f35b610626600480360381019061062191906128ca565b61138a565b6040516106339190612baf565b60405180910390f35b61065660048036038101906106519190612816565b6113bd565b6040516106639190612baf565b60405180910390f35b61067461149e565b6040516106819190612ac1565b60405180910390f35b61069261164c565b60405161069f9190612ac1565b60405180910390f35b6106b06117f3565b6040516106bd9190612aa6565b60405180910390f35b6106ce611819565b6040516106db9190612ac1565b60405180910390f35b6106ec61199d565b6040516106f99190612baf565b60405180910390f35b61070a6119a3565b6040516107179190612af7565b60405180910390f35b61073a60048036038101906107359190612816565b611a31565b6040516107479190612ac1565b60405180910390f35b61076a600480360381019061076591906128ca565b611aee565b6040516107779190612baf565b60405180910390f35b610788611b1a565b6040516107959190612b79565b60405180910390f35b6107b860048036038101906107b3919061288e565b611b3c565b6040516107c59190612ac1565b60405180910390f35b6107d6611bd2565b6040516107e39190612baf565b60405180910390f35b610806600480360381019061080191906128ca565b611bf6565b6040516108139190612baf565b60405180910390f35b6108366004803603810190610831919061296e565b611c0a565b6040516108439190612baf565b60405180910390f35b610854611cbb565b6040516108619190612b79565b60405180910390f35b610872611d25565b60405161087f9190612baf565b60405180910390f35b6108a2600480360381019061089d9190612816565b611d49565b6040516108af9190612ac1565b60405180910390f35b600063c6bb4b707c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561090d5760019050610a5e565b63449a52f87c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156109605760019050610a5e565b6301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156109b35760019050610a5e565b639493f8b27c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610a065760019050610a5e565b6337a47be47c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610a595760019050610a5e565b600090505b919050565b60058054610a7090612e0e565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9c90612e0e565b8015610ae95780601f10610abe57610100808354040283529160200191610ae9565b820191906000526020600020905b815481529060010190602001808311610acc57829003601f168201915b505050505081565b600080610afc611819565b50610b0683611292565b905080600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610b949190612be6565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051610bf89190612baf565b60405180910390a3600191505092915050565b600260009054906101000a90046fffffffffffffffffffffffffffffffff1681565b60085481565b60008080549050905090565b600080600080851415610c87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7e90612b19565b60405180910390fd5b838510610c9357600080fd5b8484610c9f9190612c3c565b91508482610cad9190612c6d565b90508084610cbb9190612cfb565b9250505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000610cf6611819565b50610d0084611292565b915081600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610d8b57600080fd5b610d96868684611deb565b90508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86604051610df59190612baf565b60405180910390a380925050509392505050565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610e9257503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b610e9b57600080fd5b6000600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060019050919050565b6000806000620f424091506d04ee2d6d415b85acef81000000007f0000000000000000000000000000000000000000000000000000000000000000610f419190612c3c565b905060005b84811015610f8857620f42408284610f5e9190612c6d565b610f689190612c3c565b83610f739190612cfb565b92508080610f8090612e40565b915050610f46565b50620f42408583610f999190612c6d565b610fa39190612c3c565b9250505092915050565b60075481565b600080610fbf8361131f565b90506000811480610fe95750610fd3611cbb565b6fffffffffffffffffffffffffffffffff168110155b15610ff857600091505061105c565b6cffffffff00000000000000000019600102600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254169250508190555060019150505b919050565b6000818154811061107157600080fd5b906000526020600020016000915090505481565b6000606860ff16710fffffffff00000000000000000000000000836001900416908060020a82049150509050919050565b600080600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661110f57600080fd5b600954600854846111209190612be6565b111561112b57600080fd5b611133611819565b5082905082600860008282546111499190612be6565b9250508190555061115a8482611e8f565b508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8856040516111b89190612baf565b60405180910390a36111c8611feb565b50600191505092915050565b600068ffffffffffffffffff600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460019004169050919050565b60007f00000000000000000000000000000000000000000000000000000000000000008261125a9190612c6d565b7f00000000000000000000000000000000000000000000000000000000000000006112859190612be6565b9050919050565b600a5481565b6000600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16620f42406d04ee2d6d415b85acef8100000000846112e39190612c6d565b6112ed9190612c6d565b6112f79190612c3c565b9050919050565b6000603c824261130e9190612cfb565b6113189190612c3c565b9050919050565b6000604860ff166cffffffff000000000000000000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546001900416908060020a82049150509050919050565b6000608c60ff1673fffff00000000000000000000000000000000000836001900416908060020a82049150509050919050565b6000806000806113cc856111d4565b9250600260109054906101000a90046fffffffffffffffffffffffffffffffff166113f5611cbb565b6113ff9190612cc7565b6fffffffffffffffffffffffffffffffff16905061144d600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1682610efc565b6fffffffffffffffffffffffffffffffff169150620f42406d04ee2d6d415b85acef810000000061147e9190612c6d565b828461148a9190612c6d565b6114949190612c3c565b9350505050919050565b60008060008060006114ae611cbb565b9350600260109054906101000a90046fffffffffffffffffffffffffffffffff16846114da9190612cc7565b92506000836fffffffffffffffffffffffffffffffff161415611504576000945050505050611649565b600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16915061155382846fffffffffffffffffffffffffffffffff16610efc565b600260006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555083600260106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555081836fffffffffffffffffffffffffffffffff16856fffffffffffffffffffffffffffffffff167fa0717e54e02bd9829db5e6e998aec0ae9de796b8d150a3cc46a92ab869697755600260009054906101000a90046fffffffffffffffffffffffffffffffff166040516116389190612b94565b60405180910390a460019450505050505b90565b600080600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116a957600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35090565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060008060008060008060008060006118326120d3565b995060006001028a14156118535760009a505050505050505050505061199a565b61185c8a611bf6565b975060018861186b9190612be6565b90506118768861122c565b915061188061149e565b50600260009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1694506118bd826112fe565b925060008311156118f2576d04ee2d6d415b85acef81000000006118e18685611c0a565b6118eb9190612c3c565b935061190f565b6d04ee2d6d415b85acef81000000008561190c9190612c3c565b93505b61191e60008560085484612203565b985060008990806001815401808255809150506001900390600052602060002001600090919091909150556119528a61228f565b95507f55d243082e019fce4009ccea5368b92e436c17586a1e793c7deda16df4e5d675816040516119839190612baf565b60405180910390a160019a50505050505050505050505b90565b60095481565b600680546119b090612e0e565b80601f01602080910402602001604051908101604052809291908181526020018280546119dc90612e0e565b8015611a295780601f106119fe57610100808354040283529160200191611a29565b820191906000526020600020905b815481529060010190602001808311611a0c57829003601f168201915b505050505081565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a8d57600080fd5b6001600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060019050919050565b6000602060ff166cffffffffffffffffff00000000836001900416908060020a82049150509050919050565b600260109054906101000a90046fffffffffffffffffffffffffffffffff1681565b6000806000611b49611819565b50611b5384611292565b9150611b60338684611deb565b90508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86604051611bbf9190612baf565b60405180910390a3809250505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600063ffffffff8260019004169050919050565b6000806000620f424091506d04ee2d6d415b85acef81000000007f0000000000000000000000000000000000000000000000000000000000000000611c4f9190612c3c565b905060005b84811015611c9657620f42408284611c6c9190612c6d565b611c769190612c3c565b83611c819190612be6565b92508080611c8e90612e40565b915050611c54565b50620f42408583611ca79190612c6d565b611cb19190612c3c565b9250505092915050565b600060017f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000042611d0c9190612cfb565b611d169190612c3c565b611d209190612be6565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611da557600080fd5b81600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550919050565b600080611df88584612482565b50611e038484611e8f565b50611e0c611cbb565b6fffffffffffffffffffffffffffffffff169050600a548310158015611e3a575080611e378661131f565b14155b8015611e7257508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15611e8357611e8185826125b3565b505b60019150509392505050565b600080600080600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546001900490506000851415611ef05760009350505050611fe5565b611ef9866111d4565b92508483611f079190612be6565b91508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1611611f77576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6e90612b59565b60405180910390fd5b68ffffffffffffffffff198116905068ffffffffffffffffff82168117905080600102600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600193505050505b92915050565b600080600060016000805490506120029190612cfb565b81548110612039577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001546001900490506cffffffffffffffffff000000001981169050602060ff166008549060020a028117905080600102600060016000805490506120869190612cfb565b815481106120bd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200181905550600191505090565b60008060008060016000805490506120eb9190612cfb565b81548110612122577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015491503073ffffffffffffffffffffffffffffffffffffffff1663e80952956040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b15801561219157600080fd5b505afa1580156121a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c9919061291c565b6fffffffffffffffffffffffffffffffff1690506121e682611bf6565b81116121fa57600060010292505050612200565b81925050505b90565b60008073fffff00000000000000000000000000000000000608c60ff16869060020a021660010281179050710fffffffff00000000000000000000000000606860ff16879060020a0216600102811790506cffffffffffffffffff00000000602060ff16859060020a02166001028117905063ffffffff83166001028117905080915050949350505050565b60008060008060006122a086611aee565b9350620f42407f0000000000000000000000000000000000000000000000000000000000000000856122d29190612c6d565b6122dc9190612c3c565b91507f0000000000000000000000000000000000000000000000000000000000000000620f42408361230e9190612c6d565b6123189190612c3c565b9050838110156124305761232b86611bf6565b9250710fffffffff000000000000000000000000001960010260006001856123539190612cfb565b8154811061238a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160008282541692505081905550606860ff1660019060020a027f80000000000000000000000000000000000000000000000000000000000000001760010260006001856123e19190612cfb565b81548110612418577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001600082825417925050819055505b612475600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166d04ee2d6d415b85acef8100000000846124709190612c3c565b611e8f565b5081945050505050919050565b600080600080600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460019004905060008514156124e357600093505050506125ad565b6124ec866111d4565b925084831015612531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161252890612b39565b60405180910390fd5b848361253d9190612cfb565b915068ffffffffffffffffff198116905068ffffffffffffffffff82168117905080600102600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600193505050505b92915050565b60006cffffffff00000000000000000019600102600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825416925050819055506cffffffff000000000000000000604860ff16839060020a0216600102600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254179250508190555061268461268f565b506001905092915050565b600080600080600060016000805490506126a99190612cfb565b815481106126e0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154925060016126f884611085565b6127029190612be6565b905082600190049150710fffffffff000000000000000000000000001982169150710fffffffff00000000000000000000000000606860ff16829060020a021682179150816001026000600160008054905061275e9190612cfb565b81548110612795577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055506001935050505090565b6000813590506127bc81612fa2565b92915050565b6000813590506127d181612fb9565b92915050565b6000813590506127e681612fd0565b92915050565b6000815190506127fb81612fe7565b92915050565b60008135905061281081612ffe565b92915050565b60006020828403121561282857600080fd5b6000612836848285016127ad565b91505092915050565b60008060006060848603121561285457600080fd5b6000612862868287016127ad565b9350506020612873868287016127ad565b925050604061288486828701612801565b9150509250925092565b600080604083850312156128a157600080fd5b60006128af858286016127ad565b92505060206128c085828601612801565b9150509250929050565b6000602082840312156128dc57600080fd5b60006128ea848285016127c2565b91505092915050565b60006020828403121561290557600080fd5b6000612913848285016127d7565b91505092915050565b60006020828403121561292e57600080fd5b600061293c848285016127ec565b91505092915050565b60006020828403121561295757600080fd5b600061296584828501612801565b91505092915050565b6000806040838503121561298157600080fd5b600061298f85828601612801565b92505060206129a085828601612801565b9150509250929050565b6129b381612d2f565b82525050565b6129c281612d41565b82525050565b6129d181612d4d565b82525050565b60006129e282612bca565b6129ec8185612bd5565b93506129fc818560208601612ddb565b612a0581612f16565b840191505092915050565b6000612a1d601183612bd5565b9150612a2882612f27565b602082019050919050565b6000612a40600d83612bd5565b9150612a4b82612f50565b602082019050919050565b6000612a63600d83612bd5565b9150612a6e82612f79565b602082019050919050565b612a8281612d83565b82525050565b612a9181612dc9565b82525050565b612aa081612dbf565b82525050565b6000602082019050612abb60008301846129aa565b92915050565b6000602082019050612ad660008301846129b9565b92915050565b6000602082019050612af160008301846129c8565b92915050565b60006020820190508181036000830152612b1181846129d7565b905092915050565b60006020820190508181036000830152612b3281612a10565b9050919050565b60006020820190508181036000830152612b5281612a33565b9050919050565b60006020820190508181036000830152612b7281612a56565b9050919050565b6000602082019050612b8e6000830184612a79565b92915050565b6000602082019050612ba96000830184612a88565b92915050565b6000602082019050612bc46000830184612a97565b92915050565b600081519050919050565b600082825260208201905092915050565b6000612bf182612dbf565b9150612bfc83612dbf565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612c3157612c30612e89565b5b828201905092915050565b6000612c4782612dbf565b9150612c5283612dbf565b925082612c6257612c61612eb8565b5b828204905092915050565b6000612c7882612dbf565b9150612c8383612dbf565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612cbc57612cbb612e89565b5b828202905092915050565b6000612cd282612d83565b9150612cdd83612d83565b925082821015612cf057612cef612e89565b5b828203905092915050565b6000612d0682612dbf565b9150612d1183612dbf565b925082821015612d2457612d23612e89565b5b828203905092915050565b6000612d3a82612d9f565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60006fffffffffffffffffffffffffffffffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612dd482612d83565b9050919050565b60005b83811015612df9578082015181840152602081019050612dde565b83811115612e08576000848401525b50505050565b60006002820490506001821680612e2657607f821691505b60208210811415612e3a57612e39612ee7565b5b50919050565b6000612e4b82612dbf565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612e7e57612e7d612e89565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000601f19601f8301169050919050565b7f4552525f4e554d50415254535f5a45524f000000000000000000000000000000600082015250565b7f4552525f4f5645525350454e4400000000000000000000000000000000000000600082015250565b7f4552525f574f554c445752415000000000000000000000000000000000000000600082015250565b612fab81612d2f565b8114612fb657600080fd5b50565b612fc281612d4d565b8114612fcd57600080fd5b50565b612fd981612d57565b8114612fe457600080fd5b50565b612ff081612d83565b8114612ffb57600080fd5b50565b61300781612dbf565b811461301257600080fd5b5056fea2646970667358221220a834e180272e82901d4d69c10917674445b4deab2e2e9f57ccf712ba2a8f33d364736f6c63430008040033
+\ No newline at end of file
diff --git a/python/erc20_demurrage_token/data/DemurrageTokenSingleCap.json b/python/erc20_demurrage_token/data/DemurrageTokenSingleCap.json
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"uint256","name":"_taxLevelMinute","type":"uint256"},{"internalType":"uint256","name":"_periodMinutes","type":"uint256"},{"internalType":"address","name":"_defaultSinkAddress","type":"address"},{"internalType":"uint256","name":"_supplyCap","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_foo","type":"bytes32"}],"name":"Debug","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_period","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_periodCount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_oldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAmount","type":"uint256"}],"name":"Decayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_period","type":"uint256"}],"name":"Period","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"},{"indexed":true,"internalType":"uint256","name":"_period","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Redistribution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"accountPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actualPeriod","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"addMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"applyDemurrage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"applyRedistributionOnAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"baseBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"changePeriod","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"decayBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"demurrageAmount","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_target","type":"uint256"}],"name":"demurrageCycles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"demurragePeriod","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodCount","type":"uint256"}],"name":"getPeriodTimeDelta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"growBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumParticipantSpend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redistributionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"redistributions","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numParts","type":"uint256"},{"internalType":"uint256","name":"_sumWhole","type":"uint256"}],"name":"remainder","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"removeMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"toBaseAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionDemurrageModifier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionParticipants","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redistribution","type":"bytes32"}],"name":"toRedistributionSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
diff --git a/python/erc20_demurrage_token/token.py b/python/erc20_demurrage_token/token.py
@@ -46,6 +46,7 @@ class DemurrageToken(ERC20):
'MultiNocap',
'SingleNocap',
'MultiCap',
+ 'SingleCap',
]
def constructor(self, sender_address, settings, redistribute=True, cap=0, tx_format=TxFormat.JSONRPC):
@@ -59,6 +60,8 @@ class DemurrageToken(ERC20):
enc.uint256(settings.demurrage_level)
enc.uint256(settings.period_minutes)
enc.address(settings.sink_address)
+ if cap > 0:
+ enc.uint256(cap)
code += enc.get()
tx = self.template(sender_address, None, use_nonce=True)
tx = self.set_code(tx, code)
@@ -255,6 +258,10 @@ class DemurrageToken(ERC20):
return self.call_noarg('demurrageAmount', contract_address, sender_address=sender_address)
+ def supply_cap(self, contract_address, sender_address=ZERO_ADDRESS):
+ return self.call_noarg('supplyCap', contract_address, sender_address=sender_address)
+
+
@classmethod
def parse_actual_period(self, v):
return abi_decode_single(ABIContractType.UINT256, v)
@@ -298,3 +305,8 @@ class DemurrageToken(ERC20):
@classmethod
def parse_to_redistribution_period(self, v):
return abi_decode_single(ABIContractType.UINT256, v)
+
+
+ @classmethod
+ def parse_supply_cap(self, v):
+ return abi_decode_single(ABIContractType.UINT256, v)
diff --git a/python/test.sh b/python/test.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -e
+
+export PYTHONPATH=.
+
+modes=(MultiNocap MultiCap SingleCap SingleNocap)
+for m in ${modes[@]}; do
+ ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_pure.py
+ ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_period.py
+ ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_basic.py
+done
+
+modes=(MultiCap SingleCap)
+for m in ${modes[@]}; do
+ ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_cap.py
+done
+
+modes=(SingleCap SingleNocap)
+for m in ${modes[@]}; do
+ ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_single.py
+done
+
+modes=(MultiCap MultiNocap)
+for m in ${modes[@]}; do
+ ERC20_DEMURRAGE_TOKEN_TEST_MODE=$m python tests/test_redistribution.py
+done
+
+set +e
diff --git a/python/tests/base.py b/python/tests/base.py
@@ -62,7 +62,7 @@ class TestDemurrage(EthTesterCase):
self.start_time = int(r['timestamp'])
self.default_supply = 1000000000000
- self.default_supply_cap = self.default_supply * 10
+ self.default_supply_cap = int(self.default_supply * 10)
def deploy(self, interface, mode):
@@ -73,9 +73,11 @@ class TestDemurrage(EthTesterCase):
elif mode == 'SingleNocap':
(tx_hash, o) = interface.constructor(self.accounts[0], self.settings, redistribute=False, cap=0)
elif mode == 'MultiCap':
+ (tx_hash, o) = interface.constructor(self.accounts[0], self.settings, redistribute=True, cap=self.default_supply_cap)
+ elif mode == 'SingleCap':
(tx_hash, o) = interface.constructor(self.accounts[0], self.settings, redistribute=False, cap=self.default_supply_cap)
else:
- raise ValueError('Invalid mode "{}", valid are {}'.format(mode, DeurrageToken.valid_modes))
+ raise ValueError('Invalid mode "{}", valid are {}'.format(self.mode, DemurrageToken.valid_modes))
r = self.rpc.do(o)
o = receipt(tx_hash)
@@ -88,11 +90,13 @@ class TestDemurrage(EthTesterCase):
r = self.rpc.do(o)
self.start_time = r['timestamp']
+ logg.debug('contract address {} start block {} start time {}'.format(self.address, self.start_block, self.start_time))
+
+
def tearDown(self):
pass
-
class TestDemurrageDefault(TestDemurrage):
def setUp(self):
@@ -104,24 +108,58 @@ class TestDemurrageDefault(TestDemurrage):
self.mode = os.environ.get('ERC20_DEMURRAGE_TOKEN_TEST_MODE')
if self.mode == None:
self.mode = 'MultiNocap'
+ logg.debug('executing test setup default mode {}'.format(self.mode))
self.deploy(c, self.mode)
logg.info('deployed with mode {}'.format(self.mode))
-class TestDemurrageSingleNocap(TestDemurrage):
+class TestDemurrageSingle(TestDemurrage):
def setUp(self):
- super(TestDemurrageSingleNocap, self).setUp()
+ super(TestDemurrageSingle, self).setUp()
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
- self.mode = 'SingleNocap'
+ self.mode = os.environ.get('ERC20_DEMURRAGE_TOKEN_TEST_MODE')
+ single_valid_modes = [
+ 'SingleNocap',
+ 'SingleCap',
+ ]
+ if self.mode != None:
+ if self.mode not in single_valid_modes:
+ raise ValueError('Invalid mode "{}" for "single" contract tests, valid are {}'.format(self.mode, single_valid_modes))
+ else:
+ self.mode = 'SingleNocap'
+ logg.debug('executing test setup demurragesingle mode {}'.format(self.mode))
self.deploy(c, self.mode)
logg.info('deployed with mode {}'.format(self.mode))
+class TestDemurrageCap(TestDemurrage):
+
+ def setUp(self):
+ super(TestDemurrageCap, self).setUp()
+
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+
+ self.mode = os.environ.get('ERC20_DEMURRAGE_TOKEN_TEST_MODE')
+ cap_valid_modes = [
+ 'MultiCap',
+ 'SingleCap',
+ ]
+ if self.mode != None:
+ if self.mode not in cap_valid_modes:
+ raise ValueError('Invalid mode "{}" for "cap" contract tests, valid are {}'.format(self.mode, cap_valid_modes))
+ else:
+ self.mode = 'MultiCap'
+ logg.debug('executing test setup demurragecap mode {}'.format(self.mode))
+
+ self.deploy(c, self.mode)
+
+ logg.info('deployed with mode {}'.format(self.mode))
diff --git a/python/tests/test_basic.py b/python/tests/test_basic.py
@@ -16,7 +16,7 @@ from erc20_demurrage_token import DemurrageToken
# test imports
from tests.base import TestDemurrageDefault
-logging.basicConfig(level=logging.INFO)
+logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
testdir = os.path.dirname(__file__)
diff --git a/python/tests/test_cap.py b/python/tests/test_cap.py
@@ -0,0 +1,67 @@
+import os
+import unittest
+import json
+import logging
+
+# external imports
+from chainlib.eth.constant import ZERO_ADDRESS
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.tx import receipt
+from chainlib.eth.block import block_latest
+from chainlib.eth.address import to_checksum_address
+from hexathon import (
+ strip_0x,
+ add_0x,
+ )
+
+# local imports
+from erc20_demurrage_token import DemurrageToken
+
+# test imports
+from tests.base import TestDemurrageCap
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+testdir = os.path.dirname(__file__)
+
+
+class TestCap(TestDemurrageCap):
+
+ def test_cap_set(self):
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ o = c.supply_cap(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ cap = c.parse_supply_cap(r)
+ self.assertEqual(cap, self.default_supply_cap)
+
+
+ def test_cap(self):
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[1], self.default_supply_cap)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[2], 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+
+ def test_cap_first(self):
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = DemurrageToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[1], self.default_supply_cap + 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/test_single.py b/python/tests/test_single.py
@@ -18,7 +18,7 @@ from hexathon import (
from erc20_demurrage_token import DemurrageToken
# test imports
-from tests.base import TestDemurrageSingleNocap
+from tests.base import TestDemurrageSingle
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
@@ -26,7 +26,7 @@ logg = logging.getLogger()
testdir = os.path.dirname(__file__)
-class TestRedistributionSingle(TestDemurrageSingleNocap):
+class TestRedistributionSingle(TestDemurrageSingle):
def test_single_even_if_multiple(self):
diff --git a/solidity/DemurrageTokenMultiCap.sol b/solidity/DemurrageTokenMultiCap.sol
@@ -101,7 +101,7 @@ contract DemurrageTokenMultiCap {
// EIP173
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // EIP173
- constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _taxLevelMinute, uint256 _periodMinutes, address _defaultSinkAddress uint256 _supplyCap) public {
+ constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _taxLevelMinute, uint256 _periodMinutes, address _defaultSinkAddress, uint256 _supplyCap) public {
// ACL setup
owner = msg.sender;
minter[owner] = true;
@@ -121,7 +121,7 @@ contract DemurrageTokenMultiCap {
redistributions.push(initialRedistribution);
// Misc settings
- supplyCap = supplyCap;
+ supplyCap = _supplyCap;
sinkAddress = _defaultSinkAddress;
minimumParticipantSpend = 10 ** uint256(_decimals);
}
diff --git a/solidity/DemurrageTokenSingleCap.sol b/solidity/DemurrageTokenSingleCap.sol
@@ -0,0 +1,614 @@
+pragma solidity > 0.6.11;
+
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+contract DemurrageTokenSingleNocap {
+
+ // Redistribution bit field, with associated shifts and masks
+ // (Uses sub-byte boundaries)
+ bytes32[] public redistributions; // uint1(isFractional) | uint95(unused) | uint20(demurrageModifier) | uint36(participants) | uint72(value) | uint32(period)
+ uint8 constant shiftRedistributionPeriod = 0;
+ uint256 constant maskRedistributionPeriod = 0x00000000000000000000000000000000000000000000000000000000ffffffff; // (1 << 32) - 1
+ uint8 constant shiftRedistributionValue = 32;
+ uint256 constant maskRedistributionValue = 0x00000000000000000000000000000000000000ffffffffffffffffff00000000; // ((1 << 72) - 1) << 32
+ uint8 constant shiftRedistributionParticipants = 104;
+ uint256 constant maskRedistributionParticipants = 0x00000000000000000000000000000fffffffff00000000000000000000000000; // ((1 << 36) - 1) << 104
+ uint8 constant shiftRedistributionDemurrage = 140;
+ uint256 constant maskRedistributionDemurrage = 0x000000000000000000000000fffff00000000000000000000000000000000000; // ((1 << 20) - 1) << 140
+ uint8 constant shiftRedistributionIsFractional = 255;
+ uint256 constant maskRedistributionIsFractional = 0x8000000000000000000000000000000000000000000000000000000000000000; // 1 << 255
+
+ // Account bit field, with associated shifts and masks
+ // Mirrors structure of redistributions for consistency
+ mapping (address => bytes32) account; // uint152(unused) | uint32(period) | uint72(value)
+ uint8 constant shiftAccountValue = 0;
+ uint256 constant maskAccountValue = 0x0000000000000000000000000000000000000000000000ffffffffffffffffff; // (1 << 72) - 1
+ uint8 constant shiftAccountPeriod = 72;
+ uint256 constant maskAccountPeriod = 0x00000000000000000000000000000000000000ffffffff000000000000000000; // ((1 << 32) - 1) << 72
+
+ // Cached demurrage amount, ppm with 38 digit resolution
+ uint128 public demurrageAmount;
+
+ // Cached demurrage period; the period for which demurrageAmount was calculated
+ uint128 public demurragePeriod;
+
+ // Implements EIP172
+ address public owner;
+
+ address newOwner;
+
+ // Implements ERC20
+ string public name;
+
+ // Implements ERC20
+ string public symbol;
+
+ // Implements ERC20
+ uint256 public decimals;
+
+ // Implements ERC20
+ uint256 public totalSupply;
+
+ // Maximum amount of tokens that can be minted
+ uint256 public supplyCap;
+
+ // Minimum amount of (demurraged) tokens an account must spend to participate in redistribution for a particular period
+ uint256 public minimumParticipantSpend;
+
+ // 128 bit resolution of the demurrage divisor
+ // (this constant x 1000000 is contained within 128 bits)
+ uint256 constant ppmDivider = 100000000000000000000000000000000;
+
+ // Timestamp of start of periods (time which contract constructor was called)
+ uint256 public immutable periodStart;
+
+ // Duration of a single redistribution period in seconds
+ uint256 public immutable periodDuration;
+
+ // Demurrage in ppm per minute
+ uint256 public immutable taxLevel;
+
+ // Addresses allowed to mint new tokens
+ mapping (address => bool) minter;
+
+ // Storage for ERC20 approve/transferFrom methods
+ mapping (address => mapping (address => uint256 ) ) allowance; // holder -> spender -> amount (amount is subject to demurrage)
+
+ // Address to send unallocated redistribution tokens
+ address sinkAddress;
+
+ // Implements ERC20
+ event Transfer(address indexed _from, address indexed _to, uint256 _value);
+
+ // Implements ERC20
+ event Approval(address indexed _owner, address indexed _spender, uint256 _value);
+
+ // New tokens minted
+ event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
+
+ // New demurrage cache milestone calculated
+ event Decayed(uint256 indexed _period, uint256 indexed _periodCount, uint256 indexed _oldAmount, uint256 _newAmount);
+
+ // When a new period threshold has been crossed
+ event Period(uint256 _period);
+
+ // Redistribution applied on a single eligible account
+ event Redistribution(address indexed _account, uint256 indexed _period, uint256 _value);
+
+ // Temporary event used in development, will be removed on prod
+ event Debug(bytes32 _foo);
+
+ // EIP173
+ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // EIP173
+
+ constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _taxLevelMinute, uint256 _periodMinutes, address _defaultSinkAddress, uint256 _supplyCap) public {
+ // ACL setup
+ owner = msg.sender;
+ minter[owner] = true;
+
+ // ERC20 setup
+ name = _name;
+ symbol = _symbol;
+ decimals = _decimals;
+
+ // Demurrage setup
+ periodStart = block.timestamp;
+ periodDuration = _periodMinutes * 60;
+ demurrageAmount = uint128(ppmDivider * 1000000); // Represents 38 decimal places
+ demurragePeriod = 1;
+ taxLevel = _taxLevelMinute; // Represents 38 decimal places
+ bytes32 initialRedistribution = toRedistribution(0, 1000000, 0, 1);
+ redistributions.push(initialRedistribution);
+
+ // Misc settings
+ supplyCap = _supplyCap;
+ sinkAddress = _defaultSinkAddress;
+ minimumParticipantSpend = 10 ** uint256(_decimals);
+ }
+
+ // Given address will be allowed to call the mintTo() function
+ function addMinter(address _minter) public returns (bool) {
+ require(msg.sender == owner);
+ minter[_minter] = true;
+ return true;
+ }
+
+ // Given address will no longer be allowed to call the mintTo() function
+ function removeMinter(address _minter) public returns (bool) {
+ require(msg.sender == owner || _minter == msg.sender);
+ minter[_minter] = false;
+ return true;
+ }
+
+ /// Implements ERC20
+ function balanceOf(address _account) public view returns (uint256) {
+ uint256 baseBalance;
+ uint256 currentDemurragedAmount;
+ uint256 periodCount;
+
+ baseBalance = baseBalanceOf(_account);
+
+ periodCount = actualPeriod() - demurragePeriod;
+
+ currentDemurragedAmount = uint128(decayBy(demurrageAmount, periodCount));
+
+ return (baseBalance * currentDemurragedAmount) / (ppmDivider * 1000000);
+ }
+
+ /// Balance unmodified by demurrage
+ function baseBalanceOf(address _account) public view returns (uint256) {
+ return uint256(account[_account]) & maskAccountValue;
+ }
+
+ /// Increases base balance for a single account
+ function increaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
+ uint256 oldBalance;
+ uint256 newBalance;
+ uint256 workAccount;
+
+ workAccount = uint256(account[_account]);
+
+ if (_delta == 0) {
+ return false;
+ }
+
+ oldBalance = baseBalanceOf(_account);
+ newBalance = oldBalance + _delta;
+ require(uint160(newBalance) > uint160(oldBalance), 'ERR_WOULDWRAP'); // revert if increase would result in a wrapped value
+ workAccount &= (~maskAccountValue);
+ workAccount |= (newBalance & maskAccountValue);
+ account[_account] = bytes32(workAccount);
+ return true;
+ }
+
+ /// Decreases base balance for a single account
+ function decreaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
+ uint256 oldBalance;
+ uint256 newBalance;
+ uint256 workAccount;
+
+ workAccount = uint256(account[_account]);
+
+ if (_delta == 0) {
+ return false;
+ }
+
+ oldBalance = baseBalanceOf(_account);
+ require(oldBalance >= _delta, 'ERR_OVERSPEND'); // overspend guard
+ newBalance = oldBalance - _delta;
+ workAccount &= (~maskAccountValue);
+ workAccount |= (newBalance & maskAccountValue);
+ account[_account] = bytes32(workAccount);
+ return true;
+ }
+
+ // Creates new tokens out of thin air, and allocates them to the given address
+ // Triggers tax
+ function mintTo(address _beneficiary, uint256 _amount) external returns (bool) {
+ uint256 baseAmount;
+
+ require(minter[msg.sender]);
+ require(_amount + totalSupply <= supplyCap);
+
+ changePeriod();
+ baseAmount = _amount;
+ totalSupply += _amount;
+ increaseBaseBalance(_beneficiary, baseAmount);
+ emit Mint(msg.sender, _beneficiary, _amount);
+ saveRedistributionSupply();
+ return true;
+ }
+
+ // Deserializes the redistribution word
+ // uint1(isFractional) | uint95(unused) | uint20(demurrageModifier) | uint36(participants) | uint72(value) | uint32(period)
+ function toRedistribution(uint256 _participants, uint256 _demurrageModifierPpm, uint256 _value, uint256 _period) private pure returns(bytes32) {
+ bytes32 redistribution;
+
+ redistribution |= bytes32((_demurrageModifierPpm << shiftRedistributionDemurrage) & maskRedistributionDemurrage);
+ redistribution |= bytes32((_participants << shiftRedistributionParticipants) & maskRedistributionParticipants);
+ redistribution |= bytes32((_value << shiftRedistributionValue) & maskRedistributionValue);
+ redistribution |= bytes32(_period & maskRedistributionPeriod);
+ return redistribution;
+ }
+
+ // Serializes the demurrage period part of the redistribution word
+ function toRedistributionPeriod(bytes32 redistribution) public pure returns (uint256) {
+ return uint256(redistribution) & maskRedistributionPeriod;
+ }
+
+ // Serializes the supply part of the redistribution word
+ function toRedistributionSupply(bytes32 redistribution) public pure returns (uint256) {
+ return (uint256(redistribution) & maskRedistributionValue) >> shiftRedistributionValue;
+ }
+
+ // Serializes the number of participants part of the redistribution word
+ function toRedistributionParticipants(bytes32 redistribution) public pure returns (uint256) {
+ return (uint256(redistribution) & maskRedistributionParticipants) >> shiftRedistributionParticipants;
+ }
+
+ // Serializes the number of participants part of the redistribution word
+ function toRedistributionDemurrageModifier(bytes32 redistribution) public pure returns (uint256) {
+ return (uint256(redistribution) & maskRedistributionDemurrage) >> shiftRedistributionDemurrage;
+ }
+
+ // Client accessor to the redistributions array length
+ function redistributionCount() public view returns (uint256) {
+ return redistributions.length;
+ }
+
+ // Add number of participants for the current redistribution period by one
+ function incrementRedistributionParticipants() private returns (bool) {
+ bytes32 currentRedistribution;
+ uint256 tmpRedistribution;
+ uint256 participants;
+
+ currentRedistribution = redistributions[redistributions.length-1];
+ participants = toRedistributionParticipants(currentRedistribution) + 1;
+ tmpRedistribution = uint256(currentRedistribution);
+ tmpRedistribution &= (~maskRedistributionParticipants);
+ tmpRedistribution |= ((participants << shiftRedistributionParticipants) & maskRedistributionParticipants);
+
+ redistributions[redistributions.length-1] = bytes32(tmpRedistribution);
+
+ return true;
+ }
+
+ // Save the current total supply amount to the current redistribution period
+ function saveRedistributionSupply() private returns (bool) {
+ uint256 currentRedistribution;
+
+ currentRedistribution = uint256(redistributions[redistributions.length-1]);
+ currentRedistribution &= (~maskRedistributionValue);
+ currentRedistribution |= (totalSupply << shiftRedistributionValue);
+
+ redistributions[redistributions.length-1] = bytes32(currentRedistribution);
+ return true;
+ }
+
+ // Get the demurrage period of the current block number
+ function actualPeriod() public view returns (uint128) {
+ return uint128((block.timestamp - periodStart) / periodDuration + 1);
+ }
+
+ // Add an entered demurrage period to the redistribution array
+ function checkPeriod() private view returns (bytes32) {
+ bytes32 lastRedistribution;
+ uint256 currentPeriod;
+
+ lastRedistribution = redistributions[redistributions.length-1];
+ currentPeriod = this.actualPeriod();
+ if (currentPeriod <= toRedistributionPeriod(lastRedistribution)) {
+ return bytes32(0x00);
+ }
+ return lastRedistribution;
+ }
+
+ // Deserialize the pemurrage period for the given account is participating in
+ function accountPeriod(address _account) public view returns (uint256) {
+ return (uint256(account[_account]) & maskAccountPeriod) >> shiftAccountPeriod;
+ }
+
+ // Save the given demurrage period as the currently participation period for the given address
+ function registerAccountPeriod(address _account, uint256 _period) private returns (bool) {
+ account[_account] &= bytes32(~maskAccountPeriod);
+ account[_account] |= bytes32((_period << shiftAccountPeriod) & maskAccountPeriod);
+ incrementRedistributionParticipants();
+ return true;
+ }
+
+ // Determine whether the unit number is rounded down, rounded up or evenly divides.
+ // Returns 0 if evenly distributed, or the remainder as a positive number
+ // A _numParts value 0 will be interpreted as the value 1
+ function remainder(uint256 _numParts, uint256 _sumWhole) public pure returns (uint256) {
+ uint256 unit;
+ uint256 truncatedResult;
+
+ if (_numParts == 0) { // no division by zero please
+ revert('ERR_NUMPARTS_ZERO');
+ }
+ require(_numParts < _sumWhole); // At least you are never LESS than the sum of your parts. Think about that.
+
+ unit = _sumWhole / _numParts;
+ truncatedResult = unit * _numParts;
+ return _sumWhole - truncatedResult;
+ }
+
+ // Returns the amount sent to the sink address
+ function applyDefaultRedistribution(bytes32 _redistribution) private returns (uint256) {
+ uint256 redistributionSupply;
+ uint256 redistributionPeriod;
+ uint256 unit;
+ uint256 truncatedResult;
+
+ redistributionSupply = toRedistributionSupply(_redistribution);
+
+ unit = (redistributionSupply * taxLevel) / 1000000;
+ truncatedResult = (unit * 1000000) / taxLevel;
+
+ if (truncatedResult < redistributionSupply) {
+ redistributionPeriod = toRedistributionPeriod(_redistribution); // since we reuse period here, can possibly be optimized by passing period instead
+ redistributions[redistributionPeriod-1] &= bytes32(~maskRedistributionParticipants); // just to be safe, zero out all participant count data, in this case there will be only one
+ redistributions[redistributionPeriod-1] |= bytes32(maskRedistributionIsFractional | (1 << shiftRedistributionParticipants));
+ }
+
+ increaseBaseBalance(sinkAddress, unit / ppmDivider);
+ return unit;
+ }
+
+ // sets the remainder bit for the given period and books the remainder to the sink address balance
+ // returns false if no change was made
+ function applyRemainderOnPeriod(uint256 _remainder, uint256 _period) private returns (bool) {
+ uint256 periodSupply;
+
+ if (_remainder == 0) {
+ return false;
+ }
+
+ // TODO: is this needed?
+ redistributions[_period-1] |= bytes32(maskRedistributionIsFractional);
+
+ periodSupply = toRedistributionSupply(redistributions[_period-1]);
+ increaseBaseBalance(sinkAddress, periodSupply - _remainder);
+ return true;
+ }
+
+
+ // Calculate and cache the demurrage value corresponding to the (period of the) time of the method call
+ function applyDemurrage() public returns (bool) {
+ uint128 epochPeriodCount;
+ uint128 periodCount;
+ uint256 lastDemurrageAmount;
+ uint256 newDemurrageAmount;
+
+ epochPeriodCount = actualPeriod();
+ periodCount = epochPeriodCount - demurragePeriod;
+ if (periodCount == 0) {
+ return false;
+ }
+ lastDemurrageAmount = demurrageAmount;
+ demurrageAmount = uint128(decayBy(lastDemurrageAmount, periodCount));
+ demurragePeriod = epochPeriodCount;
+ emit Decayed(epochPeriodCount, periodCount, lastDemurrageAmount, demurrageAmount);
+ return true;
+ }
+
+ // Return timestamp of start of period threshold
+ function getPeriodTimeDelta(uint256 _periodCount) public view returns (uint256) {
+ return periodStart + (_periodCount * periodDuration);
+ }
+
+ // Amount of demurrage cycles inbetween the current timestamp and the given target time
+ function demurrageCycles(uint256 _target) public view returns (uint256) {
+ return (block.timestamp - _target) / 60;
+ }
+
+ // Recalculate the demurrage modifier for the new period
+ function changePeriod() public returns (bool) {
+ bytes32 currentRedistribution;
+ bytes32 nextRedistribution;
+ uint256 currentPeriod;
+ uint256 currentParticipants;
+ uint256 currentRemainder;
+ uint256 currentDemurrageAmount;
+ uint256 nextRedistributionDemurrage;
+ uint256 demurrageCounts;
+ uint256 periodTimestamp;
+ uint256 nextPeriod;
+
+ currentRedistribution = checkPeriod();
+ if (currentRedistribution == bytes32(0x00)) {
+ return false;
+ }
+
+ currentPeriod = toRedistributionPeriod(currentRedistribution);
+ nextPeriod = currentPeriod + 1;
+ periodTimestamp = getPeriodTimeDelta(currentPeriod);
+
+ applyDemurrage();
+ currentDemurrageAmount = demurrageAmount;
+
+ demurrageCounts = demurrageCycles(periodTimestamp);
+ if (demurrageCounts > 0) {
+ nextRedistributionDemurrage = growBy(currentDemurrageAmount, demurrageCounts) / ppmDivider;
+ } else {
+ nextRedistributionDemurrage = currentDemurrageAmount / ppmDivider;
+ }
+
+ nextRedistribution = toRedistribution(0, nextRedistributionDemurrage, totalSupply, nextPeriod);
+ redistributions.push(nextRedistribution);
+
+ //currentParticipants = toRedistributionParticipants(currentRedistribution);
+ //if (currentParticipants == 0) {
+ currentRemainder = applyDefaultRedistribution(currentRedistribution);
+ //} else {
+ // currentRemainder = remainder(currentParticipants, totalSupply); // we can use totalSupply directly because it will always be the same as the recorded supply on the current redistribution
+ // applyRemainderOnPeriod(currentRemainder, currentPeriod);
+ //}
+ emit Period(nextPeriod);
+ return true;
+ }
+
+ // Reverse a value reduced by demurrage by the given period to its original value
+ function growBy(uint256 _value, uint256 _period) public view returns (uint256) {
+ uint256 valueFactor;
+ uint256 truncatedTaxLevel;
+
+ valueFactor = 1000000;
+ truncatedTaxLevel = taxLevel / ppmDivider;
+
+ for (uint256 i = 0; i < _period; i++) {
+ valueFactor = valueFactor + ((valueFactor * truncatedTaxLevel) / 1000000);
+ }
+ return (valueFactor * _value) / 1000000;
+ }
+
+ // Calculate a value reduced by demurrage by the given period
+ // TODO: higher precision if possible
+ function decayBy(uint256 _value, uint256 _period) public view returns (uint256) {
+ uint256 valueFactor;
+ uint256 truncatedTaxLevel;
+
+ valueFactor = 1000000;
+ truncatedTaxLevel = taxLevel / ppmDivider;
+
+ for (uint256 i = 0; i < _period; i++) {
+ valueFactor = valueFactor - ((valueFactor * truncatedTaxLevel) / 1000000);
+ }
+ return (valueFactor * _value) / 1000000;
+ }
+
+ // If the given account is participating in a period and that period has been crossed
+ // THEN increase the base value of the account with its share of the value reduction of the period
+ function applyRedistributionOnAccount(address _account) public returns (bool) {
+// bytes32 periodRedistribution;
+// uint256 supply;
+// uint256 participants;
+// uint256 baseValue;
+// uint256 value;
+ uint256 period;
+// uint256 demurrage;
+//
+ period = accountPeriod(_account);
+ if (period == 0 || period >= actualPeriod()) {
+ return false;
+ }
+// periodRedistribution = redistributions[period-1];
+// participants = toRedistributionParticipants(periodRedistribution);
+// if (participants == 0) {
+// return false;
+// }
+//
+// supply = toRedistributionSupply(periodRedistribution);
+// demurrage = toRedistributionDemurrageModifier(periodRedistribution);
+// baseValue = ((supply / participants) * (taxLevel / 1000000)) / ppmDivider;
+// value = (baseValue * demurrage) / 1000000;
+//
+// // zero out period for the account
+ account[_account] &= bytes32(~maskAccountPeriod);
+// increaseBaseBalance(_account, value);
+//
+// emit Redistribution(_account, period, value);
+ return true;
+ }
+
+ // Inflates the given amount according to the current demurrage modifier
+ function toBaseAmount(uint256 _value) public view returns (uint256) {
+ //return (_value * ppmDivider * 1000000) / toDemurrageAmount(demurrageModifier);
+ return (_value * ppmDivider * 1000000) / demurrageAmount;
+ }
+
+ // Implements ERC20, triggers tax and/or redistribution
+ function approve(address _spender, uint256 _value) public returns (bool) {
+ uint256 baseValue;
+
+ changePeriod();
+ //applyRedistributionOnAccount(msg.sender);
+
+ baseValue = toBaseAmount(_value);
+ allowance[msg.sender][_spender] += baseValue;
+ emit Approval(msg.sender, _spender, _value);
+ return true;
+ }
+
+ // Implements ERC20, triggers tax and/or redistribution
+ function transfer(address _to, uint256 _value) public returns (bool) {
+ uint256 baseValue;
+ bool result;
+
+ changePeriod();
+ //applyRedistributionOnAccount(msg.sender);
+
+ baseValue = toBaseAmount(_value);
+ result = transferBase(msg.sender, _to, baseValue);
+ emit Transfer(msg.sender, _to, _value);
+ return result;
+ }
+
+
+ // Implements ERC20, triggers tax and/or redistribution
+ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
+ uint256 baseValue;
+ bool result;
+
+ changePeriod();
+ //applyRedistributionOnAccount(msg.sender);
+
+ baseValue = toBaseAmount(_value);
+ require(allowance[_from][msg.sender] >= baseValue);
+
+ result = transferBase(_from, _to, baseValue);
+ emit Transfer(_from, _to, _value);
+ return result;
+ }
+
+ // ERC20 transfer backend for transfer, transferFrom
+ function transferBase(address _from, address _to, uint256 _value) private returns (bool) {
+ uint256 period;
+
+ decreaseBaseBalance(_from, _value);
+ increaseBaseBalance(_to, _value);
+
+ period = actualPeriod();
+ if (_value >= minimumParticipantSpend && accountPeriod(_from) != period && _from != _to) {
+ registerAccountPeriod(_from, period);
+ }
+ return true;
+ }
+
+ // Implements EIP173
+ function transferOwnership(address _newOwner) public returns (bool) {
+ require(msg.sender == owner);
+ newOwner = _newOwner;
+ }
+
+ // Implements OwnedAccepter
+ function acceptOwnership() public returns (bool) {
+ address oldOwner;
+
+ require(msg.sender == newOwner);
+ oldOwner = owner;
+ owner = newOwner;
+ newOwner = address(0);
+ emit OwnershipTransferred(oldOwner, owner);
+ }
+
+ // Implements EIP165
+ function supportsInterface(bytes4 _sum) public pure returns (bool) {
+ if (_sum == 0xc6bb4b70) { // ERC20
+ return true;
+ }
+ if (_sum == 0x449a52f8) { // Minter
+ return true;
+ }
+ if (_sum == 0x01ffc9a7) { // EIP165
+ return true;
+ }
+ if (_sum == 0x9493f8b2) { // EIP173
+ return true;
+ }
+ if (_sum == 0x37a47be4) { // OwnedAccepter
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/solidity/Makefile b/solidity/Makefile
@@ -1,17 +1,16 @@
SOLC = /usr/bin/solc
-all: multi_nocap multi_cap single_nocap
-
+all: multi single
multi_nocap:
$(SOLC) DemurrageTokenMultiNocap.sol --abi --evm-version byzantium | awk 'NR>3' > DemurrageTokenMultiNocap.json
$(SOLC) DemurrageTokenMultiNocap.sol --bin --evm-version byzantium | awk 'NR>3' > DemurrageTokenMultiNocap.bin
- truncate -s -1 DemurrageTokenMultiCap.bin
+ truncate -s -1 DemurrageTokenMultiNocap.bin
multi_cap:
$(SOLC) DemurrageTokenMultiCap.sol --abi --evm-version byzantium | awk 'NR>3' > DemurrageTokenMultiCap.json
$(SOLC) DemurrageTokenMultiCap.sol --bin --evm-version byzantium | awk 'NR>3' > DemurrageTokenMultiCap.bin
- truncate -s -1 DemurrageTokenMultiNocap.bin
+ truncate -s -1 DemurrageTokenMultiCap.bin
multi: multi_nocap multi_cap
@@ -20,6 +19,13 @@ single_nocap:
$(SOLC) DemurrageTokenSingleNocap.sol --bin --evm-version byzantium | awk 'NR>3' > DemurrageTokenSingleNocap.bin
truncate -s -1 DemurrageTokenSingleNocap.bin
+single_cap:
+ $(SOLC) DemurrageTokenSingleCap.sol --abi --evm-version byzantium | awk 'NR>3' > DemurrageTokenSingleCap.json
+ $(SOLC) DemurrageTokenSingleCap.sol --bin --evm-version byzantium | awk 'NR>3' > DemurrageTokenSingleCap.bin
+ truncate -s -1 DemurrageTokenSingleCap.bin
+
+single: single_nocap single_cap
+
test: all
python ../python/tests/test_basic.py
python ../python/tests/test_period.py