commit 7cb9e0baf0ab5db2dff71d2fb7279e2218e3cad0
parent e2dab1b72075bacf90026e1bb4f1e9406f0abc14
Author: lash <dev@holbrook.no>
Date: Mon, 12 Dec 2022 08:43:12 +0000
Merge branch 'lash/port-tests'
Diffstat:
16 files changed, 1379 insertions(+), 620 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -3,6 +3,8 @@ __pycache__
*.egg-info/
build/
dist/
+solidity/*.bin
+solidity/*.json
gmon.out
.idea
venv
diff --git a/python/erc20_transfer_authorization/data/ERC20TransferAuthorization.bin b/python/erc20_transfer_authorization/data/ERC20TransferAuthorization.bin
@@ -1 +1 @@
-60806040523480156200001157600080fd5b5033600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160068190555060016007819055506200007d33620000a2640100000000026401000000009004565b506200009b6001600062000282640100000000026401000000009004565b5062000539565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000137576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200012e906200039a565b60405180910390fd5b60001515600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514620001cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001c490620003bc565b60405180910390fd5b6001600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b60008154809291906200023a906200046a565b91905055507f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f24826040516200027091906200037d565b60405180910390a1600b549050919050565b6000600b548311156200029457600080fd5b60008311620002a257600080fd5b600b54821115620002b257600080fd5b8260098190555081600a819055507f9f40cfd22fe91777c78f252bd21a710f3fb007dc2f321876891e7644ba0ae175600954600a54600b54604051620002fb93929190620003de565b60405180910390a16001905092915050565b62000318816200042c565b82525050565b60006200032d600a836200041b565b91506200033a82620004e7565b602082019050919050565b600062000354600c836200041b565b9150620003618262000510565b602082019050919050565b620003778162000460565b82525050565b60006020820190506200039460008301846200030d565b92915050565b60006020820190508181036000830152620003b5816200031e565b9050919050565b60006020820190508181036000830152620003d78162000345565b9050919050565b6000606082019050620003f560008301866200036c565b6200040460208301856200036c565b6200041360408301846200036c565b949350505050565b600082825260208201905092915050565b6000620004398262000440565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000620004778262000460565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415620004ad57620004ac620004b8565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4552525f41434345535300000000000000000000000000000000000000000000600082015250565b7f4552525f4e4f54464f554e440000000000000000000000000000000000000000600082015250565b61239380620005496000396000f3fe608060405234801561001057600080fd5b506004361061015f576000357c010000000000000000000000000000000000000000000000000000000090048063736c0d5b116100d5578063bac911ac11610099578063bac911ac146103ee578063e3064a771461041e578063e9f9d28b1461044e578063eb12d61e1461047e578063ed71262a146104ae578063fba00cbd146104de5761015f565b8063736c0d5b1461031a578063755fd58f1461034a5780637ca548c61461037a57806381d12c58146103985780638da5cb5b146103d05761015f565b80633a9ddc80116101275780633a9ddc801461021e5780634797569a1461024e57806357ec347a1461027e57806358d71f821461029c578063614f427f146102cc5780636e417c69146102ea5761015f565b806302d947ef1461016457806306661abd1461019457806308ae6377146101b25780630e316ab7146101d05780631703a01814610200575b600080fd5b61017e60048036038101906101799190611bd0565b61050e565b60405161018b9190611e35565b60405180910390f35b61019c61053d565b6040516101a99190611e1a565b60405180910390f35b6101ba610543565b6040516101c79190611f10565b60405180910390f35b6101ea60048036038101906101e59190611adf565b61056e565b6040516101f79190611f10565b60405180910390f35b6102086107cf565b6040516102159190611f10565b60405180910390f35b61023860048036038101906102339190611b6b565b6107d5565b6040516102459190611f10565b60405180910390f35b61026860048036038101906102639190611ba7565b610806565b6040516102759190611f10565b60405180910390f35b610286610aaa565b6040516102939190611f10565b60405180910390f35b6102b660048036038101906102b19190611ba7565b610ac0565b6040516102c39190611f10565b60405180910390f35b6102d4610d45565b6040516102e19190611f10565b60405180910390f35b61030460048036038101906102ff9190611ba7565b610d4b565b6040516103119190611dff565b60405180910390f35b610334600480360381019061032f9190611adf565b61114a565b6040516103419190611dff565b60405180910390f35b610364600480360381019061035f9190611b6b565b61116a565b6040516103719190611f10565b60405180910390f35b61038261119b565b60405161038f9190611f10565b60405180910390f35b6103b260048036038101906103ad9190611ba7565b6111a1565b6040516103c799989796959493929190611f2b565b60405180910390f35b6103d861125c565b6040516103e59190611dad565b60405180910390f35b61040860048036038101906104039190611ba7565b611282565b6040516104159190611f10565b60405180910390f35b61043860048036038101906104339190611c0c565b611311565b6040516104459190611dff565b60405180910390f35b61046860048036038101906104639190611ba7565b611397565b6040516104759190611dff565b60405180910390f35b61049860048036038101906104939190611adf565b6115d0565b6040516104a59190611f10565b60405180910390f35b6104c860048036038101906104c39190611b08565b6117a6565b6040516104d59190611f10565b60405180910390f35b6104f860048036038101906104f39190611c0c565b6119f0565b6040516105059190611dad565b60405180910390f35b60006020528160005260406000206020528060005260406000206000915091509054906101000a900460000b81565b60085481565b600080600754600654610556919061203f565b1415610565576000905061056b565b60075490505b90565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806105f757508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610636576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062d90611e70565b60405180910390fd5b60011515600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146106c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c090611e90565b60405180910390fd5b600954600b541180156106df5750600a54600b54115b61071e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161071590611e50565b60405180910390fd5b6000600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b60008154809291906107899061214e565b91905055507f3525e22824a8a7df2c9a6029941c824cf95b6447f1e13d5128fd3826d35afe8b826040516107bd9190611dad565b60405180910390a1600b549050919050565b60095481565b600560205281600052604060002081815481106107f157600080fd5b90600052602060002001600091509150505481565b6000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610894576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161088b90611e70565b60405180910390fd5b600080600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460000b60000b14610936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161092d90611eb0565b60405180910390fd5b600060036000848152602001908152602001600020905060018160080160009054906101000a900460000b60000b1461096e57600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000808360000154815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360000b60ff1602179055506001600082600001548152602001908152602001600020339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806006016000815480929190610a8a906121c1565b9190505550610a9c8160000154611397565b508060060154915050919050565b60006001600654610abb919061203f565b905090565b6000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610b4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4590611e70565b60405180910390fd5b600080600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460000b60000b14610bf0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610be790611eb0565b60405180910390fd5b600060036000848152602001908152602001600020905060018160080160009054906101000a900460000b60000b14610c2857600080fd5b60016000808360000154815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360000b60ff1602179055506001600082600001548152602001908152602001600020339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806005016000815480929190610d25906121c1565b9190505550610d378160000154611397565b508060050154915050919050565b600a5481565b6000806003600084815260200190815260200160002090506000816000015411610daa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da190611ed0565b60405180910390fd5b60028160080160009054906101000a900460000b60000b14610e01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df890611ef0565b60405180910390fd5b60008160080160006101000a81548160ff021916908360000b60ff1602179055506000808260030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168460020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168560040154604051602401610ec193929190611dc8565b6040516020818303038152906040527f23b872dd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610f4b9190611d96565b6000604051808303816000865af19150503d8060008114610f88576040519150601f19603f3d011682016040523d82523d6000602084013e610f8d565b606091505b5091509150610f9f8360000154611a3e565b50438360070181905550600460008460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083600001549080600181540180825580915050600190039060005260206000200160009091909190915055600560008460020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020836000015490806001815401808255809150506001900390600052602060002001600090919091909150558115611107577fbcf6a68a2f901be4a23a41b53acd7697893a7e34def4e28acba584da75283b67856040516110fa9190611f10565b60405180910390a161113f565b7fdab20a0fcd702cf875c2d715d5c3fc99af66a716c94b3405408c94b7311c99eb856040516111369190611f10565b60405180910390a15b819350505050919050565b600c6020528060005260406000206000915054906101000a900460ff1681565b6004602052816000526040600020818154811061118657600080fd5b90600052602060002001600091509150505481565b600b5481565b60036020528060005260406000206000915090508060000154908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040154908060050154908060060154908060070154908060080160009054906101000a900460000b905089565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080600060075490505b60065481101561130557600060036000838152602001908152602001600020905060008160080160009054906101000a900460000b60000b13156112f157848314156112e2578060000154935050505061130c565b82806112ed906121c1565b9350505b5080806112fd906121c1565b91505061128d565b5060009150505b919050565b6000600b5483111561132257600080fd5b6000831161132f57600080fd5b600b5482111561133e57600080fd5b8260098190555081600a819055507f9f40cfd22fe91777c78f252bd21a710f3fb007dc2f321876891e7644ba0ae175600954600a54600b5460405161138593929190611fe1565b60405180910390a16001905092915050565b600080600060036000858152602001908152602001600020905060018160080160009054906101000a900460000b60000b12156113d85781925050506115cb565b6009548160050154106114555760028160080160006101000a81548160ff021916908360000b60ff16021790555080600001547f36ea04725f8aa40ee603224671681b753f9cba3cb5f67c5a0e24a3b39900c06582600501548360060154604051611444929190611fb8565b60405180910390a2600191506115c5565b6000600a5411801561146d5750600a54816006015410155b1561150f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160080160006101000a81548160ff021916908360000b60ff1602179055506114bf8160000154611a3e565b5080600001547f1ad80b2541a1f52bdc838332d7c23606116a1188a8cbbc4c0948b4b56ce51d14826005015483600601546040516114fe929190611fb8565b60405180910390a2600191506115c4565b6009548160060154600b54611524919061203f565b10156115c3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160080160006101000a81548160ff021916908360000b60ff1602179055506115778160000154611a3e565b5080600001547f3d61d434b895790b08f040c45261fce3b3bec596278b3a0f25dd9f741d0ba469826005015483600601546040516115b6929190611fb8565b60405180910390a2600191505b5b5b81925050505b919050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611662576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161165990611e70565b60405180910390fd5b60001515600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146116f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ec90611e90565b60405180910390fd5b6001600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b6000815480929190611760906121c1565b91905055507f47d1c22a25bb3a5d4e481b9b1e6944c2eade3181a0a20b495ed61d35b5323f24826040516117949190611dad565b60405180910390a1600b549050919050565b60008060036000600654815260200190815260200160002090506006548160000181905550848160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550858160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082816004018190555060018160080160006101000a81548160ff021916908360000b60ff160217905550600860008154809291906118d190612178565b9190505550600660008154809291906118e9906121c1565b91905055508060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168260010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c846004015485600001546040516119d8929190611fb8565b60405180910390a48060000154915050949350505050565b60016020528160005260406000208181548110611a0c57600080fd5b906000526020600020016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060086000815480929190611a5390612105565b919050555060006008541315611aa157600754821415611a9c576000611a796000611282565b90506000811415611a9257600654600781905550611a9a565b806007819055505b505b611aab565b6006546007819055505b6007549050919050565b600081359050611ac48161232f565b92915050565b600081359050611ad981612346565b92915050565b600060208284031215611af157600080fd5b6000611aff84828501611ab5565b91505092915050565b60008060008060808587031215611b1e57600080fd5b6000611b2c87828801611ab5565b9450506020611b3d87828801611ab5565b9350506040611b4e87828801611ab5565b9250506060611b5f87828801611aca565b91505092959194509250565b60008060408385031215611b7e57600080fd5b6000611b8c85828601611ab5565b9250506020611b9d85828601611aca565b9150509250929050565b600060208284031215611bb957600080fd5b6000611bc784828501611aca565b91505092915050565b60008060408385031215611be357600080fd5b6000611bf185828601611aca565b9250506020611c0285828601611ab5565b9150509250929050565b60008060408385031215611c1f57600080fd5b6000611c2d85828601611aca565b9250506020611c3e85828601611aca565b9150509250929050565b611c5181612073565b82525050565b611c6081612085565b82525050565b6000611c7182612018565b611c7b8185612023565b9350611c8b8185602086016120d2565b80840191505092915050565b611ca081612091565b82525050565b611caf8161209b565b82525050565b6000611cc2601a8361202e565b9150611ccd82612239565b602082019050919050565b6000611ce5600a8361202e565b9150611cf082612262565b602082019050919050565b6000611d08600c8361202e565b9150611d138261228b565b602082019050919050565b6000611d2b60108361202e565b9150611d36826122b4565b602082019050919050565b6000611d4e60138361202e565b9150611d59826122dd565b602082019050919050565b6000611d7160108361202e565b9150611d7c82612306565b602082019050919050565b611d90816120c8565b82525050565b6000611da28284611c66565b915081905092915050565b6000602082019050611dc26000830184611c48565b92915050565b6000606082019050611ddd6000830186611c48565b611dea6020830185611c48565b611df76040830184611d87565b949350505050565b6000602082019050611e146000830184611c57565b92915050565b6000602082019050611e2f6000830184611c97565b92915050565b6000602082019050611e4a6000830184611ca6565b92915050565b60006020820190508181036000830152611e6981611cb5565b9050919050565b60006020820190508181036000830152611e8981611cd8565b9050919050565b60006020820190508181036000830152611ea981611cfb565b9050919050565b60006020820190508181036000830152611ec981611d1e565b9050919050565b60006020820190508181036000830152611ee981611d41565b9050919050565b60006020820190508181036000830152611f0981611d64565b9050919050565b6000602082019050611f256000830184611d87565b92915050565b600061012082019050611f41600083018c611d87565b611f4e602083018b611c48565b611f5b604083018a611c48565b611f686060830189611c48565b611f756080830188611d87565b611f8260a0830187611d87565b611f8f60c0830186611d87565b611f9c60e0830185611d87565b611faa610100830184611ca6565b9a9950505050505050505050565b6000604082019050611fcd6000830185611d87565b611fda6020830184611d87565b9392505050565b6000606082019050611ff66000830186611d87565b6120036020830185611d87565b6120106040830184611d87565b949350505050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b600061204a826120c8565b9150612055836120c8565b9250828210156120685761206761220a565b5b828203905092915050565b600061207e826120a8565b9050919050565b60008115159050919050565b6000819050919050565b60008160000b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b838110156120f05780820151818401526020810190506120d5565b838111156120ff576000848401525b50505050565b600061211082612091565b91507f80000000000000000000000000000000000000000000000000000000000000008214156121435761214261220a565b5b600182039050919050565b6000612159826120c8565b9150600082141561216d5761216c61220a565b5b600182039050919050565b600061218382612091565b91507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121b6576121b561220a565b5b600182019050919050565b60006121cc826120c8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156121ff576121fe61220a565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4552525f5245445543455f5448524553484f4c445f4649525354000000000000600082015250565b7f4552525f41434345535300000000000000000000000000000000000000000000600082015250565b7f4552525f4e4f54464f554e440000000000000000000000000000000000000000600082015250565b7f4552525f414c5245414459564f54454400000000000000000000000000000000600082015250565b7f4552525f494e56414c49445f5245515545535400000000000000000000000000600082015250565b7f4552525f4e4f545f454e444f5253454400000000000000000000000000000000600082015250565b61233881612073565b811461234357600080fd5b50565b61234f816120c8565b811461235a57600080fd5b5056fea2646970667358221220db3bb04d4609a28abcde3217e8cc5e6a6573c3ee648d8e7f88e10daa0a5f7ec264736f6c63430008020033
-\ No newline at end of file
+60806040523480156200001157600080fd5b5033600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600260146101000a81548163ffffffff021916908363ffffffff1602179055506001600260186101000a81548163ffffffff021916908363ffffffff160217905550620000b133620000d6640100000000026401000000009004565b50620000cf60016000620002ef640100000000026401000000009004565b50620005e7565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146200016b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001629062000481565b60405180910390fd5b60001515600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151462000201576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001f890620004f3565b60405180910390fd5b6001600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506003600881819054906101000a900463ffffffff16809291906200027d9062000554565b91906101000a81548163ffffffff021916908363ffffffff160217905550507f6ff3aa2ea7b53070f6d9d07a445d338d89e8edef44250ffa8be19f53910d4a2e82604051620002cd9190620005ca565b60405180910390a1600360089054906101000a900463ffffffff169050919050565b6000600360089054906101000a900463ffffffff1663ffffffff168363ffffffff1611156200031d57600080fd5b60008363ffffffff16116200033157600080fd5b600360089054906101000a900463ffffffff1663ffffffff168263ffffffff1611156200035d57600080fd5b82600360006101000a81548163ffffffff021916908363ffffffff16021790555081600360046101000a81548163ffffffff021916908363ffffffff160217905550600360089054906101000a900463ffffffff1663ffffffff16600360049054906101000a900463ffffffff1663ffffffff16600360009054906101000a900463ffffffff1663ffffffff167fe77378573ac0f86c7fa8dd116b1fa17cf9c328a09a0c56a2c42d786103ac5bc360405160405180910390a46001905092915050565b600082825260208201905092915050565b7f4552525f41434345535300000000000000000000000000000000000000000000600082015250565b600062000469600a8362000420565b9150620004768262000431565b602082019050919050565b600060208201905081810360008301526200049c816200045a565b9050919050565b7f4552525f4e4f54464f554e440000000000000000000000000000000000000000600082015250565b6000620004db600c8362000420565b9150620004e882620004a3565b602082019050919050565b600060208201905081810360008301526200050e81620004cc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff82169050919050565b6000620005618262000544565b915063ffffffff82036200057a576200057962000515565b5b600182019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005b28262000585565b9050919050565b620005c481620005a5565b82525050565b6000602082019050620005e16000830184620005b9565b92915050565b61284580620005f76000396000f3fe608060405234801561001057600080fd5b5060043610610154576000357c010000000000000000000000000000000000000000000000000000000090048063614f427f116100d55780637ca548c6116100995780637ca548c6146103d65780637f4dbec1146103f45780638da5cb5b14610424578063da2824a814610442578063ed71262a14610472578063fdd33d68146104a257610154565b8063614f427f146102f8578063655c013114610316578063669cd53b1461034657806366a5267214610376578063736c0d5b146103a657610154565b80631703a0181161011c5780631703a0181461022c5780632b29ba231461024a578063476ce3ad1461027a5780635356dddc146102aa57806357ec347a146102da57610154565b806306661abd1461015957806308ae6377146101775780630ab469b0146101955780630ac94000146101cc57806310858c67146101fc575b600080fd5b6101616104d2565b60405161016e9190612044565b60405180910390f35b61017f6104e8565b60405161018c9190612044565b60405180910390f35b6101af60048036038101906101aa9190612090565b6105df565b6040516101c3989796959493929190612133565b60405180910390f35b6101e660048036038101906101e19190612090565b6106c4565b6040516101f391906121cc565b60405180910390f35b61021660048036038101906102119190612090565b610a12565b6040516102239190612044565b60405180910390f35b610234610b37565b6040516102419190612044565b60405180910390f35b610264600480360381019061025f9190612213565b610b4d565b60405161027191906121cc565b60405180910390f35b610294600480360381019061028f9190612090565b610ba3565b6040516102a19190612044565b60405180910390f35b6102c460048036038101906102bf9190612213565b610e2d565b6040516102d19190612044565b60405180910390f35b6102e26110e9565b6040516102ef9190612044565b60405180910390f35b61030061110f565b60405161030d9190612044565b60405180910390f35b610330600480360381019061032b9190612240565b611125565b60405161033d919061229c565b60405180910390f35b610360600480360381019061035b91906122b7565b611154565b60405161036d91906121cc565b60405180910390f35b610390600480360381019061038b9190612323565b611282565b60405161039d9190612350565b60405180910390f35b6103c060048036038101906103bb9190612213565b6112c1565b6040516103cd91906121cc565b60405180910390f35b6103de6112e1565b6040516103eb9190612044565b60405180910390f35b61040e60048036038101906104099190612090565b6112f7565b60405161041b9190612044565b60405180910390f35b61042c6115a0565b6040516104399190612350565b60405180910390f35b61045c60048036038101906104579190612213565b6115c6565b6040516104699190612044565b60405180910390f35b61048c6004803603810190610487919061236b565b6117d5565b6040516104999190612044565b60405180910390f35b6104bc60048036038101906104b79190612090565b611ad4565b6040516104c991906121cc565b60405180910390f35b6002601c9054906101000a900463ffffffff1681565b600080600260189054906101000a900463ffffffff16600260149054906101000a900463ffffffff1661051b9190612401565b63ffffffff16036105c6576001600260149054906101000a900463ffffffff1663ffffffff160361054f57600090506105dc565b600060016000600260189054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020905060008160040160009054906101000a900460ff1660ff1611156105bc57600260189054906101000a900463ffffffff169150506105dc565b60009150506105dc565b600260189054906101000a900463ffffffff1690505b90565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160149054906101000a900463ffffffff16908060030160189054906101000a900463ffffffff169080600301601c9054906101000a900463ffffffff16908060040160009054906101000a900460ff16905088565b600080600160008463ffffffff1663ffffffff168152602001908152602001600020905060008160030160149054906101000a900463ffffffff1663ffffffff1611610745576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073c90612496565b60405180910390fd5b6003600b8260040160009054906101000a900460ff161660ff161461079f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079690612502565b60405180910390fd5b6107bc8160030160149054906101000a900463ffffffff16611e99565b5060088160040160008282829054906101000a900460ff161792506101000a81548160ff021916908360ff1602179055506000808260030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168460020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856000015460405160240161088c93929190612522565b6040516020818303038152906040527f23b872dd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161091691906125ca565b6000604051808303816000865af19150503d8060008114610953576040519150601f19603f3d011682016040523d82523d6000602084013e610958565b606091505b5091509150811561099f577fa80d5e3445b11533e6c584c506299aa14168f2ad1fe65b0266e7d622c5461c30856040516109929190612044565b60405180910390a1610a07565b60108360040160008282829054906101000a900460ff161792506101000a81548160ff021916908360ff1602179055507f8f15e24c8a8ecaa6b067f0cd2c220532e6496f53b2ac3263129d1496cb6f192e856040516109fe9190612044565b60405180910390a15b819350505050919050565b600080600260149054906101000a900463ffffffff1663ffffffff16600260189054906101000a900463ffffffff1663ffffffff1603610a56576000915050610b32565b6000600260189054906101000a900463ffffffff1690505b600260149054906101000a900463ffffffff1663ffffffff168163ffffffff161015610b2b576000600160008363ffffffff1663ffffffff1681526020019081526020016000209050600160078260040160009054906101000a900460ff161660ff1603610b17578463ffffffff168363ffffffff1603610b08578060030160149054906101000a900463ffffffff169350505050610b32565b8280610b13906125e1565b9350505b508080610b23906125e1565b915050610a6e565b5060009150505b919050565b600360009054906101000a900463ffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610c31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2890612659565b60405180910390fd5b60008060008463ffffffff1663ffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460000b60000b14610cdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd6906126c5565b60405180910390fd5b6000600160008463ffffffff1663ffffffff168152602001908152602001600020905060018160040160009054906101000a900460ff1660ff1614610d2357600080fd5b60016000808360030160149054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360000b60ff16021790555080600301601881819054906101000a900463ffffffff1680929190610dd3906125e1565b91906101000a81548163ffffffff021916908363ffffffff16021790555050610e0f8160030160149054906101000a900463ffffffff16611ad4565b508060030160189054906101000a900463ffffffff16915050919050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ebf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb690612659565b60405180910390fd5b60011515600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610f52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4990612731565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff16600360089054906101000a900463ffffffff1663ffffffff16118015610fc05750600360049054906101000a900463ffffffff1663ffffffff16600360089054906101000a900463ffffffff1663ffffffff16115b610fff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ff69061279d565b60405180910390fd5b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506003600881819054906101000a900463ffffffff1680929190611079906127bd565b91906101000a81548163ffffffff021916908363ffffffff160217905550507f86e5bbceda94081c32220d685f37cc4e3ea7bb0be2dfbf0cb703579505a5390e826040516110c79190612350565b60405180910390a1600360089054906101000a900463ffffffff169050919050565b60006001600260149054906101000a900463ffffffff1661110a9190612401565b905090565b600360049054906101000a900463ffffffff1681565b60006020528160005260406000206020528060005260406000206000915091509054906101000a900460000b81565b6000600360089054906101000a900463ffffffff1663ffffffff168363ffffffff16111561118157600080fd5b60008363ffffffff161161119457600080fd5b600360089054906101000a900463ffffffff1663ffffffff168263ffffffff1611156111bf57600080fd5b82600360006101000a81548163ffffffff021916908363ffffffff16021790555081600360046101000a81548163ffffffff021916908363ffffffff160217905550600360089054906101000a900463ffffffff1663ffffffff16600360049054906101000a900463ffffffff1663ffffffff16600360009054906101000a900463ffffffff1663ffffffff167fe77378573ac0f86c7fa8dd116b1fa17cf9c328a09a0c56a2c42d786103ac5bc360405160405180910390a46001905092915050565b6005818154811061129257600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60046020528060005260406000206000915054906101000a900460ff1681565b600360089054906101000a900463ffffffff1681565b6000600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611385576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137c90612659565b60405180910390fd5b60008060008463ffffffff1663ffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460000b60000b14611433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161142a906126c5565b60405180910390fd5b6000600160008463ffffffff1663ffffffff168152602001908152602001600020905060018160040160009054906101000a900460ff1660ff161461147757600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000808360030160149054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360000b60ff16021790555080600301601c81819054906101000a900463ffffffff1680929190611546906125e1565b91906101000a81548163ffffffff021916908363ffffffff160217905550506115828160030160149054906101000a900463ffffffff16611ad4565b5080600301601c9054906101000a900463ffffffff16915050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164f90612659565b60405180910390fd5b60001515600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146116eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e290612731565b60405180910390fd5b6001600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506003600881819054906101000a900463ffffffff1680929190611765906125e1565b91906101000a81548163ffffffff021916908363ffffffff160217905550507f6ff3aa2ea7b53070f6d9d07a445d338d89e8edef44250ffa8be19f53910d4a2e826040516117b39190612350565b60405180910390a1600360089054906101000a900463ffffffff169050919050565b60008060016000600260149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020019081526020016000209050600260149054906101000a900463ffffffff168160030160146101000a81548163ffffffff021916908363ffffffff160217905550848160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550858160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082816000018190555060018160040160006101000a81548160ff021916908360ff1602179055506002601c81819054906101000a900463ffffffff1680929190611952906125e1565b91906101000a81548163ffffffff021916908363ffffffff160217905550506002601481819054906101000a900463ffffffff1680929190611993906125e1565b91906101000a81548163ffffffff021916908363ffffffff160217905550508060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168260010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f3ba7a259b57ae3d653287762394374c856528591f691ecd6494021fdcea00f2484600001548560030160149054906101000a900463ffffffff16604051611aac9291906127e6565b60405180910390a48060030160149054906101000a900463ffffffff16915050949350505050565b6000806000600160008563ffffffff1663ffffffff168152602001908152602001600020905060018160040160009054906101000a900460ff1660ff161080611b345750600060068260040160009054906101000a900460ff161660ff16115b15611b43578192505050611e94565b600360009054906101000a900463ffffffff1663ffffffff168160030160189054906101000a900463ffffffff1663ffffffff1610611c325760028160040160008282829054906101000a900460ff161792506101000a81548160ff021916908360ff16021790555080600301601c9054906101000a900463ffffffff1663ffffffff168160030160189054906101000a900463ffffffff1663ffffffff168260030160149054906101000a900463ffffffff1663ffffffff167f7a17acca3819c1012204b2d019c0ee13bb7e5cf151111030329219582ba83f3160405160405180910390a460019150611e8e565b6000600360049054906101000a900463ffffffff1663ffffffff16118015611c8c5750600360049054906101000a900463ffffffff1663ffffffff1681600301601c9054906101000a900463ffffffff1663ffffffff1610155b15611d655760048160040160008282829054906101000a900460ff161792506101000a81548160ff021916908360ff160217905550611cde8160030160149054906101000a900463ffffffff16611e99565b5080600301601c9054906101000a900463ffffffff1663ffffffff168160030160189054906101000a900463ffffffff1663ffffffff168260030160149054906101000a900463ffffffff1663ffffffff167f4bdd2d0e6caefafbf833eda0d32f2dcb0e7a621e3e7b87b2a17c12090edbc0d660405160405180910390a460019150611e8d565b600360009054906101000a900463ffffffff1663ffffffff1681600301601c9054906101000a900463ffffffff16600360089054906101000a900463ffffffff16611db09190612401565b63ffffffff161015611e8c5760048160040160008282829054906101000a900460ff161792506101000a81548160ff021916908360ff160217905550611e098160030160149054906101000a900463ffffffff16611e99565b5080600301601c9054906101000a900463ffffffff1663ffffffff168160030160189054906101000a900463ffffffff1663ffffffff168260030160149054906101000a900463ffffffff1663ffffffff167f3c478de516aa199022ddcd594a6e3b7f03a3e23bfcafd6143adceb687a8e38ea60405160405180910390a4600191505b5b5b81925050505b919050565b60006002601c81819054906101000a900463ffffffff1680929190611ebd906127bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055505060006002601c9054906101000a900463ffffffff1663ffffffff161115611f9f57600260189054906101000a900463ffffffff1663ffffffff168263ffffffff1603611f9a576000611f2e6000610a12565b905060008163ffffffff1603611f7657600260149054906101000a900463ffffffff16600260186101000a81548163ffffffff021916908363ffffffff160217905550611f98565b80600260186101000a81548163ffffffff021916908363ffffffff1602179055505b505b61200b565b600260149054906101000a900463ffffffff1663ffffffff16600260189054906101000a900463ffffffff1663ffffffff161461200a57600260149054906101000a900463ffffffff16600260186101000a81548163ffffffff021916908363ffffffff1602179055505b5b600260189054906101000a900463ffffffff169050919050565b600063ffffffff82169050919050565b61203e81612025565b82525050565b60006020820190506120596000830184612035565b92915050565b600080fd5b61206d81612025565b811461207857600080fd5b50565b60008135905061208a81612064565b92915050565b6000602082840312156120a6576120a561205f565b5b60006120b48482850161207b565b91505092915050565b6000819050919050565b6120d0816120bd565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612101826120d6565b9050919050565b612111816120f6565b82525050565b600060ff82169050919050565b61212d81612117565b82525050565b600061010082019050612149600083018b6120c7565b612156602083018a612108565b6121636040830189612108565b6121706060830188612108565b61217d6080830187612035565b61218a60a0830186612035565b61219760c0830185612035565b6121a460e0830184612124565b9998505050505050505050565b60008115159050919050565b6121c6816121b1565b82525050565b60006020820190506121e160008301846121bd565b92915050565b6121f0816120f6565b81146121fb57600080fd5b50565b60008135905061220d816121e7565b92915050565b6000602082840312156122295761222861205f565b5b6000612237848285016121fe565b91505092915050565b600080604083850312156122575761225661205f565b5b60006122658582860161207b565b9250506020612276858286016121fe565b9150509250929050565b60008160000b9050919050565b61229681612280565b82525050565b60006020820190506122b1600083018461228d565b92915050565b600080604083850312156122ce576122cd61205f565b5b60006122dc8582860161207b565b92505060206122ed8582860161207b565b9150509250929050565b612300816120bd565b811461230b57600080fd5b50565b60008135905061231d816122f7565b92915050565b6000602082840312156123395761233861205f565b5b60006123478482850161230e565b91505092915050565b60006020820190506123656000830184612108565b92915050565b600080600080608085870312156123855761238461205f565b5b6000612393878288016121fe565b94505060206123a4878288016121fe565b93505060406123b5878288016121fe565b92505060606123c68782880161230e565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061240c82612025565b915061241783612025565b9250828203905063ffffffff811115612433576124326123d2565b5b92915050565b600082825260208201905092915050565b7f4552525f494e56414c49445f5245515545535400000000000000000000000000600082015250565b6000612480601383612439565b915061248b8261244a565b602082019050919050565b600060208201905081810360008301526124af81612473565b9050919050565b7f4552525f4e4f545f454e444f5253454400000000000000000000000000000000600082015250565b60006124ec601083612439565b91506124f7826124b6565b602082019050919050565b6000602082019050818103600083015261251b816124df565b9050919050565b60006060820190506125376000830186612108565b6125446020830185612108565b61255160408301846120c7565b949350505050565b600081519050919050565b600081905092915050565b60005b8381101561258d578082015181840152602081019050612572565b60008484015250505050565b60006125a482612559565b6125ae8185612564565b93506125be81856020860161256f565b80840191505092915050565b60006125d68284612599565b915081905092915050565b60006125ec82612025565b915063ffffffff8203612602576126016123d2565b5b600182019050919050565b7f4552525f41434345535300000000000000000000000000000000000000000000600082015250565b6000612643600a83612439565b915061264e8261260d565b602082019050919050565b6000602082019050818103600083015261267281612636565b9050919050565b7f4552525f414c5245414459564f54454400000000000000000000000000000000600082015250565b60006126af601083612439565b91506126ba82612679565b602082019050919050565b600060208201905081810360008301526126de816126a2565b9050919050565b7f4552525f4e4f54464f554e440000000000000000000000000000000000000000600082015250565b600061271b600c83612439565b9150612726826126e5565b602082019050919050565b6000602082019050818103600083015261274a8161270e565b9050919050565b7f4552525f5245445543455f5448524553484f4c445f4649525354000000000000600082015250565b6000612787601a83612439565b915061279282612751565b602082019050919050565b600060208201905081810360008301526127b68161277a565b9050919050565b60006127c882612025565b9150600082036127db576127da6123d2565b5b600182039050919050565b60006040820190506127fb60008301856120c7565b6128086020830184612035565b939250505056fea26469706673582212202cc5839cf3734f7f04d95e61219fc5e69a1a116202984ee674eb387bbaaa9b1764736f6c63430008110033
+\ No newline at end of file
diff --git a/python/erc20_transfer_authorization/data/ERC20TransferAuthorization.json b/python/erc20_transfer_authorization/data/ERC20TransferAuthorization.json
@@ -1 +1 @@
-[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_serial","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_yays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nays","type":"uint256"}],"name":"Approved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":true,"internalType":"address","name":"_recipient","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"NewRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_quorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_vetoThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_signerCount","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_serial","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_yays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nays","type":"uint256"}],"name":"Rejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_signer","type":"address"}],"name":"SignerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_signer","type":"address"}],"name":"SignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"TransferFail","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_serial","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_yays","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nays","type":"uint256"}],"name":"Vetoed","type":"event"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"addSigner","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"checkResult","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"count","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"createRequest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"executeRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_idx","type":"uint256"}],"name":"getSerialAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSerial","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"nay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextSerial","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"removeSigner","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestRecipientIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestSenderIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requests","outputs":[{"internalType":"uint256","name":"serial","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"yay","type":"uint256"},{"internalType":"uint256","name":"nay","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"int8","name":"result","type":"int8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quorum","type":"uint256"},{"internalType":"uint256","name":"_vetoThreshold","type":"uint256"}],"name":"setThresholds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vetoThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"vote","outputs":[{"internalType":"int8","name":"","type":"int8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"voters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_serial","type":"uint256"}],"name":"yay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
+[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"_serial","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_yays","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_nays","type":"uint32"}],"name":"Approved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":true,"internalType":"address","name":"_recipient","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"NewRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"_quorum","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_vetoThreshold","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_signerCount","type":"uint32"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"_serial","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_yays","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_nays","type":"uint32"}],"name":"Rejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"TransferFail","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"_serial","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_yays","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"_nays","type":"uint32"}],"name":"Vetoed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_signer","type":"address"}],"name":"WriterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_signer","type":"address"}],"name":"WriterRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"addWriter","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"checkResult","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"count","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"createRequest","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"executeRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_idx","type":"uint32"}],"name":"getSerialAt","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"isWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSerial","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"nay","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextSerial","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorum","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"removeWriter","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"requests","outputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32","name":"serial","type":"uint32"},{"internalType":"uint32","name":"yay","type":"uint32"},{"internalType":"uint32","name":"nay","type":"uint32"},{"internalType":"uint8","name":"result","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_quorum","type":"uint32"},{"internalType":"uint32","name":"_vetoThreshold","type":"uint32"}],"name":"setThresholds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerCount","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vetoThreshold","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"}],"name":"vote","outputs":[{"internalType":"int8","name":"","type":"int8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"writers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_serial","type":"uint32"}],"name":"yay","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"}]
diff --git a/python/erc20_transfer_authorization/transfer_authorization.py b/python/erc20_transfer_authorization/transfer_authorization.py
@@ -32,11 +32,88 @@ moddir = os.path.dirname(__file__)
datadir = os.path.join(moddir, 'data')
+class Request:
+
+ def __init__(self, sender, recipient, value, token):
+ self.sender = sender
+ self.recipient = recipient
+ self.value = value
+ self.token = token
+ self.serial = 0
+ self.yay = 0
+ self.nay = 0
+ self.result = 0
+
+
+ @classmethod
+ def create(cls, sender, recipient, value, token, *args):
+ o = Request(sender, recipient, value, token)
+ if len(args) > 0:
+ o.serial = args[0]
+ o.yay = args[1]
+ o.nsy = args[2]
+ o.result = args[3]
+ return o
+
+
+ def is_accepted(self):
+ return self.result & 2 > 0
+
+
+ def is_rejected(self):
+ return self.result & 4 > 0
+
+
+ def is_transferred(self):
+ return self.result & 24 == 8
+
+
+ def is_voting(self):
+ return self.result & 7 == 1
+
+
+ def is_executed(self):
+ return self.result & 8 == 8
+
+
+ def __str__(self):
+ return "{}Â {}Â {} {}".format(self.sender, self.recipient, self.value, self.result)
+
+
+
class TransferAuthorization(TxFactory):
__abi = None
__bytecode = None
-
+
+
+ def __init__(self, *args, **kwargs):
+ super(TransferAuthorization, self).__init__(*args, **kwargs)
+
+
+ def count(self, *args, **kwargs):
+ return self.call_noarg('count', *args, **kwargs)
+
+
+ def quorum_threshold(self, *args, **kwargs):
+ return self.call_noarg('quorum', *args, **kwargs)
+
+
+ def veto_threshold(self, *args, **kwargs):
+ return self.call_noarg('vetoThreshold', *args, **kwargs)
+
+
+ def signer_count(self, *args, **kwargs):
+ return self.call_noarg('signerCount', *args, **kwargs)
+
+
+ def last_serial(self, *args, **kwargs):
+ return self.call_noarg('lastSerial', *args, **kwargs)
+
+
+ def next_serial(self, *args, **kwargs):
+ return self.call_noarg('nextSerial', *args, **kwargs)
+
@staticmethod
def abi():
@@ -61,6 +138,26 @@ class TransferAuthorization(TxFactory):
return 2800000
+ def __single_address_method(self, method, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
+ enc = ABIContractEncoder()
+ enc.method(method)
+ enc.typ(ABIContractType.ADDRESS)
+ enc.address(address)
+ data = enc.get()
+ tx = self.template(sender_address, contract_address, use_nonce=True)
+ tx = self.set_code(tx, data)
+ tx = self.finalize(tx, tx_format)
+ return tx
+
+
+ def add_writer(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
+ return self.__single_address_method('addWriter', contract_address, sender_address, address, tx_format)
+
+
+ def delete_writer(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
+ return self.__single_address_method('deleteWriter', contract_address, sender_address, address, tx_format)
+
+
def create_request(self, contract_address, sender_address, sender, recipient, token, value, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('createRequest')
@@ -79,6 +176,62 @@ class TransferAuthorization(TxFactory):
return tx
+
+ def set_thresholds(self, contract_address, sender_address, quorum_threshold, veto_threshold, tx_format=TxFormat.JSONRPC):
+ enc = ABIContractEncoder()
+ enc.method('setThresholds')
+ enc.typ(ABIContractType.UINT32)
+ enc.typ(ABIContractType.UINT32)
+ enc.uintn(quorum_threshold, 32)
+ enc.uintn(veto_threshold, 32)
+ data = enc.get()
+ tx = self.template(sender_address, contract_address, use_nonce=True)
+ tx = self.set_code(tx, data)
+ tx = self.finalize(tx, tx_format)
+ return tx
+
+
+ def requests(self, contract_address, idx, sender_address=ZERO_ADDRESS, id_generator=None):
+ j = JSONRPCRequest(id_generator)
+ o = j.template()
+ o['method'] = 'eth_call'
+ enc = ABIContractEncoder()
+ enc.method('requests')
+ enc.typ(ABIContractType.UINT32)
+ enc.uintn(idx, 32)
+ data = add_0x(enc.get())
+ tx = self.template(sender_address, contract_address)
+ tx = self.set_code(tx, data)
+ o['params'].append(self.normalize(tx))
+ o['params'].append('latest')
+ o = j.finalize(o)
+ return o
+
+
+ def yay(self, contract_address, sender_address, serial, tx_format=TxFormat.JSONRPC):
+ enc = ABIContractEncoder()
+ enc.method('yay')
+ enc.typ(ABIContractType.UINT32)
+ enc.uintn(serial, 32)
+ data = enc.get()
+ tx = self.template(sender_address, contract_address, use_nonce=True)
+ tx = self.set_code(tx, data)
+ tx = self.finalize(tx, tx_format)
+ return tx
+
+
+ def nay(self, contract_address, sender_address, serial, tx_format=TxFormat.JSONRPC):
+ enc = ABIContractEncoder()
+ enc.method('nay')
+ enc.typ(ABIContractType.UINT32)
+ enc.uintn(serial, 32)
+ data = enc.get()
+ tx = self.template(sender_address, contract_address, use_nonce=True)
+ tx = self.set_code(tx, data)
+ tx = self.finalize(tx, tx_format)
+ return tx
+
+
def constructor(self, sender_address):
code = TransferAuthorization.bytecode()
tx = self.template(sender_address, None, use_nonce=True)
@@ -86,7 +239,7 @@ class TransferAuthorization(TxFactory):
return self.build(tx)
- def signers(self, contract_address, signer_address, sender_address=ZERO_ADDRESS, id_generator=None):
+ def writers(self, contract_address, signer_address, sender_address=ZERO_ADDRESS, id_generator=None):
j = JSONRPCRequest(id_generator)
o = j.template()
o['method'] = 'eth_call'
@@ -103,8 +256,32 @@ class TransferAuthorization(TxFactory):
return o
- def have_signer(self, contract_address, signer_address, sender_address=ZERO_ADDRESS):
- return self.signers(contract_address, signer_address, sender_address)
+ def check_result(self, contract_address, sender_address, serial, id_generator=None, tx_format=TxFormat.JSONRPC):
+ enc = ABIContractEncoder()
+ enc.method('checkResult')
+ enc.typ(ABIContractType.UINT32)
+ enc.uintn(serial, 32)
+ data = enc.get()
+ tx = self.template(sender_address, contract_address, use_nonce=True)
+ tx = self.set_code(tx, data)
+ tx = self.finalize(tx, tx_format)
+ return tx
+
+
+ def execute_request(self, contract_address, sender_address, serial, id_generator=None, tx_format=TxFormat.JSONRPC):
+ enc = ABIContractEncoder()
+ enc.method('executeRequest')
+ enc.typ(ABIContractType.UINT32)
+ enc.uintn(serial, 32)
+ data = enc.get()
+ tx = self.template(sender_address, contract_address, use_nonce=True)
+ tx = self.set_code(tx, data)
+ tx = self.finalize(tx, tx_format)
+ return tx
+
+
+ def is_writer(self, contract_address, signer_address, sender_address=ZERO_ADDRESS, id_generator=None):
+ return self.writers(contract_address, signer_address, sender_address)
@classmethod
@@ -113,6 +290,11 @@ class TransferAuthorization(TxFactory):
@classmethod
+ def parse_count(self, v):
+ return abi_decode_single(ABIContractType.UINT32, v)
+
+
+ @classmethod
def parse_create_request_request(self, v):
v = strip_0x(v)
cursor = 0
@@ -145,21 +327,35 @@ class TransferAuthorization(TxFactory):
r = dec.decode()
return r
-#
-# def last_serial(self):
-# return self.contract.functions.lastSerial().call()
-#
-#
-# def next_serial(self):
-# return self.contract.functions.nextSerial().call()
-#
-#
-# def requests(self, idx):
-# req = self.contract.functions.requests(idx).call()
-# return {
-# 'serial': req[0],
-# 'sender': req[1],
-# 'recipient': req[2],
-# 'token': req[3],
-# 'value': req[4],
-# }
+
+ @classmethod
+ def parse_request(self, v):
+ cursor = 0
+ v = strip_0x(v)
+ d = ABIContractDecoder()
+ d.typ(ABIContractType.UINT256)
+ d.typ(ABIContractType.ADDRESS)
+ d.typ(ABIContractType.ADDRESS)
+ d.typ(ABIContractType.ADDRESS)
+ d.typ(ABIContractType.UINT32)
+ d.typ(ABIContractType.UINT32)
+ d.typ(ABIContractType.UINT32)
+ d.typ(ABIContractType.UINT32)
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ d.val(v[cursor:cursor+64])
+ cursor += 64
+ r = d.decode()
+ return Request.create(r[1], r[2], r[0], r[3], r[4], r[5], r[6], r[7])
diff --git a/python/erc20_transfer_authorization/unittest/__init__.py b/python/erc20_transfer_authorization/unittest/__init__.py
@@ -0,0 +1 @@
+from .base import TestBase
diff --git a/python/erc20_transfer_authorization/unittest/base.py b/python/erc20_transfer_authorization/unittest/base.py
@@ -0,0 +1,45 @@
+# standard imports
+import os
+import unittest
+import json
+import logging
+
+# external imports
+from chainlib.eth.unittest.ethtester import EthTesterCase
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.tx import receipt
+from giftable_erc20_token import GiftableToken
+
+# local imports
+from erc20_transfer_authorization import TransferAuthorization
+
+logg = logging.getLogger()
+
+testdir = os.path.dirname(__file__)
+
+
+class TestBase(EthTesterCase):
+
+ def setUp(self):
+ super(TestBase, self).setUp()
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.constructor(self.accounts[0])
+
+ self.rpc.do(o)
+
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ self.address = r['contract_address']
+
+ c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.constructor(self.accounts[0], 'FooToken', 'FOO', 6)
+ self.rpc.do(o)
+
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ self.token_address = r['contract_address']
diff --git a/python/requirements.txt b/python/requirements.txt
@@ -1,3 +1,3 @@
confini>=0.5.2,<0.7.0
-chainlib-eth>=0.3.0,<0.4.0
-potaahto~=0.1.1
-\ No newline at end of file
+chainlib-eth~=0.4.7
+potaahto~=0.1.1
diff --git a/python/setup.cfg b/python/setup.cfg
@@ -26,6 +26,7 @@ python_requires = >= 3.6
packages =
erc20_transfer_authorization
erc20_transfer_authorization.runnable
+ erc20_transfer_authorization.unittest
[options.package_data]
* =
diff --git a/python/test_requirements.txt b/python/test_requirements.txt
@@ -1,3 +1,3 @@
eth-tester==0.5.0b3
py-evm==0.3.0a20
-eth-erc20~=0.4.0
+eth-erc20~=0.5.2
diff --git a/python/tests/base_erc20transferauthorization.py b/python/tests/base_erc20transferauthorization.py
@@ -1,49 +0,0 @@
-# standard imports
-import os
-import unittest
-import json
-import logging
-
-# external imports
-from chainlib.eth.unittest.ethtester import EthTesterCase
-from chainlib.eth.nonce import RPCNonceOracle
-from chainlib.eth.tx import receipt
-from giftable_erc20_token import GiftableToken
-
-# local imports
-from erc20_transfer_authorization import TransferAuthorization
-
-logging.basicConfig(level=logging.DEBUG)
-logg = logging.getLogger()
-
-logging.getLogger('web3').setLevel(logging.WARNING)
-logging.getLogger('eth.vm').setLevel(logging.WARNING)
-
-testdir = os.path.dirname(__file__)
-
-
-class TestBase(EthTesterCase):
-
- def setUp(self):
- super(TestBase, self).setUp()
- nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
- c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
- (tx_hash_hex, o) = c.constructor(self.accounts[0])
-
- self.rpc.do(o)
-
- o = receipt(tx_hash_hex)
- r = self.rpc.do(o)
- self.assertEqual(r['status'], 1)
-
- self.address = r['contract_address']
-
- c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
- (tx_hash_hex, o) = c.constructor(self.accounts[0], 'FooToken', 'FOO', 6)
- self.rpc.do(o)
-
- o = receipt(tx_hash_hex)
- r = self.rpc.do(o)
- self.assertEqual(r['status'], 1)
-
- self.token_address = r['contract_address']
diff --git a/python/tests/test_app.py b/python/tests/test_app.py
@@ -1,165 +0,0 @@
-# standard imports
-import os
-import unittest
-import logging
-
-# external imports
-from chainlib.eth.nonce import RPCNonceOracle
-
-# local imports
-from erc20_transfer_authorization import TransferAuthorization
-
-# testutil imports
-from tests.base_erc20transferauthorization import TestBase
-
-logg = logging.getLogger()
-
-testdir = os.path.dirname(__file__)
-
-
-class ERC20TransferAuthorizationBasicTest(TestBase):
-
- def test_basic(self):
-
- nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
- c = TransferAuthorization(self.chain_spec)
-
- o = c.signers(self.address, self.accounts[0], sender_address=self.accounts[0])
- r = self.rpc.do(o)
- self.assertTrue(c.parse_signers(r))
-
- o = c.signers(self.address, self.accounts[1], sender_address=self.accounts[0])
- r = self.rpc.do(o)
- self.assertFalse(c.parse_signers(r))
-
-
-# def test_get(self):
-# w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
-# t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-#
-# tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
-# r = self.w3.eth.getTransactionReceipt(tx_hash)
-#
-# topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
-# log = r.logs[0]
-# topic = log.topics[0]
-# self.assertEqual(topic.hex()[2:], topic_match)
-# serial = int(log.data[66:], 16)
-#
-# for i in range(1, 3):
-# tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3+i], t.address, 10*(i+1)).transact({'from': self.w3.eth.accounts[2]})
-#
-# tq_count = w.functions.count().call()
-# assert (tq_count == 3);
-#
-# for i in range(w.functions.nextSerial().call(), w.functions.lastSerial().call()):
-# tqg = w.functions.requests(i).call()
-#
-# self.assertEqual(tqg[0], i)
-# self.assertEqual(tqg[1], self.w3.eth.accounts[2])
-# self.assertEqual(tqg[2], self.w3.eth.accounts[3+(i-1)])
-# self.assertEqual(tqg[3], t.address)
-# self.assertEqual(tqg[4], 10*i)
-#
-#
-# def test_get_vote(self):
-# w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
-# t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-#
-# tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
-# w.functions.nay(1).transact({'from': self.w3.eth.accounts[0]})
-#
-# self.assertEqual(w.functions.voters(1, 0).call(), self.w3.eth.accounts[0])
-# self.assertEqual(w.functions.vote(1, self.w3.eth.accounts[0]).call(), -1)
-#
-#
-# def test_indexes(self):
-# w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
-# t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-#
-# for i in range(0, 5):
-# amount = 10*(i+1)
-# sender = self.w3.eth.accounts[3+i];
-# tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], sender, t.address, amount).transact({'from': self.w3.eth.accounts[2]})
-#
-# w.functions.nay(1).transact({'from': self.w3.eth.accounts[0]})
-# w.functions.nay(4).transact({'from': self.w3.eth.accounts[0]})
-#
-# self.assertEqual(w.functions.getSerialAt(0).call(), 2)
-# self.assertEqual(w.functions.getSerialAt(1).call(), 3)
-# self.assertEqual(w.functions.getSerialAt(2).call(), 5)
-#
-#
-# def test_index_after_removal(self):
-# w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
-# t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-#
-# for i in range(0, 4):
-# amount = 10*(i+1)
-# sender = self.w3.eth.accounts[3+i];
-# tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], sender, t.address, amount).transact({'from': self.w3.eth.accounts[2]})
-#
-# tq_count = w.functions.count().call()
-# self.assertEqual(tq_count, 4);
-# self.assertEqual(w.functions.lastSerial().call(), 4)
-# self.assertEqual(w.functions.nextSerial().call(), 1)
-#
-# w.functions.nay(2).transact({'from': self.w3.eth.accounts[0]})
-# self.assertEqual(w.functions.count().call(), 3)
-# self.assertEqual(w.functions.nextSerial().call(), 1)
-# self.assertEqual(w.functions.lastSerial().call(), 4)
-#
-# w.functions.nay(1).transact({'from': self.w3.eth.accounts[0]})
-# self.assertEqual(w.functions.count().call(), 2)
-# self.assertEqual(w.functions.nextSerial().call(), 3)
-# self.assertEqual(w.functions.lastSerial().call(), 4)
-#
-# w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 42).transact({'from': self.w3.eth.accounts[2]})
-# self.assertEqual(w.functions.count().call(), 3)
-# self.assertEqual(w.functions.lastSerial().call(), 5)
-# self.assertEqual(w.functions.nextSerial().call(), 3)
-#
-# w.functions.nay(3).transact({'from': self.w3.eth.accounts[0]})
-# self.assertEqual(w.functions.count().call(), 2)
-# self.assertEqual(w.functions.lastSerial().call(), 5)
-# self.assertEqual(w.functions.nextSerial().call(), 4)
-#
-# w.functions.nay(4).transact({'from': self.w3.eth.accounts[0]})
-# self.assertEqual(w.functions.count().call(), 1)
-# self.assertEqual(w.functions.nextSerial().call(), 5)
-# self.assertEqual(w.functions.lastSerial().call(), 5)
-#
-# w.functions.nay(5).transact({'from': self.w3.eth.accounts[0]})
-# self.assertEqual(w.functions.count().call(), 0)
-# self.assertEqual(w.functions.nextSerial().call(), 0)
-# self.assertEqual(w.functions.lastSerial().call(), 5)
-#
-#
-# def test_pass_on_insufficient_approve(self):
-# w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
-# t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-#
-# self.eth_tester.mine_block()
-#
-# w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[2]})
-# w.functions.yay(1).transact({'from': self.w3.eth.accounts[0]})
-# self.eth_tester.mine_block()
-#
-# tx_hash = w.functions.executeRequest(1).transact({'from': self.w3.eth.accounts[0]})
-#
-# r = self.w3.eth.getTransactionReceipt(tx_hash)
-#
-# topic_match = 'dab20a0fcd702cf875c2d715d5c3fc99af66a716c94b3405408c94b7311c99eb' # TransferFail(uint256)
-# log = r.logs[0]
-# topic = log.topics[0]
-# self.assertEqual(topic.hex()[2:], topic_match)
-# serial = int(log.data[2:], 16)
-#
-# self.assertEqual(serial, 1)
-#
-# self.assertEqual(w.functions.count().call(), 0)
-# self.assertEqual(w.functions.nextSerial().call(), 0)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/python/tests/test_basic.py b/python/tests/test_basic.py
@@ -0,0 +1,121 @@
+# standard imports
+import os
+import unittest
+import logging
+
+# external imports
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.tx import receipt
+
+# local imports
+from erc20_transfer_authorization import TransferAuthorization
+from erc20_transfer_authorization.unittest import TestBase
+
+logg = logging.getLogger()
+
+testdir = os.path.dirname(__file__)
+
+
+class TestBasic(TestBase):
+
+ def setUp(self):
+ super(TestBasic, self).setUp()
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ self.c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = self.c.add_writer(self.address, self.accounts[0], self.accounts[1])
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.add_writer(self.address, self.accounts[0], self.accounts[2])
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+
+ def test_basic(self):
+ c = TransferAuthorization(self.chain_spec)
+
+ o = c.is_writer(self.address, self.accounts[0], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ self.assertTrue(c.parse_signers(r))
+
+ o = c.is_writer(self.address, self.accounts[1], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ self.assertTrue(c.parse_signers(r))
+
+ o = c.is_writer(self.address, self.accounts[2], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ self.assertTrue(c.parse_signers(r))
+
+ o = c.is_writer(self.address, self.accounts[3], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ self.assertFalse(c.parse_signers(r))
+
+ o = c.signer_count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = c.parse_count(r)
+ self.assertEqual(count, 3)
+
+
+# def test_limit(self):
+# nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+# c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+#
+# (tx_hash_hex, o) = c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+# self.rpc.do(o)
+# o = receipt(tx_hash_hex)
+# r = self.rpc.do(o)
+# self.assertEqual(r['status'], 1)
+#
+# (tx_hash_hex, o) = c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+# self.rpc.do(o)
+# o = receipt(tx_hash_hex)
+# r = self.rpc.do(o)
+# self.assertEqual(r['status'], 1)
+#
+# (tx_hash_hex, o) = c.yay(self.address, self.accounts[0], 1)
+# self.rpc.do(o)
+# o = receipt(tx_hash_hex)
+# r = self.rpc.do(o)
+# self.assertEqual(r['status'], 1)
+#
+# (tx_hash_hex, o) = c.yay(self.address, self.accounts[0], 2)
+# self.rpc.do(o)
+# o = receipt(tx_hash_hex)
+# r = self.rpc.do(o)
+# self.assertEqual(r['status'], 1)
+#
+# (tx_hash_hex, o) = c.check_result(self.address, self.accounts[0], 1)
+# self.rpc.do(o)
+# o = receipt(tx_hash_hex)
+# r = self.rpc.do(o)
+# self.assertEqual(r['status'], 1)
+#
+# o = c.requests(self.address, 1, sender_address=self.accounts[0])
+# r = self.rpc.do(o)
+# request = self.c.parse_request(r)
+# logg.debug('request {}'.format(request))
+# self.assertTrue(request.is_accepted())
+
+
+ def test_serial(self):
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ for i in range(5):
+ (tx_hash_hex, o) = c.create_request(self.address, self.accounts[0], self.accounts[i], self.accounts[i+1], self.token_address, 1024 * i)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = c.count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = c.parse_count(r)
+ self.assertEqual(count, 5)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/test_quorum.py b/python/tests/test_quorum.py
@@ -1,298 +1,516 @@
# standard imports
-import logging
+import os
import unittest
+import logging
-# testutil imports
-from tests.base_erc20transferauthorization import TestBase
-
-logg = logging.getLogger()
-
-rejected_log_signature = '3d61d434b895790b08f040c45261fce3b3bec596278b3a0f25dd9f741d0ba469'
-vetoed_log_signature = '1ad80b2541a1f52bdc838332d7c23606116a1188a8cbbc4c0948b4b56ce51d14'
-approved_log_signature = '36ea04725f8aa40ee603224671681b753f9cba3cb5f67c5a0e24a3b39900c065'
-
-
-class ERC20TransferAuthorizationQuorumTest(TestBase):
-
- @unittest.skip('must be ported to chainlib')
- def test_vote_access(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- w.functions.addSigner(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.setThresholds(2, 0).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- # only signers may vote
- with self.assertRaises(Exception):
- tx_hashh = w.functions.yay(serial).transact({'from': self.w3.eth.accounts[2]})
-
- # only signers may vote
- with self.assertRaises(Exception):
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[2]})
-
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[0]})
-
- # may not vote twice
- with self.assertRaises(Exception):
- tx_hashh = w.functions.yay(serial).transact({'from': self.w3.eth.accounts[0]})
-
- # may not change vote
- with self.assertRaises(Exception):
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[5]})
-
- # may not vote twice
- with self.assertRaises(Exception):
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[5]})
-
- # may not change vote
- with self.assertRaises(Exception):
- tx_hashh = w.functions.yay(serial).transact({'from': self.w3.eth.accounts[5]})
-
-
- @unittest.skip('must be ported to chainlib')
- def test_minimal_quorum(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- t.functions.approve(w.address, 10).transact({'from': self.w3.eth.accounts[2]})
- self.eth_tester.mine_block()
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- with self.assertRaises(Exception):
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
-
- # only signers may vote
- with self.assertRaises(Exception):
- tx_hashh = w.functions.yay(serial).transact({'from': self.w3.eth.accounts[2]})
-
- tx_hashh = w.functions.yay(serial).transact({'from': self.w3.eth.accounts[0]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
-
- topic_match = approved_log_signature
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
-
- tx_hashh = w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
-
- topic_match = 'bcf6a68a2f901be4a23a41b53acd7697893a7e34def4e28acba584da75283b67' # Executed(serial)
- log = r.logs[1]
- topic = log.topics[0].hex()[2:]
- self.assertEqual(topic, topic_match)
-
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[2]).call(), 90)
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[3]).call(), 10)
-
-
- @unittest.skip('must be ported to chainlib')
- def test_simple_quorum(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- t.functions.approve(w.address, 10).transact({'from': self.w3.eth.accounts[2]})
- self.eth_tester.mine_block()
-
- w.functions.addSigner(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.addSigner(self.w3.eth.accounts[6]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.setThresholds(2, 0).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- tx_hashh = w.functions.yay(serial).transact({'from': self.w3.eth.accounts[0]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
- self.assertEqual(len(r.logs), 0)
-
- # attempt to execute fails
- with self.assertRaises(Exception):
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
-
- # dough is still there
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[2]).call(), 100)
+# external imports
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.address import is_same_address
+from chainlib.eth.tx import receipt
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[5]})
-
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
+# local imports
+from erc20_transfer_authorization import TransferAuthorization
+from erc20_transfer_authorization.unittest import TestBase
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[2]).call(), 90)
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[3]).call(), 10)
-
- # additional votes not possible
- with self.assertRaises(Exception):
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[6]})
+logg = logging.getLogger()
- with self.assertRaises(Exception):
- w.functions.nay(serial).transact({'from': self.w3.eth.accounts[6]})
+testdir = os.path.dirname(__file__)
+
+
+class TestQuorum(TestBase):
+
+ def setUp(self):
+ super(TestQuorum, self).setUp()
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ self.c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+
+ for i in range(1, 5):
+ (tx_hash_hex, o) = self.c.add_writer(self.address, self.accounts[0], self.accounts[i])
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+
+ def test_basic(self):
+ o = self.c.quorum_threshold(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 1)
+
+ o = self.c.veto_threshold(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 0)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 3, 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.quorum_threshold(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 3)
+
+ o = self.c.veto_threshold(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 1)
+
+
+ def test_signer_sanity(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 0, 0)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 0, 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 5, 0)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 6, 0)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 5, 5)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 5, 6)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+
+ def test_register(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(is_same_address(request.sender, self.accounts[1]))
+ self.assertTrue(is_same_address(request.recipient, self.accounts[2]))
+ self.assertTrue(is_same_address(request.token, self.token_address))
+ self.assertEqual(request.value, 1024)
+ self.assertEqual(request.serial, 1)
+ self.assertEqual(request.yay, 1)
+ self.assertEqual(request.nay, 0)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
- @unittest.skip('must be ported to chainlib')
- def test_minimal_rejection(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[0]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
-
- topic_match = rejected_log_signature
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
-
- # cannot execute
- with self.assertRaises(Exception):
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
-
-
- @unittest.skip('must be ported to chainlib')
- def test_simple_rejection(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- t.functions.approve(w.address, 10).transact({'from': self.w3.eth.accounts[2]})
- self.eth_tester.mine_block()
-
- w.functions.addSigner(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.addSigner(self.w3.eth.accounts[6]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.setThresholds(2, 0).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[0]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
- self.assertEqual(len(r.logs), 0)
-
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[5]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
-
- topic_match = rejected_log_signature
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
-
- # cannot execute
- with self.assertRaises(Exception):
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
-
- # additional votes not possible
- with self.assertRaises(Exception):
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[6]})
-
- with self.assertRaises(Exception):
- w.functions.nay(serial).transact({'from': self.w3.eth.accounts[6]})
-
-
- @unittest.skip('must be ported to chainlib')
def test_veto(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- t.functions.approve(w.address, 10).transact({'from': self.w3.eth.accounts[2]})
- self.eth_tester.mine_block()
-
- w.functions.addSigner(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.addSigner(self.w3.eth.accounts[6]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.setThresholds(2, 1).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[0]})
- tx_hashh = w.functions.nay(serial).transact({'from': self.w3.eth.accounts[5]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
-
- topic_match = vetoed_log_signature
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
-
- # cannot execute
- with self.assertRaises(Exception):
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
-
- # additional votes not possible
- with self.assertRaises(Exception):
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[6]})
-
- with self.assertRaises(Exception):
- w.functions.nay(serial).transact({'from': self.w3.eth.accounts[6]})
-
-
- @unittest.skip('must be ported to chainlib')
- def test_inflight_change(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
-
- w.functions.addSigner(self.w3.eth.accounts[5]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.addSigner(self.w3.eth.accounts[6]).transact({'from': self.w3.eth.accounts[0]})
- w.functions.setThresholds(2, 0).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
-
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
-
- w.functions.nay(serial).transact({'from': self.w3.eth.accounts[0]})
- w.functions.removeSigner(self.w3.eth.accounts[6]).transact({'from': self.w3.eth.accounts[0]})
-
- tx_hashh = w.functions.checkResult(serial).transact({'from': self.w3.eth.accounts[6]})
- r = self.w3.eth.getTransactionReceipt(tx_hashh)
-
- topic_match = rejected_log_signature
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 1, 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_rejected())
+
+
+ def test_simple_yay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_accepted())
+
+
+ def test_nay_before_yay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertFalse(request.is_accepted())
+
+
+ def test_yay_nay_yay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_accepted())
+
+
+ def test_yay_yay_nay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ logg.debug('request {}'.format(request))
+ self.assertTrue(request.is_accepted())
+
+
+ def test_nay_yay_nay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_rejected())
+
+
+ def test_nay_yay_nay_yay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ logg.debug('request {}'.format(request))
+ self.assertTrue(request.is_rejected())
+
+
+ def test_nay_yay_nay_nay(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 2, 2)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.yay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ logg.debug('request {}'.format(request))
+ self.assertTrue(request.is_rejected())
+
+
+ def test_nay_majority(self):
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 3, 0)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[1], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[1], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc)
+ c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.nay(self.address, self.accounts[2], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ logg.debug('request {}'.format(request))
+ self.assertTrue(request.is_rejected())
if __name__ == '__main__':
diff --git a/python/tests/test_request.py b/python/tests/test_request.py
@@ -0,0 +1,275 @@
+# standard imports
+import os
+import unittest
+import logging
+import random
+
+# external imports
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.address import is_same_address
+from giftable_erc20_token import GiftableToken
+from eth_erc20 import ERC20
+from chainlib.eth.tx import receipt
+
+# local imports
+from erc20_transfer_authorization import TransferAuthorization
+from erc20_transfer_authorization.unittest import TestBase
+
+#logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+testdir = os.path.dirname(__file__)
+
+
+class TestRequest(TestBase):
+
+ def setUp(self):
+ super(TestRequest, self).setUp()
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ self.c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+
+ c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.mint_to(self.token_address, self.accounts[0], self.accounts[9], 10000)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[9], self.rpc)
+ c = ERC20(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.approve(self.token_address, self.accounts[9], self.address, 10000)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+
+ def test_basic(self):
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 0)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 0)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[2], self.token_address, 1)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[3], self.token_address, 2)
+ self.rpc.do(o)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 2)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 1)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 2)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 2)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 2)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 2)
+ self.rpc.do(o)
+
+ o = self.c.count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 0)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 2)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 0)
+
+
+ def test_hi_lo(self):
+ for i in range(5):
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[i+1], self.token_address, i+1)
+ self.rpc.do(o)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 5)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 6)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 5)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 5)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 5)
+ self.rpc.do(o)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 5)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 1)
+
+ o = self.c.requests(self.address, 5, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_executed())
+
+ o = self.c.count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 4)
+
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[0], self.token_address, 100)
+ self.rpc.do(o)
+
+ o = self.c.count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 5)
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 6)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 1)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 6)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 6)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 6)
+ self.rpc.do(o)
+
+ o = self.c.requests(self.address, 6, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_executed())
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 6)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 1)
+
+ c = ERC20(self.chain_spec)
+ o = c.balance(self.token_address, self.accounts[0], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ balance = c.parse_balance(r)
+ self.assertEqual(balance, 100)
+
+ o = c.balance(self.token_address, self.accounts[5], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ balance = c.parse_balance(r)
+ self.assertEqual(balance, 5)
+
+ o = c.balance(self.token_address, self.accounts[9], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ balance = c.parse_balance(r)
+ self.assertEqual(balance, 10000-100-5)
+
+
+ def test_hi_lo_shuffle(self):
+ for i in range(100):
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[(i+1)%8], self.token_address, i+1)
+ self.rpc.do(o)
+
+ v = list(range(1, 101))
+ c = 0
+ random.shuffle(v)
+ for i in v:
+ logg.info('processing request number {} at index {}'.format(c, i))
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], i)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], i)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ o = self.c.requests(self.address, i, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_rejected())
+
+ c += 1
+ o = self.c.count(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ count = self.c.parse_count(r)
+ self.assertEqual(count, 100-c)
+
+
+ o = self.c.last_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 100)
+
+ o = self.c.next_serial(self.address, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ serial = self.c.parse_count(r)
+ self.assertEqual(serial, 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/test_transfer.py b/python/tests/test_transfer.py
@@ -1,46 +1,138 @@
# standard imports
-import logging
+import os
import unittest
+import logging
+
+# external imports
+from chainlib.eth.nonce import RPCNonceOracle
+from chainlib.eth.address import is_same_address
+from chainlib.eth.tx import receipt
+from giftable_erc20_token import GiftableToken
+from eth_erc20 import ERC20
-# testutil imports
-from tests.base_erc20transferauthorization import TestBase
+# local imports
+from erc20_transfer_authorization import TransferAuthorization
+from erc20_transfer_authorization.unittest import TestBase
logg = logging.getLogger()
+testdir = os.path.dirname(__file__)
-class ERC20TransferAuthorizationTransferTest(TestBase):
- @unittest.skip('must be ported to chainlib')
- def test_transfer(self):
- w = self.w3.eth.contract(abi=self.abi_wallet, address=self.address_wallet)
- t = self.w3.eth.contract(abi=self.abi_token, address=self.address_token)
+class TestTransfer(TestBase):
+
+ def setUp(self):
+ super(TestTransfer, self).setUp()
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ self.c = TransferAuthorization(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+
+ c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.mint_to(self.token_address, self.accounts[0], self.accounts[9], 10000)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ nonce_oracle = RPCNonceOracle(self.accounts[9], self.rpc)
+ c = ERC20(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
+ (tx_hash_hex, o) = c.approve(self.token_address, self.accounts[9], self.address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+
+ def test_premature_transfer(self):
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
- t.functions.approve(w.address, 10).transact({'from': self.w3.eth.accounts[2]})
- self.eth_tester.mine_block()
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
- tx_hash = w.functions.createRequest(self.w3.eth.accounts[2], self.w3.eth.accounts[3], t.address, 10).transact({'from': self.w3.eth.accounts[9]})
- r = self.w3.eth.getTransactionReceipt(tx_hash)
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
- topic_match = 'b609ae609609ee99268d05bc1371102cafe8d6b964bf082439ab16be2a01c87c'
- log = r.logs[0]
- topic = log.topics[0]
- self.assertEqual(topic.hex()[2:], topic_match)
- serial = int(log.data[66:], 16)
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_voting())
+ self.assertFalse(request.is_executed())
+
+
+ def test_reject_transfer(self):
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
+
+ (tx_hash_hex, o) = self.c.set_thresholds(self.address, self.accounts[0], 1, 1)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.nay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
+
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ self.assertTrue(request.is_rejected())
+ self.assertFalse(request.is_voting())
+ self.assertFalse(request.is_executed())
+
+
+ def test_transfer(self):
+ (tx_hash_hex, o) = self.c.create_request(self.address, self.accounts[0], self.accounts[9], self.accounts[2], self.token_address, 1024)
+ self.rpc.do(o)
+
+ (tx_hash_hex, o) = self.c.yay(self.address, self.accounts[0], 1)
+ self.rpc.do(o)
- w.functions.yay(serial).transact({'from': self.w3.eth.accounts[0]})
- w.functions.executeRequest(serial).transact({'from': self.w3.eth.accounts[0]})
+ (tx_hash_hex, o) = self.c.check_result(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[2]).call(), 90)
- self.assertEqual(t.functions.balanceOf(self.w3.eth.accounts[3]).call(), 10)
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 1)
- req = w.functions.requests(1).call()
- self.assertEqual(req[7], self.w3.eth.blockNumber)
+ o = self.c.requests(self.address, 1, sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ request = self.c.parse_request(r)
+ logg.debug('request {}'.format(request))
+ self.assertTrue(request.is_transferred())
+ self.assertTrue(request.is_executed())
- serial_compare = w.functions.requestSenderIndex(self.w3.eth.accounts[2], 0).call()
- self.assertEqual(serial_compare, req[0])
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ c = ERC20(self.chain_spec, nonce_oracle=nonce_oracle)
+ o = c.balance(self.token_address, self.accounts[9], sender_address=self.accounts[0])
+ r = self.rpc.do(o)
+ balance = c.parse_balance(r)
+ self.assertEqual(balance, 10000-1024)
- serial_compare = w.functions.requestRecipientIndex(self.w3.eth.accounts[3], 0).call()
- self.assertEqual(serial_compare, req[0])
+ (tx_hash_hex, o) = self.c.execute_request(self.address, self.accounts[0], 1)
+ r = self.rpc.do(o)
+ o = receipt(tx_hash_hex)
+ r = self.rpc.do(o)
+ self.assertEqual(r['status'], 0)
if __name__ == '__main__':
diff --git a/solidity/ERC20TransferAuthorization.sol b/solidity/ERC20TransferAuthorization.sol
@@ -1,75 +1,86 @@
-pragma solidity >0.6.11;
+pragma solidity >0.8.0;
// SPDX-License-Identifier: GPL-3.0-or-later
contract ERC20TransferAuthorization {
struct Transaction {
- uint256 serial;
+ uint256 value;
address sender;
address recipient;
address token;
- uint256 value;
- uint256 yay;
- uint256 nay;
- uint256 blockNumber;
- int8 result; // -1 rejected/vetoed, 0 = completed, 1 = voting, 2 = approved
+ uint32 serial;
+ uint32 yay;
+ uint32 nay;
+ //uint256 blockNumber;
+ // bit 1: started
+ // bit 2: approved
+ // bit 3: rejected
+ // bit 4: finalized
+ // bit 5: transfererror
+ uint8 result;
}
- mapping ( uint256 => mapping ( address => int8 )) public vote;
- mapping ( uint256 => address[] ) public voters;
+ mapping ( uint32 => mapping ( address => int8 )) public vote;
+ //mapping ( uint256 => address[] ) public voters;
+ mapping( uint32 => Transaction ) public requests;
+ //mapping(address => uint256[]) public requestSenderIndex;
+ //mapping(address => uint256[]) public requestRecipientIndex;
address public owner;
- mapping(uint256 => Transaction) public requests;
- mapping(address => uint256[]) public requestSenderIndex;
- mapping(address => uint256[]) public requestRecipientIndex;
- uint256 hi;
- uint256 lo;
- int256 public count;
- uint256 public quorum;
- uint256 public vetoThreshold;
- uint256 public signerCount;
+ uint32 hi;
+ uint32 lo;
+ uint32 public count;
+ uint32 public quorum;
+ uint32 public vetoThreshold;
+ uint32 public signerCount;
mapping(address => bool) public signers;
-
- event NewRequest(address indexed _sender, address indexed _recipient, address indexed _token, uint256 _value, uint256 _serial);
- event Executed(uint256 _serial);
- event TransferFail(uint256 _serial);
- event QuorumSet(uint256 _quorum, uint256 _vetoThreshold, uint256 _signerCount);
- event SignerAdded(address _signer);
- event SignerRemoved(address _signer);
- event Vetoed(uint256 indexed _serial, uint256 _yays, uint256 _nays);
- event Approved(uint256 indexed _serial, uint256 _yays, uint256 _nays);
- event Rejected(uint256 indexed _serial, uint256 _yays, uint256 _nays);
+ address[] public writers;
+
+ event NewRequest(address indexed _sender, address indexed _recipient, address indexed _token, uint256 _value, uint32 _serial);
+ event Executed(uint32 _serial);
+ event TransferFail(uint32 _serial);
+ event QuorumSet(uint32 indexed _quorum, uint32 indexed _vetoThreshold, uint32 indexed _signerCount);
+ event WriterAdded(address _signer);
+ event WriterRemoved(address _signer);
+ event Vetoed(uint32 indexed _serial, uint32 indexed _yays, uint32 indexed _nays);
+ event Approved(uint32 indexed _serial, uint32 indexed _yays, uint32 indexed _nays);
+ event Rejected(uint32 indexed _serial, uint32 indexed _yays, uint32 indexed _nays);
constructor() public {
owner = msg.sender;
hi = 1;
lo = 1;
- addSigner(msg.sender);
+ addWriter(msg.sender);
setThresholds(1, 0);
}
- function addSigner(address _signer) public returns (uint256) {
+ function isWriter(address _signer) public view returns (bool) {
+ return signers[_signer];
+ }
+
+ function addWriter(address _signer) public returns (uint32) {
require(msg.sender == owner, 'ERR_ACCESS');
require(signers[_signer] == false, 'ERR_NOTFOUND');
signers[_signer] = true;
signerCount++;
- emit SignerAdded(_signer);
+ emit WriterAdded(_signer);
return signerCount;
}
- function removeSigner(address _signer) public returns (uint256) {
- require(msg.sender == owner || msg.sender == _signer, 'ERR_ACCESS');
+ function removeWriter(address _signer) public returns (uint32) {
+ //require(msg.sender == owner || msg.sender == _signer, 'ERR_ACCESS');
+ require(msg.sender == owner, 'ERR_ACCESS');
require(signers[_signer] == true, 'ERR_NOTFOUND');
require(signerCount > quorum && signerCount > vetoThreshold, 'ERR_REDUCE_THRESHOLD_FIRST');
signers[_signer] = false;
signerCount--;
- emit SignerRemoved(_signer);
+ emit WriterRemoved(_signer);
return signerCount;
}
- function setThresholds(uint256 _quorum, uint256 _vetoThreshold) public returns (bool) {
+ function setThresholds(uint32 _quorum, uint32 _vetoThreshold) public returns (bool) {
require(_quorum <= signerCount);
require(_quorum > 0);
require(_vetoThreshold <= signerCount);
@@ -81,7 +92,7 @@ contract ERC20TransferAuthorization {
}
// create new request
- function createRequest(address _sender, address _recipient, address _token, uint256 _value) public returns (uint256) {
+ function createRequest(address _sender, address _recipient, address _token, uint256 _value) public returns (uint32) {
Transaction storage txx = requests[hi];
txx.serial = hi;
@@ -91,7 +102,7 @@ contract ERC20TransferAuthorization {
txx.value = _value;
txx.result = 1;
- count++;
+ count++;
hi++;
emit NewRequest(txx.sender, txx.recipient, txx.token, txx.value, txx.serial);
@@ -101,12 +112,12 @@ contract ERC20TransferAuthorization {
// if request was oldest in index, move the pointer to oldest request to next oldest unfinished request.
// if no unfinished requests exits, it will point to newest request
- function removeItem(uint256 _serialToRemove) private returns (uint256) {
+ function removeItem(uint32 _serialToRemove) private returns (uint32) {
count--;
if (count > 0) {
if (_serialToRemove == lo) {
- uint256 i;
+ uint32 i;
i = getSerialAt(0);
if (i == 0) {
lo = hi;
@@ -114,7 +125,7 @@ contract ERC20TransferAuthorization {
lo = i;
}
}
- } else {
+ } else if (lo != hi) {
lo = hi;
}
@@ -122,24 +133,36 @@ contract ERC20TransferAuthorization {
}
// index of newest vote
- function lastSerial() public view returns ( uint256 ) {
+ function lastSerial() public view returns ( uint32 ) {
return hi - 1;
}
// index of oldest unfinished vote
- function nextSerial() public view returns ( uint256 ) {
+ function nextSerial() public view returns ( uint32 ) {
if (hi - lo == 0) {
+ if (hi == 1) {
+ return 0;
+ }
+ Transaction storage txx = requests[lo];
+ if (txx.result > 0) {
+ return lo;
+ }
return 0;
}
return lo;
}
- // get the unfinished vote at the given index
- function getSerialAt(uint256 _idx) public view returns ( uint256 ) {
- uint256 i;
- for (uint256 j = lo; j < hi; j++) {
+ // get the nth unfinished vote, where nth is _idx, starting at 0
+ function getSerialAt(uint32 _idx) public view returns ( uint32 ) {
+ uint32 i;
+
+ if (lo == hi) {
+ return 0;
+ }
+
+ for (uint32 j = lo; j < hi; j++) {
Transaction storage txx = requests[j];
- if (txx.result > 0) {
+ if (txx.result & 7 == 1) {
if (i == _idx) {
return txx.serial;
}
@@ -150,7 +173,7 @@ contract ERC20TransferAuthorization {
}
// vote yay, one per signer
- function yay(uint256 _serial) public returns (uint256) {
+ function yay(uint32 _serial) public returns (uint32) {
require(signers[msg.sender], 'ERR_ACCESS');
require(vote[_serial][msg.sender] == 0, 'ERR_ALREADYVOTED');
@@ -158,7 +181,7 @@ contract ERC20TransferAuthorization {
require(txx.result == 1);
vote[txx.serial][msg.sender] = 1;
- voters[txx.serial].push(msg.sender);
+ //voters[txx.serial].push(msg.sender);
txx.yay++;
checkResult(txx.serial);
@@ -167,7 +190,7 @@ contract ERC20TransferAuthorization {
}
// vote nay, one per signer
- function nay(uint256 _serial) public returns (uint256) {
+ function nay(uint32 _serial) public returns (uint32) {
require(signers[msg.sender], 'ERR_ACCESS');
require(vote[_serial][msg.sender] == 0, 'ERR_ALREADYVOTED');
@@ -175,7 +198,7 @@ contract ERC20TransferAuthorization {
require(txx.result == 1);
vote[txx.serial][msg.sender] = -1;
- voters[txx.serial].push(msg.sender);
+ //voters[txx.serial].push(msg.sender);
txx.nay++;
checkResult(txx.serial);
@@ -185,25 +208,25 @@ contract ERC20TransferAuthorization {
// locks the state of the vote if quorum or veto is reached
// returns true if state changes
- function checkResult(uint256 _serial) public returns (bool) {
+ function checkResult(uint32 _serial) public returns (bool) {
bool result;
Transaction storage txx = requests[_serial];
- if (txx.result < 1) {
+ if (txx.result < 1 || txx.result & 6 > 0) {
return result;
}
if (txx.yay >= quorum) {
- txx.result = 2;
+ txx.result |= 2;
emit Approved(txx.serial, txx.yay, txx.nay);
result = true;
} else if (vetoThreshold > 0 && txx.nay >= vetoThreshold) {
- txx.result = -1;
+ txx.result |= 4;
removeItem(txx.serial);
emit Vetoed(txx.serial, txx.yay, txx.nay);
result = true;
} else if (signerCount - txx.nay < quorum) {
- txx.result = -1;
+ txx.result |= 4;
removeItem(txx.serial);
emit Rejected(txx.serial, txx.yay, txx.nay);
result = true;
@@ -213,24 +236,24 @@ contract ERC20TransferAuthorization {
}
// execute transfer. needs positive vote result
- function executeRequest(uint256 _serial) public returns (bool) {
+ function executeRequest(uint32 _serial) public returns (bool) {
Transaction storage txx = requests[_serial];
require(txx.serial > 0, 'ERR_INVALID_REQUEST');
- require(txx.result == 2, 'ERR_NOT_ENDORSED');
+ require(txx.result & 11 == 3, 'ERR_NOT_ENDORSED');
- txx.result = 0;
+ removeItem(txx.serial);
+ txx.result |= 8;
(bool success, bytes memory _r) = txx.token.call(abi.encodeWithSignature("transferFrom(address,address,uint256)", txx.sender, txx.recipient, txx.value));
- removeItem(txx.serial);
-
- txx.blockNumber = block.number;
- requestSenderIndex[txx.sender].push(txx.serial);
- requestRecipientIndex[txx.recipient].push(txx.serial);
+ //txx.blockNumber = block.number;
+ //requestSenderIndex[txx.sender].push(txx.serial);
+ //requestRecipientIndex[txx.recipient].push(txx.serial);
if (success) {
emit Executed(_serial);
} else {
+ txx.result |= 16; // this edit is for convenience only. since bit 4 is already set, it is not re-entrant.
emit TransferFail(_serial);
}