Consensys / mythril

Security analysis tool for EVM bytecode. Supports smart contracts built for Ethereum, Hedera, Quorum, Vechain, Rootstock, Tron and other EVM-compatible blockchains.
https://mythx.io/
MIT License
3.85k stars 736 forks source link

SWC 123 and 127 caught by Harvey but not Mythril - why? #936

Closed rocky closed 3 years ago

rocky commented 5 years ago

Description

Here are 3 issues, (one SWC 123, and two SWC-127) of something that the fuzzer Harvey catches that Mythril doesn't. Why? And should Mythril also detect it?

How to Reproduce

$ myth -x -f AssertRegistry.bc

==== Integer Overflow ====
SWC ID: 101
Severity: High
Contract: MAIN
Function name: _function_0x6a0cc449
PC address: 1202
Estimated Gas Usage: 555 - 650
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.
--------------------

==== Exception State ====
SWC ID: 110
Severity: Low
Contract: MAIN
Function name: _function_0x0409efcd
PC address: 2254
Estimated Gas Usage: 678 - 773
A reachable exception has been detected.
It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------

==== Exception State ====
SWC ID: 110
Severity: Low
Contract: MAIN
Function name: _function_0x2854af99
PC address: 3545
Estimated Gas Usage: 718 - 813
A reachable exception has been detected.
It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------
$

AssertRegistry.bc is:

60806040523480156200001157600080fd5b5060405160408062005aac833981018060405260408110156200003357600080fd5b81019080805190602001909291908051906020019092919050505062000068336200034a640100000000026401000000009004565b6000600160006101000a81548160ff021916908315150217905550336001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a381600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506004608060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600015158152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160146101000a81548160ff02191690831515021790555060608201518160010160156101000a81548160ff02191690831515021790555050505060076000908060018154018082558091505090600182039060005260206000200160009091929091909150555050506200050c565b6200036e816000620003b46401000000000262002140179091906401000000009004565b8073ffffffffffffffffffffffffffffffffffffffff167f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f860405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515620003f157600080fd5b6200040c828262000477640100000000026401000000009004565b1515156200041957600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515620004b557600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b615590806200051c6000396000f3fe6080604052600436106200013f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630409efcd14620001445780630aac5dfd146200018d5780632482855714620001bb5780632854af99146200022c5780633f4ba83a146200026b57806346fbf68e146200028557806348abcf8314620002f2578063494fd749146200039e5780635460303014620003cc5780635c975abb14620003fa5780636a0cc449146200042c5780636ef8d66d1462000516578063715018a6146200053057806382dc1ec4146200054a5780638456cb59146200059f5780638da5cb5b14620005b95780638f32d59b14620006135780639ac7876c1462000645578063b3e444a714620006cc578063ec9da59e1462000794578063f2fde38b14620007e9578063fb7ad2e3146200083e575b600080fd5b3480156200015157600080fd5b506200018b600480360360408110156200016a57600080fd5b810190808035906020019092919080359060200190929190505050620008a7565b005b3480156200019a57600080fd5b50620001a562000c4e565b6040518082815260200191505060405180910390f35b348015620001c857600080fd5b50620001d362000c5e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101562000218578082015181840152602081019050620001fb565b505050509050019250505060405180910390f35b3480156200023957600080fd5b5062000269600480360360208110156200025257600080fd5b810190808035906020019092919050505062000db1565b005b3480156200027857600080fd5b506200028362000ecb565b005b3480156200029257600080fd5b50620002d860048036036020811015620002ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505062000f7e565b604051808215151515815260200191505060405180910390f35b348015620002ff57600080fd5b5062000345600480360360208110156200031857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505062000f9d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156200038a5780820151818401526020810190506200036d565b505050509050019250505060405180910390f35b348015620003ab57600080fd5b50620003b66200104c565b6040518082815260200191505060405180910390f35b348015620003d957600080fd5b50620003e4620011ee565b6040518082815260200191505060405180910390f35b3480156200040757600080fd5b506200041262001201565b604051808215151515815260200191505060405180910390f35b3480156200043957600080fd5b506200051460048036036101008110156200045357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156200049157600080fd5b820183602082011115620004a457600080fd5b80359060200191846001830284011164010000000083111715620004c757600080fd5b909192939192939080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505062001218565b005b3480156200052357600080fd5b506200052e620017d6565b005b3480156200053d57600080fd5b5062000548620017e3565b005b3480156200055757600080fd5b506200059d600480360360208110156200057057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050620018b8565b005b348015620005ac57600080fd5b50620005b7620018dd565b005b348015620005c657600080fd5b50620005d162001990565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156200062057600080fd5b506200062b620019b9565b604051808215151515815260200191505060405180910390f35b3480156200065257600080fd5b50620006ca600480360360c08110156200066b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505062001a10565b005b348015620006d957600080fd5b506200070960048036036020811015620006f257600080fd5b810190808035906020019092919050505062001bd9565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001831515151581526020018215151515815260200194505050505060405180910390f35b348015620007a157600080fd5b50620007e760048036036020811015620007ba57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505062001cff565b005b348015620007f657600080fd5b506200083c600480360360208110156200080f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505062001d59565b005b3480156200084b57600080fd5b5062000891600480360360208110156200086457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505062001d7d565b6040518082815260200191505060405180910390f35b803373ffffffffffffffffffffffffffffffffffffffff16600482815481101515620008cf57fe5b906000526020600020906002020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156200092457600080fd5b60006004838154811015156200093657fe5b906000526020600020906002020190508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ad7ee8326040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b158015620009cd57600080fd5b505afa158015620009e2573d6000803e3d6000fd5b505050506040513d6020811015620009f957600080fd5b810190808051906020019092919050505062000a27670de0b6b3a76400008662001dc690919063ffffffff16565b1015151562000a3557600080fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd338360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801562000b5357600080fd5b505af115801562000b68573d6000803e3d6000fd5b505050506040513d602081101562000b7f57600080fd5b8101908080519060200190929190505050151562000b9c57600080fd5b60018160010160156101000a81548160ff0219169083151502179055507f9490153ccd10164d959040e4e2c23d989eea12bb8f5a5560e983e70ffa51d8c9838260010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150505050565b6000600160048054905003905090565b60606000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501415151562000d1c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6d757374206861766520616e206163746976652061737365740000000000000081525060200191505060405180910390fd5b600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801562000da757602002820191906000526020600020905b81548152602001906001019080831162000d92575b5050505050905090565b80600073ffffffffffffffffffffffffffffffffffffffff1660048281548110151562000dda57fe5b906000526020600020906002020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151562000e3057600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151562000e8d57600080fd5b600160048381548110151562000e9f57fe5b906000526020600020906002020160010160146101000a81548160ff0219169083151502179055505050565b62000ed63362000f7e565b151562000ee257600080fd5b600160009054906101000a900460ff16151562000efe57600080fd5b6000600160006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b600062000f9682600062001df290919063ffffffff16565b9050919050565b606062000fa9620019b9565b151562000fb557600080fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156200104057602002820191906000526020600020905b8154815260200190600101908083116200102b575b50505050509050919050565b6000806000600190505b60016004805490500381111515620011e657600073ffffffffffffffffffffffffffffffffffffffff166004828154811015156200109057fe5b906000526020600020906002020160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515620011d857620011d5600482815481101515620010f457fe5b906000526020600020906002020160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630f76c1146040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156200118857600080fd5b505afa1580156200119d573d6000803e3d6000fd5b505050506040513d6020811015620011b457600080fd5b81019080805190602001909291905050508362001e8790919063ffffffff16565b91505b808060010191505062001056565b508091505090565b6000620011fc600762001ea9565b905090565b6000600160009054906101000a900460ff16905090565b600089600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a8a8a8a8a8a8a8a62001250620021f4565b808b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018060200188815260200187815260200186815260200185815260200184815260200183815260200182810382528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050509b505050505050505050505050604051809103906000f08015801562001332573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663983b2d56600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b158015620013f357600080fd5b505af115801562001408573d6000803e3d6000fd5b50505050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a356e79182886040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015620014d257600080fd5b505af1158015620014e7573d6000803e3d6000fd5b50505050620014f562002205565b6080604051908101604052808c73ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600015158152509050600060016004839080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160146101000a81548160ff02191690831515021790555060608201518160010160156101000a81548160ff0219169083151502179055505050039050600560008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081908060018154018082558091505090600182039060005260206000200160009091929091909150555080600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060078690806001815401808255809150509060018203906000526020600020016000909192909190915055507ffa059abe2916f4d57f1c7b4f97b9258577651dd2b526a041e78635f804d5d763838d83604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050505050505050505050565b620017e13362001eda565b565b620017ed620019b9565b1515620017f957600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166001809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360006001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b620018c33362000f7e565b1515620018cf57600080fd5b620018da8162001f36565b50565b620018e83362000f7e565b1515620018f457600080fd5b600160009054906101000a900460ff161515156200191157600080fd5b60018060006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1565b60006001809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006001809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b62001a1a620019b9565b151562001a2657600080fd5b6000600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415151562001a7657600080fd5b8573ffffffffffffffffffffffffffffffffffffffff1663158e89a986868686866040518663ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018086815260200185815260200184815260200183815260200182815260200195505050505050600060405180830381600087803b15801562001b0657600080fd5b505af115801562001b1b573d6000803e3d6000fd5b505050506000600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508360078281548110151562001b7457fe5b90600052602060002001819055508673ffffffffffffffffffffffffffffffffffffffff167fc421279808c21ea1a5078cb61b852c933f2d541137749d0e79577590a1ba704f826040518082815260200191505060405180910390a250505050505050565b60008060008084600073ffffffffffffffffffffffffffffffffffffffff1660048281548110151562001c0857fe5b906000526020600020906002020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151562001c5e57600080fd5b600060048781548110151562001c7057fe5b906000526020600020906002020190508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1695508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508060010160149054906101000a900460ff1693508060010160159054906101000a900460ff16925050509193509193565b62001d09620019b9565b151562001d1557600080fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b62001d63620019b9565b151562001d6f57600080fd5b62001d7a8162001f92565b50565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000808211151562001dd757600080fd5b6000828481151562001de557fe5b0490508091505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415151562001e3057600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080828401905083811015151562001e9f57600080fd5b8091505092915050565b60008160605260005b825481101562001ed45781816020606020015401915060018101905062001eb2565b50919050565b62001ef08160006200208d90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e60405160405180910390a250565b62001f4c8160006200214090919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f860405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151562001fcf57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166001809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806001806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515620020ca57600080fd5b620020d6828262001df2565b1515620020e257600080fd5b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156200217d57600080fd5b62002189828262001df2565b1515156200219657600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b604051613306806200225f83390190565b608060405190810160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600015158152509056fe60806040526012600655600c60075561016d600855620151806009553480156200002857600080fd5b50604051620033063803806200330683398101806040526101208110156200004f57600080fd5b81019080805190602001909291908051906020019092919080516401000000008111156200007c57600080fd5b828101905060208101848111156200009357600080fd5b8151856001820283011164010000000082111715620000b157600080fd5b5050929190602001805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190505050846200011333620002bd640100000000026401000000009004565b6000811115156200012357600080fd5b806004819055505033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a386600b9080519060200190620002019291906200047f565b5085600c8190555083600d8190555082600e8190555042600f81905550816010819055508060118190555087601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050505050506200052e565b620002e1816003620003276401000000000262002c3d179091906401000000009004565b8073ffffffffffffffffffffffffffffffffffffffff167f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f660405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156200036457600080fd5b6200037f8282620003ea640100000000026401000000009004565b1515156200038c57600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156200042857600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004c257805160ff1916838001178555620004f3565b82800160010185558215620004f3579182015b82811115620004f2578251825591602001919060010190620004d5565b5b50905062000502919062000506565b5090565b6200052b91905b80821115620005275760008160009055506001016200050d565b5090565b90565b612dc8806200053e6000396000f3fe6080604052600436106101ac576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde0314610226578063095ea7b3146102b65780630f76c11414610329578063158e89a91461035457806318160ddd146103b757806323b872dd146103e2578063313ce5671461047557806334f2114a146104a0578063355274ea146104b757806339509351146104e257806340c10f191461055557806342966c68146105c857806359c6ecd6146106035780635da139ab1461062e57806370a0823114610659578063715018a6146106be57806379cc6790146106d5578063821f1219146107305780638da5cb5b1461075b5780638f32d59b146107b2578063983b2d56146107e157806398650275146108325780639ac9940f14610849578063a457c2d7146108a0578063a9059cbb14610913578063aa271e1a14610986578063ad7ee832146109ef578063af214cf314610a1a578063b8613ae814610a45578063cf09e0d014610a70578063dd62ed3e14610a9b578063e0b9d9b014610b20578063e2608c9e14610b4b578063f2fde38b14610b76575b600034141515610224576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6e6f7420616363657074696e672045544800000000000000000000000000000081525060200191505060405180910390fd5b005b34801561023257600080fd5b5061023b610bc7565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561027b578082015181840152602081019050610260565b50505050905090810190601f1680156102a85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102c257600080fd5b5061030f600480360360408110156102d957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c65565b604051808215151515815260200191505060405180910390f35b34801561033557600080fd5b5061033e610d92565b6040518082815260200191505060405180910390f35b34801561036057600080fd5b506103b5600480360360a081101561037757600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610dec565b005b3480156103c357600080fd5b506103cc610e29565b6040518082815260200191505060405180910390f35b3480156103ee57600080fd5b5061045b6004803603606081101561040557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e33565b604051808215151515815260200191505060405180910390f35b34801561048157600080fd5b5061048a61103b565b6040518082815260200191505060405180910390f35b3480156104ac57600080fd5b506104b5611041565b005b3480156104c357600080fd5b506104cc61179e565b6040518082815260200191505060405180910390f35b3480156104ee57600080fd5b5061053b6004803603604081101561050557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506117a8565b604051808215151515815260200191505060405180910390f35b34801561056157600080fd5b506105ae6004803603604081101561057857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506119df565b604051808215151515815260200191505060405180910390f35b3480156105d457600080fd5b50610601600480360360208110156105eb57600080fd5b8101908080359060200190929190505050611a09565b005b34801561060f57600080fd5b50610618611a16565b6040518082815260200191505060405180910390f35b34801561063a57600080fd5b50610643611b1e565b6040518082815260200191505060405180910390f35b34801561066557600080fd5b506106a86004803603602081101561067c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b24565b6040518082815260200191505060405180910390f35b3480156106ca57600080fd5b506106d3611b6c565b005b3480156106e157600080fd5b5061072e600480360360408110156106f857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611c40565b005b34801561073c57600080fd5b50610745611c4e565b6040518082815260200191505060405180910390f35b34801561076757600080fd5b50610770611c54565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107be57600080fd5b506107c7611c7e565b604051808215151515815260200191505060405180910390f35b3480156107ed57600080fd5b506108306004803603602081101561080457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611cd6565b005b34801561083e57600080fd5b50610847611cf6565b005b34801561085557600080fd5b5061085e611d01565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ac57600080fd5b506108f9600480360360408110156108c357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611d27565b604051808215151515815260200191505060405180910390f35b34801561091f57600080fd5b5061096c6004803603604081101561093657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611f5e565b604051808215151515815260200191505060405180910390f35b34801561099257600080fd5b506109d5600480360360208110156109a957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f75565b604051808215151515815260200191505060405180910390f35b3480156109fb57600080fd5b50610a04611f92565b6040518082815260200191505060405180910390f35b348015610a2657600080fd5b50610a2f611f98565b6040518082815260200191505060405180910390f35b348015610a5157600080fd5b50610a5a612090565b6040518082815260200191505060405180910390f35b348015610a7c57600080fd5b50610a85612096565b6040518082815260200191505060405180910390f35b348015610aa757600080fd5b50610b0a60048036036040811015610abe57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061209c565b6040518082815260200191505060405180910390f35b348015610b2c57600080fd5b50610b35612123565b6040518082815260200191505060405180910390f35b348015610b5757600080fd5b50610b60612129565b6040518082815260200191505060405180910390f35b348015610b8257600080fd5b50610bc560048036036020811015610b9957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612209565b005b600b8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c5d5780601f10610c3257610100808354040283529160200191610c5d565b820191906000526020600020905b815481529060010190602001808311610c4057829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610ca257600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b600080610da5610da061179e565b612228565b9050610de6610dd5600f544203610dc76011548561227390919063ffffffff16565b61227390919063ffffffff16565b600c546122b190919063ffffffff16565b91505090565b610df4611c7e565b1515610dff57600080fd5b84600c8190555083600d8190555082600e8190555081601081905550806011819055505050505050565b6000600254905090565b6000610ec482600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122d290919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f4f8484846122f4565b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a3600190509392505050565b60065481565b600061104c33611b24565b141515156110e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001807f6d757374206861766520616e2061637469766520696e766573746d656e74206981526020017f6e2074686973206173736574000000000000000000000000000000000000000081525060400191505060405180910390fd5b60006110f2612129565b90506000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156111b157600080fd5b505afa1580156111c5573d6000803e3d6000fd5b505050506040513d60208110156111db57600080fd5b810190808051906020019092919050505090508181101561130a57601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f193061124884866122d290919063ffffffff16565b6040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156112cd57600080fd5b505af11580156112e1573d6000803e3d6000fd5b505050506040513d60208110156112f757600080fd5b8101908080519060200190929190505050505b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156113cf57600080fd5b505af11580156113e3573d6000803e3d6000fd5b505050506040513d60208110156113f957600080fd5b8101908080519060200190929190505050151561147e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f6661696c6564207472616e7366657272696e67205420746f6b656e730000000081525060200191505060405180910390fd5b61148f61148a33611b24565b611a09565b6000611499610e29565b141561179a576000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561155c57600080fd5b505afa158015611570573d6000803e3d6000fd5b505050506040513d602081101561158657600080fd5b81019080805190602001909291905050509050600081111561175f57601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561168957600080fd5b505af115801561169d573d6000803e3d6000fd5b505050506040513d60208110156116b357600080fd5b8101908080519060200190929190505050151561175e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f6661696c656420726566756e64696e672072656d61696e646572205420746f6b81526020017f656e7320746f206173736574206f776e6572000000000000000000000000000081525060400191505060405180910390fd5b5b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5050565b6000600454905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156117e557600080fd5b61187482600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122b190919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b60006119ea33611f75565b15156119f557600080fd5b6119ff83836124c0565b6001905092915050565b611a1333826124f8565b50565b600080611a2233611b24565b14151515611abe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001807f6d757374206861766520616e2061637469766520696e766573746d656e74206981526020017f6e2074686973206173736574000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000611ac933611b24565b90506000611ad682612228565b9050611b17611b06600f544203611af86011548561227390919063ffffffff16565b61227390919063ffffffff16565b600c546122b190919063ffffffff16565b9250505090565b600d5481565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611b74611c7e565b1515611b7f57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b611c4a828261264c565b5050565b60105481565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b611cdf33611f75565b1515611cea57600080fd5b611cf38161284a565b50565b611cff336128a4565b565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515611d6457600080fd5b611df382600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122d290919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b6000611f6b3384846122f4565b6001905092915050565b6000611f8b8260036128fe90919063ffffffff16565b9050919050565b600e5481565b600080611fa433611b24565b14151515612040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001807f6d757374206861766520616e2061637469766520696e766573746d656e74206981526020017f6e2074686973206173736574000000000000000000000000000000000000000081525060400191505060405180910390fd5b600061204b33611b24565b9050600061205882612992565b90506000612071600754836129c390919063ffffffff16565b90506120886010548261227390919063ffffffff16565b935050505090565b60115481565b600f5481565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600c5481565b60008061213533611b24565b141515156121d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001807f6d757374206861766520616e2061637469766520696e766573746d656e74206981526020017f6e2074686973206173736574000000000000000000000000000000000000000081525060400191505060405180910390fd5b60006121dc33611b24565b905060006121e982612228565b9050612202600f5442038261227390919063ffffffff16565b9250505090565b612211611c7e565b151561221c57600080fd5b612225816129ed565b50565b60008061223483612992565b9050600061224d600854836129c390919063ffffffff16565b90506000612266600954836129c390919063ffffffff16565b9050809350505050919050565b60008083141561228657600090506122ab565b6000828402905082848281151561229957fe5b041415156122a657600080fd5b809150505b92915050565b60008082840190508381101515156122c857600080fd5b8091505092915050565b60008282111515156122e357600080fd5b600082840390508091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415151561233057600080fd5b612381816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122d290919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612414816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122b190919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6004546124dd826124cf610e29565b6122b190919063ffffffff16565b111515156124ea57600080fd5b6124f48282612ae9565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415151561253457600080fd5b612549816002546122d290919063ffffffff16565b6002819055506125a0816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122d290919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b6126db81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122d290919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061276582826124f8565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a35050565b61285e816003612c3d90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f660405160405180910390a250565b6128b8816003612ced90919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669260405160405180910390a250565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415151561293b57600080fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60006129bc60646129ae600d548561227390919063ffffffff16565b6129c390919063ffffffff16565b9050919050565b600080821115156129d357600080fd5b600082848115156129e057fe5b0490508091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612a2957600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515612b2557600080fd5b612b3a816002546122b190919063ffffffff16565b600281905550612b91816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122b190919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612c7957600080fd5b612c8382826128fe565b151515612c8f57600080fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612d2957600080fd5b612d3382826128fe565b1515612d3e57600080fd5b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505056fea165627a7a72305820d88dc01ed340e689f9d00e580fd8072f848808dbc7da073abb513ac1f0fc10620029a165627a7a72305820f4063b1af1c18d610cc83e16b139e81fecef65d039787acc7f756e42065ef5000029

Expected behavior

Here is what harvey-cli reports:

$ cat AssetRegistry.json | harvey-cli
{
    "issues": [
        {
            "swc-id": "SWC-123",
            "title": "precondition violation",
            "details": "Precondition violations should be avoided when passing inputs to other contracts. Make sure your contracts provide only valid inputs to both callees (e.g, via passed arguments) and callers (e.g., via return values).",
            "code-hash": "0xd6a271e58404cfd95406d16bdc12f24f8e33aee4b87ebec2fb1d1c331091954a",
            "function-signature": "00000000",
            "bytecode-offset": 290,
            "stack-trace": [
                {
                    "op-code": "CREATE",
                    "code-hash": "0xb17b583de9bdbb8dbda78285df7abbe982b373490723cc2694896c87bc8dae64",
                    "function-signature": "6a0cc449",
                    "bytecode-offset": 4895
                }
            ],
            "time-secs": 4.497308861
        },
        {
            "swc-id": "SWC-110",
            "title": "assertion violation",
            "details": "Assertion violations should be avoided within your contracts. Make sure that your program logic is correct (e.g., no division by zero) and that you add appropriate validation for inputs from both callers (e.g, passed arguments) and callees (e.g., return values). If your contracts are written in Solidity you may want to use the \"require\" language construct for this purpose.",
            "code-hash": "0xb17b583de9bdbb8dbda78285df7abbe982b373490723cc2694896c87bc8dae64",
            "function-signature": "2854af99",
            "bytecode-offset": 3545,
            "stack-trace": [],
            "time-secs": 6.412805462
        },
        {
            "swc-id": "SWC-110",
            "title": "assertion violation",
            "details": "Assertion violations should be avoided within your contracts. Make sure that your program logic is correct (e.g., no division by zero) and that you add appropriate validation for inputs from both callers (e.g, passed arguments) and callees (e.g., return values). If your contracts are written in Solidity you may want to use the \"require\" language construct for this purpose.",
            "code-hash": "0xb17b583de9bdbb8dbda78285df7abbe982b373490723cc2694896c87bc8dae64",
            "function-signature": "0409efcd",
            "bytecode-offset": 2254,
            "stack-trace": [],
            "time-secs": 6.660975065
        },
        {
            "swc-id": "SWC-110",
            "title": "assertion violation",
            "details": "Assertion violations should be avoided within your contracts. Make sure that your program logic is correct (e.g., no division by zero) and that you add appropriate validation for inputs from both callers (e.g, passed arguments) and callees (e.g., return values). If your contracts are written in Solidity you may want to use the \"require\" language construct for this purpose.",
            "code-hash": "0xb17b583de9bdbb8dbda78285df7abbe982b373490723cc2694896c87bc8dae64",
            "function-signature": "b3e444a7",
            "bytecode-offset": 7175,
            "stack-trace": [],
            "time-secs": 9.666337898
        },
        {
            "swc-id": "SWC-127",
            "title": "jump to arbitrary destination",
            "details": "A caller can trigger a jump to an arbitrary destination.",
            "code-hash": "0x497a74b6f2beea96da5f6318de670706217e0edbcad5ce1bc5eaf89880d3f50b",
            "function-signature": "00000000",
            "bytecode-offset": 903,
            "stack-trace": [
                {
                    "op-code": "CREATE",
                    "code-hash": "0xb17b583de9bdbb8dbda78285df7abbe982b373490723cc2694896c87bc8dae64",
                    "function-signature": "6a0cc449",
                    "bytecode-offset": 4895
                }
            ],
            "time-secs": 26.878317139
        },
        {
            "swc-id": "SWC-127",
            "title": "jump to arbitrary destination",
            "details": "A caller can trigger a jump to an arbitrary destination.",
            "code-hash": "0xcc8f9d2be824285e0603317cba15118dd5c82ff0237ceb1b46daea8a99643370",
            "function-signature": "00000000",
            "bytecode-offset": 903,
            "stack-trace": [
                {
                    "op-code": "CREATE",
                    "code-hash": "0xb17b583de9bdbb8dbda78285df7abbe982b373490723cc2694896c87bc8dae64",
                    "function-signature": "6a0cc449",
                    "bytecode-offset": 4895
                }
            ],
            "time-secs": 78.71825101
        }
    ],
    "covered-paths": 721,
    "covered-instructions": 276715,
    "error": "",
    "total-time-secs": 96.005005074
}>

Environment

rocky commented 5 years ago

Forgot to add that AssertRegistry.sol is

pragma solidity 0.5.0;

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "openzeppelin-solidity/contracts/lifecycle/Pausable.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./VTToken.sol";
import "./TToken.sol";
import "./Main.sol";

/**
 * @title AssetRegistry
 * This contract manages the functionality for assets - adding records, as well as reading data. It allows
 * users to add assets to the platform, and asset owners to fund their assets once sold.
 *
 * @author Carlos Beltran <imthatcarlos@gmail.com>
 */
contract AssetRegistry is Pausable, Ownable {
  using SafeMath for uint;

  event AssetRecordCreated(address tokenAddress, address assetOwner, uint id);
  event AssetRecordUpdated(address indexed tokenAddress, uint id);
  event AssetFunded(uint id, address tokenAddress);

  struct Asset {
    address owner;
    address payable tokenAddress;
    bool filled;
    bool funded;
  }

  TToken private stableToken;
  address private mainContractAddress;

  Asset[] private assets;
  mapping (address => uint[]) private ownerToAssetIds;
  mapping (address => uint) private tokenToAssetIds;

  // allows us to easily calculate the total value of all assets
  uint[] private assetProjectedValuesUSD;

  modifier hasActiveAsset() {
    require(ownerToAssetIds[msg.sender].length != 0, "must have an active asset");
    _;
  }

  modifier validAsset(uint _id) {
    require(assets[_id].owner != address(0));
    _;
  }

  modifier onlyAssetOwner(uint _id) {
    require(assets[_id].owner == msg.sender);
    _;
  }

  constructor(address _stableTokenAddress, address _mainContractAddress) public {
    stableToken = TToken(_stableTokenAddress);
    mainContractAddress = _mainContractAddress;

    // take care of zero-index for storage array
    assets.push(Asset({
      owner: address(0),
      tokenAddress: address(0),
      filled: false,
      funded: false
    }));

    assetProjectedValuesUSD.push(0);
  }

  /**
   * Sets this contract's reference to the Main contract
   * @param _contractAddress Main contract address
   */
  function setMainContractAddress(address _contractAddress) public onlyOwner {
    mainContractAddress = _contractAddress;
  }

  /**
   * Creates an Asset record and adds it to storage, also creating a VTToken contract instance to
   * represent the asset
   * @param _owner Owner of the asset
   * @param _name Name of the asset
   * @param _valueUSD Value of the asset in USD
   * @param _cap token cap == _valueUSD / _valuePerTokenUSD
   * @param _annualizedROI AROI %
   * @param _projectedValueUSD The PROJECTED value of the asset in USD
   * @param _timeframeMonths Time frame for the investment
   * @param _valuePerTokenCents Value of each token
   */
  function addAsset(
    address payable _owner,
    string calldata _name,
    uint _valueUSD,
    uint _cap,
    uint _annualizedROI,
    uint _projectedValueUSD,
    uint _timeframeMonths,
    uint _valuePerTokenCents
  ) external {
    VTToken token = new VTToken(
      _owner,
      address(stableToken),
      _name,
      _valueUSD,
      _cap,
      _annualizedROI,
      _projectedValueUSD,
      _timeframeMonths,
      _valuePerTokenCents
    );

    // so the main contract can mint
    token.addMinter(mainContractAddress);

    // so main contract is always in sync
    Main(mainContractAddress).addFillableAsset(address(token), _cap);

    Asset memory record = Asset({
      owner: _owner,
      tokenAddress: address(token),
      filled: false,
      funded: false
    });

    // add the record to the storage array and push the index to the hashmap
    uint id = assets.push(record) - 1;
    ownerToAssetIds[_owner].push(id);
    tokenToAssetIds[address(token)] = id;

    // update our records for calculating
    assetProjectedValuesUSD.push(_projectedValueUSD);

    emit AssetRecordCreated(address(token), _owner, id);
  }

  /**
   * Allows the contract owner to edit certain data on the token contract
   * NOTE: we don't allow editing the token cap of the contract as it would jeopardize the validity of lookup
   *       records of other contracts (ie: Asset.filled in AssetRegistry). That being said...
   * NOTE: the cap is derived from the initial _valueUSD / _valuePerTokenUSD, so there will have to be some balancing
   *       if we want to preserve correct calculations
   * @param _tokenAddress The address of token contract
   * @param _valueUSD Value of the asset in USD
   * @param _annualizedROI AROI %
   * @param _projectedValueUSD The PROJECTED value of the asset in USD
   * @param _timeframeMonths Time frame for the investment
   * @param _valuePerTokenCents Value of each token
   */
  function editAsset(
    address payable _tokenAddress,
    uint _valueUSD,
    uint _annualizedROI,
    uint _projectedValueUSD,
    uint _timeframeMonths,
    uint _valuePerTokenCents
  ) external onlyOwner {
    // sanity check, must be a valid asset contract
    require(tokenToAssetIds[_tokenAddress] != 0);

    VTToken(_tokenAddress).editAssetData(
      _valueUSD,
      _annualizedROI,
      _projectedValueUSD,
      _timeframeMonths,
      _valuePerTokenCents
    );

    // udpate the projected value usd for the lookup record
    // ids on both arrays should be 1:1
    uint id = tokenToAssetIds[_tokenAddress];
    assetProjectedValuesUSD[id] = _projectedValueUSD;

    // emit an event for active clients to be notified
    emit AssetRecordUpdated(_tokenAddress, id);
  }

  /**
   * Allows an Asset Owner to fund the VTToken contract with T tokens to be distributed to investors
   * @dev should be called when the asset is sold, and any amount of T tokens sent in should
   *      equal the projected profit. this amount is divided amongst token owners based on the percentage
   *      of tokens they own. these token owners must claim their profit, it will NOT be automatically
   *      distributed to avoid security concerns
   * NOTE: asset owner must have approved the transfer of T tokens from their wallet to the VTToken contract
   * @param _amountStable Amount of T tokens the owner will fund - MUST equal the asset's projected value recorded
   * @param _assetId Asset id
   */

  function fundAsset(uint _amountStable, uint _assetId) public onlyAssetOwner(_assetId) {
    Asset storage asset = assets[_assetId];

    // sanity check
    require(_amountStable.div(10**18) >= VTToken(asset.tokenAddress).projectedValueUSD());

    // send T tokens from owner wallet to the token contract to be claimed by investors
    require(stableToken.transferFrom(msg.sender, asset.tokenAddress, _amountStable));

    asset.funded = true;

    emit AssetFunded(_assetId, asset.tokenAddress);
  }

  /**
   * Updates the asset record to filled when fully invested
   * @param _assetId Storage array id of the asset
   * NOTE: this method may only be called by the Main contract (in _updateAssetLookup())
   */
  function setAssetFilled(uint _assetId) public validAsset(_assetId) {
    // only the Main contract may call
    require(msg.sender == mainContractAddress);

    assets[_assetId].filled = true;
  }

  /**
   * Calculates and returns the sum of PROJECTED values of all assets (USD)
   */
  function calculateTotalProjectedValue() public view returns(uint) {
    return _sumElementsStorage(assetProjectedValuesUSD);
  }

  /**
   * Calculates and returns the sum of CURRENT values of all assets (T/USD)
   * @dev For all assets in the storage array that have not been deleted, calculate its current value
   */
  function calculateTotalCurrentValue() public view returns(uint) {
    uint total;
    for (uint i = 1; i <= (assets.length - 1); i++) {
      if (assets[i].tokenAddress != address(0)) {
        total = total.add(VTToken(assets[i].tokenAddress).getCurrentValue());
      }
    }

    return total;
  }

  /**
   * Returns the storage array id of the asset with the given VT contract address
   * @param _tokenAddress Address of VT contract
   */
  function getAssetIdByToken(address _tokenAddress) public view returns(uint) {
    return tokenToAssetIds[_tokenAddress];
  }

  /**
   * Returns the ids of all the sender's active assets
   */
  function getActiveAssetIds() public hasActiveAsset view returns(uint[] memory) {
    return ownerToAssetIds[msg.sender];
  }

  /**
   * Returns the ids of all the given accounts's active assets
   * NOTE: can only be called by contract owner
   */
  function getActiveAssetIdsOf(address _owner) public view onlyOwner returns(uint[] memory) {
    return ownerToAssetIds[_owner];
  }

  /**
   * Returns the number of active assets
   */
  function getAssetsCount() public view returns(uint) {
    return assets.length - 1; // ignoring first one created at init
  }

  /**
   * Returns details of the Asset with the given id
   * @param _id Asset id
   */
  function getAssetById(uint _id)
    public
    view
    validAsset(_id)
    returns (
      address owner,
      address tokenAddress,
      bool filled,
      bool funded
    )
  {
    Asset storage asset = assets[_id];

    owner = asset.owner;
    tokenAddress = asset.tokenAddress;
    filled = asset.filled;
    funded = asset.funded;
  }

  /// @dev Sum vector
  /// @param self Storage array containing uint256 type variables
  /// @return sum The sum of all elements, does not check for overflow
  /// https://github.com/Modular-Network/ethereum-libraries/contracts/Array256Lib.sol
  function _sumElementsStorage(uint256[] storage self) internal view returns(uint256 sum) {
    assembly {
      mstore(0x60,self_slot)

      for { let i := 0 } lt(i, sload(self_slot)) { i := add(i, 1) } {
        sum := add(sload(add(keccak256(0x60,0x20),i)),sum)
      }
    }
  }

  /// @dev Sum vector
  /// @param self Storage array containing uint256 type variables
  /// @return sum The sum of all elements, does not check for overflow
  /// https://github.com/Modular-Network/ethereum-libraries/contracts/Array256Lib.sol
  function _sumElementsMemory(uint256[] memory self) internal view returns(uint256 sum) {
    assembly {
      mstore(0x60,self)

      for { let i := 0 } lt(i, sload(self)) { i := add(i, 1) } {
        sum := add(sload(add(keccak256(0x60,0x20),i)),sum)
      }
    }
  }
}
rocky commented 5 years ago

@wuestholz informs me that there is a dynamicaly-generated call address involved here?

norhh commented 5 years ago

With increased depth mythril seems to detect all the assert fails, Currently mythril doesn't detect swc 127, 123, I think it would be easy to take care of swc 127, and possibly at least some part of swc 123

rocky commented 5 years ago

Thans @norhh the additional information!

As a Mythril novice, what depth is needed for 127? (and what depth is it now?)

How much additional time is needed? Thanks for the information.

rocky commented 5 years ago

Also, if you prefer to separate swc 127 from swc 123 so they can be tracked separately, I am happy to add as separate issue, and narrow this one.

rocky commented 5 years ago

Another stray thought. Is there a way that it might be detected in advance that either of these might need an additional depth?

norhh commented 5 years ago

As a Mythril novice, what depth is needed for 127? (and what depth is it now?) It can detect all the assert fails of harvey at depth 100, but currently there isn't support for 127 and 123.

Also, if you prefer to separate swc 127 from swc 123 so they can be tracked separately, I am happy to add as separate issue, and narrow this one. Yes, That would be great for tracking them.

Is there a way that it might be detected in advance that either of these might need an additional depth? That's an interesting thing to have.Unfortunately It isn't easily possible to know how much depth is required(due to loops and recursion) but we can at least get the minimum depth required by reverse topologically ordering the functions(assuming the function calls form a DAG, if it's forms a cycle then just one invocation of all the functions in the cycle) and then adding all the possible places of depth increment like function calls, if-else and some iterations of loops.

rocky commented 5 years ago

Having an option to do the work to indicate what a good "minimum" depth is and/or to warn whether the depth tried was less than the minimum depth would be a great thing to add. Especially in a "full" analysis.

Should I add this as a feature request?

I do not understand why "reverse topological ordering of functions" is necessary although I can see how it is sufficient. The essential property that you want to capture is the maximum number of nodes/functions that particupates in a cycle, correct? Is so, I think (an also linear) depth-first search of the call graph is another possibility.

norhh commented 5 years ago

Should I add this as a feature request? Sure, thats a great feature. The essential property that you want to capture is the maximum number of nodes/functions that particupates in a cycle and also the maximum number of functions which participate in a straight line. I do not understand why "reverse topological ordering of functions" is necessary although if A->B->C->D and functions are ordered as B, A, C, D by solc, we start executing at B then a direct dfs might be a bit weird, we have to do some minor modifications to dfs to make it work in linear time(and yeah toposort sounds like an overkill here). Anyway there are lot's of ways to do it.

ytrezq commented 4 years ago

@rocky : sorry that’s not about the issue, but wait ! Do you mean you can run Harvey locally on your computer and without using other MytX tools ?

I searched for how to run Harvey standalone myself locally and never found how.

norhh commented 4 years ago

@ytrezq Harvey will be opensourced soon but I don’t think it will include detection modules, using MythX should be better.

ytrezq commented 4 years ago

@norhh : I mean even as a binary I couldn’t download it.

norhh commented 4 years ago

@ytrezq that’s because it’s not open sourced yet. MythX runs it on its own servers.

JoranHonig commented 3 years ago

This seems to be a stale issue -> closing 🙌

ytrezq commented 3 years ago

@norhh are there still plan to perform at least a binary (not open source) release?