From 4d29d5c7eab959d1684f2ea7334c67e1e2bfe020 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sun, 24 Sep 2023 01:45:35 +0200 Subject: [PATCH 01/82] Update delay bytecode --- sdk/initData/Delay.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/initData/Delay.ts b/sdk/initData/Delay.ts index a02cb90c..78f6c2f7 100644 --- a/sdk/initData/Delay.ts +++ b/sdk/initData/Delay.ts @@ -1,4 +1,4 @@ export const salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; export const initCode = - "0x60806040523480156200001157600080fd5b5060405162004e2138038062004e21833981810160405281019062000037919062000a30565b600085858585856040516020016200005495949392919062000d57565b604051602081830303815290604052905062000076816200008260201b60201c565b50505050505062000f53565b600080600080600085806020019051810190620000a09190620009ae565b94509450945094509450620000ba6200032a60201b60201c565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156200012d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001249062000e5e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415620001a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001979062000dd6565b60405180910390fd5b6000811480620001b15750603c8110155b620001f3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001ea9062000e3c565b60405180910390fd5b83606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080606a819055508160698190555062000294856200042960201b60201c565b620002a46200053f60201b60201c565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffd805e12a6d02f83d7029c03fdfcf3f226ebcd409af51b3095237015eae50300866040516200031a919062000d3a565b60405180910390a4505050505050565b600060019054906101000a900460ff168062000351575060008054906101000a900460ff16155b62000393576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038a9062000df8565b60405180910390fd5b60008060019054906101000a900460ff161590508015620003e4576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b620003f46200069360201b60201c565b620004046200077260201b60201c565b8015620004265760008060016101000a81548160ff0219169083151502179055505b50565b620004396200087160201b60201c565b73ffffffffffffffffffffffffffffffffffffffff166200045f6200087960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620004b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004af9062000e1a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200052b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005229062000db4565b60405180910390fd5b6200053c81620008a360201b60201c565b50565b600073ffffffffffffffffffffffffffffffffffffffff1660686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161462000611576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006089062000e80565b60405180910390fd5b600160686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600060019054906101000a900460ff1680620006ba575060008054906101000a900460ff16155b620006fc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006f39062000df8565b60405180910390fd5b60008060019054906101000a900460ff1615905080156200074d576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b80156200076f5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff168062000799575060008054906101000a900460ff16155b620007db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007d29062000df8565b60405180910390fd5b60008060019054906101000a900460ff1615905080156200082c576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6200084c620008406200087160201b60201c565b620008a360201b60201c565b80156200086e5760008060016101000a81548160ff0219169083151502179055505b50565b600033905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000815190506200097a8162000f05565b92915050565b600081519050620009918162000f1f565b92915050565b600081519050620009a88162000f39565b92915050565b600080600080600060a08688031215620009c757600080fd5b6000620009d78882890162000980565b9550506020620009ea8882890162000980565b9450506040620009fd8882890162000980565b935050606062000a108882890162000997565b925050608062000a238882890162000997565b9150509295509295909350565b600080600080600060a0868803121562000a4957600080fd5b600062000a598882890162000969565b955050602062000a6c8882890162000969565b945050604062000a7f8882890162000969565b935050606062000a928882890162000997565b925050608062000aa58882890162000997565b9150509295509295909350565b62000abd8162000eb3565b82525050565b600062000ad260268362000ea2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600062000b3a601e8362000ea2565b91507f5461726765742063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b600062000b7c602e8362000ea2565b91507f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008301527f647920696e697469616c697a65640000000000000000000000000000000000006020830152604082019050919050565b600062000be460208362000ea2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b600062000c26602d8362000ea2565b91507f457870697261746974696f6e206d7573742062652030206f72206174206c656160008301527f7374203630207365636f6e6473000000000000000000000000000000000000006020830152604082019050919050565b600062000c8e601e8362000ea2565b91507f4176617461722063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b600062000cd060248362000ea2565b91507f73657455704d6f64756c65732068617320616c7265616479206265656e20636160008301527f6c6c6564000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b62000d348162000efb565b82525050565b600060208201905062000d51600083018462000ab2565b92915050565b600060a08201905062000d6e600083018862000ab2565b62000d7d602083018762000ab2565b62000d8c604083018662000ab2565b62000d9b606083018562000d29565b62000daa608083018462000d29565b9695505050505050565b6000602082019050818103600083015262000dcf8162000ac3565b9050919050565b6000602082019050818103600083015262000df18162000b2b565b9050919050565b6000602082019050818103600083015262000e138162000b6d565b9050919050565b6000602082019050818103600083015262000e358162000bd5565b9050919050565b6000602082019050818103600083015262000e578162000c17565b9050919050565b6000602082019050818103600083015262000e798162000c7f565b9050919050565b6000602082019050818103600083015262000e9b8162000cc1565b9050919050565b600082825260208201905092915050565b600062000ec08262000edb565b9050919050565b600062000ed48262000edb565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000f108162000eb3565b811462000f1c57600080fd5b50565b62000f2a8162000ec7565b811462000f3657600080fd5b50565b62000f448162000efb565b811462000f5057600080fd5b50565b613ebe8062000f636000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c80637ceab3b11161010f578063d4b83992116100a2578063e19a9dd911610071578063e19a9dd914610582578063ebb2b4a21461059e578063ee072baf146105ba578063f2fde38b146105d6576101e5565b8063d4b839921461050c578063dcafac091461052a578063de8dd91d14610548578063e009cfde14610566576101e5565b8063b19d4758116100de578063b19d475814610495578063c66323e51461049f578063c9106389146104bd578063cc2f8452146104db576101e5565b80637ceab3b1146104215780638da5cb5b1461043f5780639b56d5be1461045d578063a4f9edbf14610479576101e5565b806346ba230711610187578063610b592511610156578063610b5925146103af5780636b0a4cf6146103cb578063715018a6146103fb578063776d1a0114610405576101e5565b806346ba2307146103265780635229073f146103425780635aef7de614610373578063605df59c14610391576101e5565b8063300c661f116101c3578063300c661f146102665780633aa7690614610296578063427e232f146102c6578063468721a7146102f6576101e5565b8063086cfca8146101ea578063258148cc146102065780632d9ad53d14610236575b600080fd5b61020460048036038101906101ff9190612b58565b6105f2565b005b610220600480360381019061021b9190612dd5565b610734565b60405161022d9190613a47565b60405180910390f35b610250600480360381019061024b9190612b58565b61074c565b60405161025d919061373d565b60405180910390f35b610280600480360381019061027b9190612cf0565b61081e565b60405161028d9190613788565b60405180910390f35b6102b060048036038101906102ab9190612dd5565b610857565b6040516102bd9190613a47565b60405180910390f35b6102e060048036038101906102db9190612dd5565b610874565b6040516102ed9190613788565b60405180910390f35b610310600480360381019061030b9190612c70565b61088c565b60405161031d919061373d565b60405180910390f35b610340600480360381019061033b9190612dd5565b610a5c565b005b61035c60048036038101906103579190612c70565b610b6b565b60405161036a929190613758565b60405180910390f35b61037b610c48565b604051610388919061359f565b60405180910390f35b610399610c6e565b6040516103a69190613a47565b60405180910390f35b6103c960048036038101906103c49190612b58565b610c74565b005b6103e560048036038101906103e09190612dd5565b610ffe565b6040516103f29190613788565b60405180910390f35b61040361101b565b005b61041f600480360381019061041a9190612b58565b6110a3565b005b6104296111e5565b604051610436919061359f565b60405180910390f35b61044761120b565b604051610454919061359f565b60405180910390f35b61047760048036038101906104729190612dd5565b611235565b005b610493600480360381019061048e9190612d94565b61130a565b005b61049d61158c565b005b6104a7611601565b6040516104b49190613a47565b60405180910390f35b6104c5611607565b6040516104d2919061359f565b60405180910390f35b6104f560048036038101906104f09190612c34565b611631565b60405161050392919061370d565b60405180910390f35b61051461187e565b604051610521919061359f565b60405180910390f35b6105326118a4565b60405161053f9190613a47565b60405180910390f35b6105506118aa565b60405161055d9190613a47565b60405180910390f35b610580600480360381019061057b9190612bf8565b6118b0565b005b61059c60048036038101906105979190612b58565b611c39565b005b6105b860048036038101906105b39190612dd5565b611e6f565b005b6105d460048036038101906105cf9190612c70565b611ef5565b005b6105f060048036038101906105eb9190612b58565b612171565b005b6105fa612269565b73ffffffffffffffffffffffffffffffffffffffff1661061861120b565b73ffffffffffffffffffffffffffffffffffffffff161461066e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610665906138c7565b60405180910390fd5b6000606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f52ae88b092de36f87fb43fe794eb1381023b9c1bce563a871154022c63dce34260405160405180910390a35050565b606e6020528060005260406000206000915090505481565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156108175750600073ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000848484846040516020016108379493929190613555565b604051602081830303815290604052805190602001209050949350505050565b6000606e6000838152602001908152602001600020549050919050565b606d6020528060005260406000206000915090505481565b60008073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561095c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095390613947565b60405180910390fd5b6109ac868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508561081e565b606d6000606c5481526020019081526020016000208190555042606e6000606c54815260200190815260200160002081905550606d6000606c54815260200190815260200160002054606c547f4c8a9c748e976c17c2eb2c2bc50da76eac9cd90ff529f0fe900e0c10a179f0318888888888604051610a2f9594939291906135ba565b60405180910390a3606c6000815480929190610a4a90613cc7565b91905055506001905095945050505050565b610a64612269565b73ffffffffffffffffffffffffffffffffffffffff16610a8261120b565b73ffffffffffffffffffffffffffffffffffffffff1614610ad8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610acf906138c7565b60405180910390fd5b606b548111610b1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b13906138a7565b60405180910390fd5b606c54811115610b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b58906138e7565b60405180910390fd5b80606b8190555050565b60006060600073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610c3e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3590613947565b60405180910390fd5b9550959350505050565b606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606a5481565b610c7c612269565b73ffffffffffffffffffffffffffffffffffffffff16610c9a61120b565b73ffffffffffffffffffffffffffffffffffffffff1614610cf0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce7906138c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610d5a5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b610d99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9090613a07565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5e906139a7565b60405180910390fd5b60686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844081604051610ff3919061359f565b60405180910390a150565b6000606d6000838152602001908152602001600020549050919050565b611023612269565b73ffffffffffffffffffffffffffffffffffffffff1661104161120b565b73ffffffffffffffffffffffffffffffffffffffff1614611097576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161108e906138c7565b60405180910390fd5b6110a16000612271565b565b6110ab612269565b73ffffffffffffffffffffffffffffffffffffffff166110c961120b565b73ffffffffffffffffffffffffffffffffffffffff161461111f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611116906138c7565b60405180910390fd5b6000606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f90cc2f570a6eb594b1580ea3e41247d2d73a55281889e86bd4ec2fc29c7e62d660405160405180910390a35050565b606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61123d612269565b73ffffffffffffffffffffffffffffffffffffffff1661125b61120b565b73ffffffffffffffffffffffffffffffffffffffff16146112b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112a8906138c7565b60405180910390fd5b60008114806112c15750603c8110155b611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613907565b60405180910390fd5b80606a8190555050565b6000806000806000858060200190518101906113269190612b81565b94509450945094509450611338612337565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156113a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161139f90613927565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140f90613867565b60405180910390fd5b60008114806114285750603c8110155b611467576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145e90613907565b60405180910390fd5b83606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080606a819055508160698190555061150085612171565b611508612420565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffd805e12a6d02f83d7029c03fdfcf3f226ebcd409af51b3095237015eae503008660405161157c919061359f565b60405180910390a4505050505050565b5b6000606a54141580156115ce575042606a54606954606e6000606b548152602001908152602001600020546115c29190613b34565b6115cc9190613b34565b105b80156115dd5750606c54606b54105b156115ff57606b60008154809291906115f590613cc7565b919050555061158d565b565b606b5481565b6000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008267ffffffffffffffff811115611675577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156116a35781602001602082028036833780820191505090505b509150600080606860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156117765750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561178157508482105b1561186f57808483815181106117c0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050818061186790613cc7565b92505061170c565b80925081845250509250929050565b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60695481565b606c5481565b6118b8612269565b73ffffffffffffffffffffffffffffffffffffffff166118d661120b565b73ffffffffffffffffffffffffffffffffffffffff161461192c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611923906138c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156119965750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6119d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119cc90613a07565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611aa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a99906137e7565b60405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427681604051611c2d919061359f565b60405180910390a15050565b611c41612269565b73ffffffffffffffffffffffffffffffffffffffff16611c5f61120b565b73ffffffffffffffffffffffffffffffffffffffff1614611cb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cac906138c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611dd2578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401611d4291906137cc565b60206040518083038186803b158015611d5a57600080fd5b505afa158015611d6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d929190612d6b565b611dd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc890613967565b60405180910390fd5b5b80606560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa2606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611e64919061359f565b60405180910390a150565b611e77612269565b73ffffffffffffffffffffffffffffffffffffffff16611e9561120b565b73ffffffffffffffffffffffffffffffffffffffff1614611eeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee2906138c7565b60405180910390fd5b8060698190555050565b606c54606b5410611f3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f32906139e7565b60405180910390fd5b606954606e6000606b5481526020019081526020016000205442611f5f9190613b8a565b1015611fa0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f9790613987565b60405180910390fd5b6000606a541461201d5742606a54606954606e6000606b54815260200190815260200160002054611fd19190613b34565b611fdb9190613b34565b101561201c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201390613827565b60405180910390fd5b5b61206d858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508461081e565b606d6000606b54815260200190815260200160002054146120c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120ba90613847565b60405180910390fd5b606b60008154809291906120d690613cc7565b919050555061212b858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505084612571565b61216a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161216190613a27565b60405180910390fd5b5050505050565b612179612269565b73ffffffffffffffffffffffffffffffffffffffff1661219761120b565b73ffffffffffffffffffffffffffffffffffffffff16146121ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e4906138c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561225d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225490613807565b60405180910390fd5b61226681612271565b50565b600033905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600060019054906101000a900460ff168061235d575060008054906101000a900460ff16155b61239c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239390613887565b60405180910390fd5b60008060019054906101000a900460ff1615905080156123ec576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6123f4612866565b6123fc61293f565b801561241d5760008060016101000a81548160ff0219169083151502179055505b50565b600073ffffffffffffffffffffffffffffffffffffffff1660686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146124ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124e6906139c7565b60405180910390fd5b600160686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146126a357606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166375f0bb528686868660008060008060006040518060400160405280600281526020017f307800000000000000000000000000000000000000000000000000000000000081525060006040518c63ffffffff1660e01b81526004016126709b9a99989796959493929190613654565b600060405180830381600087803b15801561268a57600080fd5b505af115801561269e573d6000803e3d6000fd5b505050505b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663468721a7868686866040518563ffffffff1660e01b81526004016127049493929190613608565b602060405180830381600087803b15801561271e57600080fd5b505af1158015612732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127569190612d6b565b9050600073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461285e57606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663932713687f3078000000000000000000000000000000000000000000000000000000000000836040518363ffffffff1660e01b815260040161282b9291906137a3565b600060405180830381600087803b15801561284557600080fd5b505af1158015612859573d6000803e3d6000fd5b505050505b949350505050565b600060019054906101000a900460ff168061288c575060008054906101000a900460ff16155b6128cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128c290613887565b60405180910390fd5b60008060019054906101000a900460ff16159050801561291b576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b801561293c5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff1680612965575060008054906101000a900460ff16155b6129a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299b90613887565b60405180910390fd5b60008060019054906101000a900460ff1615905080156129f4576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b612a046129ff612269565b612271565b8015612a255760008060016101000a81548160ff0219169083151502179055505b50565b6000612a3b612a3684613a93565b613a62565b905082815260208101848484011115612a5357600080fd5b612a5e848285613c85565b509392505050565b600081359050612a7581613e1c565b92915050565b600081519050612a8a81613e33565b92915050565b600081519050612a9f81613e4a565b92915050565b60008083601f840112612ab757600080fd5b8235905067ffffffffffffffff811115612ad057600080fd5b602083019150836001820283011115612ae857600080fd5b9250929050565b600082601f830112612b0057600080fd5b8135612b10848260208601612a28565b91505092915050565b600081359050612b2881613e61565b92915050565b600081359050612b3d81613e71565b92915050565b600081519050612b5281613e71565b92915050565b600060208284031215612b6a57600080fd5b6000612b7884828501612a66565b91505092915050565b600080600080600060a08688031215612b9957600080fd5b6000612ba788828901612a7b565b9550506020612bb888828901612a7b565b9450506040612bc988828901612a7b565b9350506060612bda88828901612b43565b9250506080612beb88828901612b43565b9150509295509295909350565b60008060408385031215612c0b57600080fd5b6000612c1985828601612a66565b9250506020612c2a85828601612a66565b9150509250929050565b60008060408385031215612c4757600080fd5b6000612c5585828601612a66565b9250506020612c6685828601612b2e565b9150509250929050565b600080600080600060808688031215612c8857600080fd5b6000612c9688828901612a66565b9550506020612ca788828901612b2e565b945050604086013567ffffffffffffffff811115612cc457600080fd5b612cd088828901612aa5565b93509350506060612ce388828901612b19565b9150509295509295909350565b60008060008060808587031215612d0657600080fd5b6000612d1487828801612a66565b9450506020612d2587828801612b2e565b935050604085013567ffffffffffffffff811115612d4257600080fd5b612d4e87828801612aef565b9250506060612d5f87828801612b19565b91505092959194509250565b600060208284031215612d7d57600080fd5b6000612d8b84828501612a90565b91505092915050565b600060208284031215612da657600080fd5b600082013567ffffffffffffffff811115612dc057600080fd5b612dcc84828501612aef565b91505092915050565b600060208284031215612de757600080fd5b6000612df584828501612b2e565b91505092915050565b6000612e0a8383612e25565b60208301905092915050565b612e1f81613bd0565b82525050565b612e2e81613bbe565b82525050565b612e3d81613bbe565b82525050565b612e54612e4f82613bbe565b613d10565b82525050565b6000612e6582613ad3565b612e6f8185613af6565b9350612e7a83613ac3565b8060005b83811015612eab578151612e928882612dfe565b9750612e9d83613ae9565b925050600181019050612e7e565b5085935050505092915050565b612ec181613be2565b82525050565b612ed081613bee565b82525050565b612edf81613bf8565b82525050565b6000612ef18385613b07565b9350612efe838584613c85565b612f0783613ddd565b840190509392505050565b6000612f1d82613ade565b612f278185613b07565b9350612f37818560208601613c94565b612f4081613ddd565b840191505092915050565b6000612f5682613ade565b612f608185613b18565b9350612f70818560208601613c94565b80840191505092915050565b612f8581613c61565b82525050565b612f9c612f9782613c61565b613d3e565b82525050565b612fab81613c73565b82525050565b6000612fbe601783613b23565b91507f4d6f64756c6520616c72656164792064697361626c65640000000000000000006000830152602082019050919050565b6000612ffe602683613b23565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613064601383613b23565b91507f5472616e73616374696f6e2065787069726564000000000000000000000000006000830152602082019050919050565b60006130a4601f83613b23565b91507f5472616e73616374696f6e2068617368657320646f206e6f74206d61746368006000830152602082019050919050565b60006130e4601e83613b23565b91507f5461726765742063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b6000613124602e83613b23565b91507f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008301527f647920696e697469616c697a65640000000000000000000000000000000000006020830152604082019050919050565b600061318a602d83613b23565b91507f4e6577206e6f6e6365206d75737420626520686967686572207468616e20637560008301527f7272656e742074784e6f6e6365000000000000000000000000000000000000006020830152604082019050919050565b60006131f0602083613b23565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613230602083613b23565b91507f43616e6e6f7420626520686967686572207468616e2071756575654e6f6e63656000830152602082019050919050565b6000613270602d83613b23565b91507f457870697261746974696f6e206d7573742062652030206f72206174206c656160008301527f7374203630207365636f6e6473000000000000000000000000000000000000006020830152604082019050919050565b60006132d6601e83613b23565b91507f4176617461722063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b6000613316601583613b23565b91507f4d6f64756c65206e6f7420617574686f72697a656400000000000000000000006000830152602082019050919050565b6000613356602083613b23565b91507f477561726420646f6573206e6f7420696d706c656d656e7420494552433136356000830152602082019050919050565b6000613396602083613b23565b91507f5472616e73616374696f6e206973207374696c6c20696e20636f6f6c646f776e6000830152602082019050919050565b60006133d6601683613b23565b91507f4d6f64756c6520616c726561647920656e61626c6564000000000000000000006000830152602082019050919050565b6000613416602483613b23565b91507f73657455704d6f64756c65732068617320616c7265616479206265656e20636160008301527f6c6c6564000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061347c601a83613b23565b91507f5472616e73616374696f6e20717565756520697320656d7074790000000000006000830152602082019050919050565b60006134bc600e83613b23565b91507f496e76616c6964206d6f64756c650000000000000000000000000000000000006000830152602082019050919050565b60006134fc601983613b23565b91507f4d6f64756c65207472616e73616374696f6e206661696c6564000000000000006000830152602082019050919050565b61353881613c57565b82525050565b61354f61354a82613c57565b613d34565b82525050565b60006135618287612e43565b601482019150613571828661353e565b6020820191506135818285612f4b565b915061358d8284612f8b565b60018201915081905095945050505050565b60006020820190506135b46000830184612e34565b92915050565b60006080820190506135cf6000830188612e34565b6135dc602083018761352f565b81810360408301526135ef818587612ee5565b90506135fe6060830184612f7c565b9695505050505050565b600060808201905061361d6000830187612e34565b61362a602083018661352f565b818103604083015261363c8185612f12565b905061364b6060830184612f7c565b95945050505050565b60006101608201905061366a600083018e612e34565b613677602083018d61352f565b8181036040830152613689818c612f12565b9050613698606083018b612f7c565b6136a5608083018a612fa2565b6136b260a0830189612fa2565b6136bf60c0830188612fa2565b6136cc60e0830187612e34565b6136da610100830186612e16565b8181036101208301526136ed8185612f12565b90506136fd610140830184612e34565b9c9b505050505050505050505050565b600060408201905081810360008301526137278185612e5a565b90506137366020830184612e34565b9392505050565b60006020820190506137526000830184612eb8565b92915050565b600060408201905061376d6000830185612eb8565b818103602083015261377f8184612f12565b90509392505050565b600060208201905061379d6000830184612ec7565b92915050565b60006040820190506137b86000830185612ec7565b6137c56020830184612eb8565b9392505050565b60006020820190506137e16000830184612ed6565b92915050565b6000602082019050818103600083015261380081612fb1565b9050919050565b6000602082019050818103600083015261382081612ff1565b9050919050565b6000602082019050818103600083015261384081613057565b9050919050565b6000602082019050818103600083015261386081613097565b9050919050565b60006020820190508181036000830152613880816130d7565b9050919050565b600060208201905081810360008301526138a081613117565b9050919050565b600060208201905081810360008301526138c08161317d565b9050919050565b600060208201905081810360008301526138e0816131e3565b9050919050565b6000602082019050818103600083015261390081613223565b9050919050565b6000602082019050818103600083015261392081613263565b9050919050565b60006020820190508181036000830152613940816132c9565b9050919050565b6000602082019050818103600083015261396081613309565b9050919050565b6000602082019050818103600083015261398081613349565b9050919050565b600060208201905081810360008301526139a081613389565b9050919050565b600060208201905081810360008301526139c0816133c9565b9050919050565b600060208201905081810360008301526139e081613409565b9050919050565b60006020820190508181036000830152613a008161346f565b9050919050565b60006020820190508181036000830152613a20816134af565b9050919050565b60006020820190508181036000830152613a40816134ef565b9050919050565b6000602082019050613a5c600083018461352f565b92915050565b6000604051905081810181811067ffffffffffffffff82111715613a8957613a88613dae565b5b8060405250919050565b600067ffffffffffffffff821115613aae57613aad613dae565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000613b3f82613c57565b9150613b4a83613c57565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613b7f57613b7e613d50565b5b828201905092915050565b6000613b9582613c57565b9150613ba083613c57565b925082821015613bb357613bb2613d50565b5b828203905092915050565b6000613bc982613c37565b9050919050565b6000613bdb82613c37565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050613c3282613e08565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000613c6c82613c24565b9050919050565b6000613c7e82613c57565b9050919050565b82818337600083830152505050565b60005b83811015613cb2578082015181840152602081019050613c97565b83811115613cc1576000848401525b50505050565b6000613cd282613c57565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613d0557613d04613d50565b5b600182019050919050565b6000613d1b82613d22565b9050919050565b6000613d2d82613dfb565b9050919050565b6000819050919050565b6000613d4982613dee565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160f81b9050919050565b60008160601b9050919050565b60028110613e1957613e18613d7f565b5b50565b613e2581613bbe565b8114613e3057600080fd5b50565b613e3c81613bd0565b8114613e4757600080fd5b50565b613e5381613be2565b8114613e5e57600080fd5b50565b60028110613e6e57600080fd5b50565b613e7a81613c57565b8114613e8557600080fd5b5056fea26469706673582212206f4de68ccc61e36655459f9fb9c07003c20f8e19b2a434ed1a757de2d8dc3f8e64736f6c6343000800003300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"; + "0x60806040523480156200001157600080fd5b5060405162004f4a38038062004f4a833981810160405281019062000037919062000a30565b600085858585856040516020016200005495949392919062000d57565b604051602081830303815290604052905062000076816200008260201b60201c565b50505050505062000f53565b600080600080600085806020019051810190620000a09190620009ae565b94509450945094509450620000ba6200032a60201b60201c565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156200012d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001249062000e5e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415620001a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001979062000dd6565b60405180910390fd5b6000811480620001b15750603c8110155b620001f3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001ea9062000e3c565b60405180910390fd5b83606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080606a819055508160698190555062000294856200042960201b60201c565b620002a46200053f60201b60201c565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffd805e12a6d02f83d7029c03fdfcf3f226ebcd409af51b3095237015eae50300866040516200031a919062000d3a565b60405180910390a4505050505050565b600060019054906101000a900460ff168062000351575060008054906101000a900460ff16155b62000393576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038a9062000df8565b60405180910390fd5b60008060019054906101000a900460ff161590508015620003e4576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b620003f46200069360201b60201c565b620004046200077260201b60201c565b8015620004265760008060016101000a81548160ff0219169083151502179055505b50565b620004396200087160201b60201c565b73ffffffffffffffffffffffffffffffffffffffff166200045f6200087960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620004b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004af9062000e1a565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200052b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005229062000db4565b60405180910390fd5b6200053c81620008a360201b60201c565b50565b600073ffffffffffffffffffffffffffffffffffffffff1660686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161462000611576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006089062000e80565b60405180910390fd5b600160686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600060019054906101000a900460ff1680620006ba575060008054906101000a900460ff16155b620006fc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006f39062000df8565b60405180910390fd5b60008060019054906101000a900460ff1615905080156200074d576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b80156200076f5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff168062000799575060008054906101000a900460ff16155b620007db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007d29062000df8565b60405180910390fd5b60008060019054906101000a900460ff1615905080156200082c576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6200084c620008406200087160201b60201c565b620008a360201b60201c565b80156200086e5760008060016101000a81548160ff0219169083151502179055505b50565b600033905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000815190506200097a8162000f05565b92915050565b600081519050620009918162000f1f565b92915050565b600081519050620009a88162000f39565b92915050565b600080600080600060a08688031215620009c757600080fd5b6000620009d78882890162000980565b9550506020620009ea8882890162000980565b9450506040620009fd8882890162000980565b935050606062000a108882890162000997565b925050608062000a238882890162000997565b9150509295509295909350565b600080600080600060a0868803121562000a4957600080fd5b600062000a598882890162000969565b955050602062000a6c8882890162000969565b945050604062000a7f8882890162000969565b935050606062000a928882890162000997565b925050608062000aa58882890162000997565b9150509295509295909350565b62000abd8162000eb3565b82525050565b600062000ad260268362000ea2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600062000b3a601e8362000ea2565b91507f5461726765742063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b600062000b7c602e8362000ea2565b91507f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008301527f647920696e697469616c697a65640000000000000000000000000000000000006020830152604082019050919050565b600062000be460208362000ea2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b600062000c26602d8362000ea2565b91507f457870697261746974696f6e206d7573742062652030206f72206174206c656160008301527f7374203630207365636f6e6473000000000000000000000000000000000000006020830152604082019050919050565b600062000c8e601e8362000ea2565b91507f4176617461722063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b600062000cd060248362000ea2565b91507f73657455704d6f64756c65732068617320616c7265616479206265656e20636160008301527f6c6c6564000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b62000d348162000efb565b82525050565b600060208201905062000d51600083018462000ab2565b92915050565b600060a08201905062000d6e600083018862000ab2565b62000d7d602083018762000ab2565b62000d8c604083018662000ab2565b62000d9b606083018562000d29565b62000daa608083018462000d29565b9695505050505050565b6000602082019050818103600083015262000dcf8162000ac3565b9050919050565b6000602082019050818103600083015262000df18162000b2b565b9050919050565b6000602082019050818103600083015262000e138162000b6d565b9050919050565b6000602082019050818103600083015262000e358162000bd5565b9050919050565b6000602082019050818103600083015262000e578162000c17565b9050919050565b6000602082019050818103600083015262000e798162000c7f565b9050919050565b6000602082019050818103600083015262000e9b8162000cc1565b9050919050565b600082825260208201905092915050565b600062000ec08262000edb565b9050919050565b600062000ed48262000edb565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000f108162000eb3565b811462000f1c57600080fd5b50565b62000f2a8162000ec7565b811462000f3657600080fd5b50565b62000f448162000efb565b811462000f5057600080fd5b50565b613fe78062000f636000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c80637ceab3b11161010f578063d4b83992116100a2578063e19a9dd911610071578063e19a9dd914610582578063ebb2b4a21461059e578063ee072baf146105ba578063f2fde38b146105d6576101e5565b8063d4b839921461050c578063dcafac091461052a578063de8dd91d14610548578063e009cfde14610566576101e5565b8063b19d4758116100de578063b19d475814610495578063c66323e51461049f578063c9106389146104bd578063cc2f8452146104db576101e5565b80637ceab3b1146104215780638da5cb5b1461043f5780639b56d5be1461045d578063a4f9edbf14610479576101e5565b806346ba230711610187578063610b592511610156578063610b5925146103af5780636b0a4cf6146103cb578063715018a6146103fb578063776d1a0114610405576101e5565b806346ba2307146103265780635229073f146103425780635aef7de614610373578063605df59c14610391576101e5565b8063300c661f116101c3578063300c661f146102665780633aa7690614610296578063427e232f146102c6578063468721a7146102f6576101e5565b8063086cfca8146101ea578063258148cc146102065780632d9ad53d14610236575b600080fd5b61020460048036038101906101ff9190612c4a565b6105f2565b005b610220600480360381019061021b9190612ec7565b610734565b60405161022d9190613b39565b60405180910390f35b610250600480360381019061024b9190612c4a565b61074c565b60405161025d919061382f565b60405180910390f35b610280600480360381019061027b9190612de2565b61081e565b60405161028d919061387a565b60405180910390f35b6102b060048036038101906102ab9190612ec7565b610857565b6040516102bd9190613b39565b60405180910390f35b6102e060048036038101906102db9190612ec7565b610874565b6040516102ed919061387a565b60405180910390f35b610310600480360381019061030b9190612d62565b61088c565b60405161031d919061382f565b60405180910390f35b610340600480360381019061033b9190612ec7565b610a4d565b005b61035c60048036038101906103579190612d62565b610b5c565b60405161036a92919061384a565b60405180910390f35b61037b610d49565b6040516103889190613691565b60405180910390f35b610399610d6f565b6040516103a69190613b39565b60405180910390f35b6103c960048036038101906103c49190612c4a565b610d75565b005b6103e560048036038101906103e09190612ec7565b6110ff565b6040516103f2919061387a565b60405180910390f35b61040361111c565b005b61041f600480360381019061041a9190612c4a565b6111a4565b005b6104296112e6565b6040516104369190613691565b60405180910390f35b61044761130c565b6040516104549190613691565b60405180910390f35b61047760048036038101906104729190612ec7565b611336565b005b610493600480360381019061048e9190612e86565b61140b565b005b61049d61168d565b005b6104a7611702565b6040516104b49190613b39565b60405180910390f35b6104c5611708565b6040516104d29190613691565b60405180910390f35b6104f560048036038101906104f09190612d26565b611732565b6040516105039291906137ff565b60405180910390f35b61051461197f565b6040516105219190613691565b60405180910390f35b6105326119a5565b60405161053f9190613b39565b60405180910390f35b6105506119ab565b60405161055d9190613b39565b60405180910390f35b610580600480360381019061057b9190612cea565b6119b1565b005b61059c60048036038101906105979190612c4a565b611d3a565b005b6105b860048036038101906105b39190612ec7565b611f70565b005b6105d460048036038101906105cf9190612d62565b611ff6565b005b6105f060048036038101906105eb9190612c4a565b612263565b005b6105fa61235b565b73ffffffffffffffffffffffffffffffffffffffff1661061861130c565b73ffffffffffffffffffffffffffffffffffffffff161461066e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610665906139b9565b60405180910390fd5b6000606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f52ae88b092de36f87fb43fe794eb1381023b9c1bce563a871154022c63dce34260405160405180910390a35050565b606e6020528060005260406000206000915090505481565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156108175750600073ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000848484846040516020016108379493929190613647565b604051602081830303815290604052805190602001209050949350505050565b6000606e6000838152602001908152602001600020549050919050565b606d6020528060005260406000206000915090505481565b60008073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561095c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095390613a39565b60405180910390fd5b60006109ae878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508661081e565b905080606d6000606c5481526020019081526020016000208190555042606e6000606c5481526020019081526020016000208190555080606c547f4c8a9c748e976c17c2eb2c2bc50da76eac9cd90ff529f0fe900e0c10a179f0318989898989604051610a1f9594939291906136ac565b60405180910390a3606c6000815480929190610a3a90613df0565b9190505550600191505095945050505050565b610a5561235b565b73ffffffffffffffffffffffffffffffffffffffff16610a7361130c565b73ffffffffffffffffffffffffffffffffffffffff1614610ac9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac0906139b9565b60405180910390fd5b606b548111610b0d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0490613999565b60405180910390fd5b606c54811115610b52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b49906139d9565b60405180910390fd5b80606b8190555050565b60006060600073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610c2f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2690613a39565b60405180910390fd5b6000610c81888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508761081e565b905080606d6000606c5481526020019081526020016000208190555042606e6000606c5481526020019081526020016000208190555080606c547f4c8a9c748e976c17c2eb2c2bc50da76eac9cd90ff529f0fe900e0c10a179f0318a8a8a8a8a604051610cf29594939291906136ac565b60405180910390a360019250606c548142604051602001610d1593929190613b54565b6040516020818303038152906040529150606c6000815480929190610d3990613df0565b9190505550509550959350505050565b606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606a5481565b610d7d61235b565b73ffffffffffffffffffffffffffffffffffffffff16610d9b61130c565b73ffffffffffffffffffffffffffffffffffffffff1614610df1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610de8906139b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610e5b5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b610e9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9190613af9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5f90613a99565b60405180910390fd5b60686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440816040516110f49190613691565b60405180910390a150565b6000606d6000838152602001908152602001600020549050919050565b61112461235b565b73ffffffffffffffffffffffffffffffffffffffff1661114261130c565b73ffffffffffffffffffffffffffffffffffffffff1614611198576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161118f906139b9565b60405180910390fd5b6111a26000612363565b565b6111ac61235b565b73ffffffffffffffffffffffffffffffffffffffff166111ca61130c565b73ffffffffffffffffffffffffffffffffffffffff1614611220576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611217906139b9565b60405180910390fd5b6000606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f90cc2f570a6eb594b1580ea3e41247d2d73a55281889e86bd4ec2fc29c7e62d660405160405180910390a35050565b606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61133e61235b565b73ffffffffffffffffffffffffffffffffffffffff1661135c61130c565b73ffffffffffffffffffffffffffffffffffffffff16146113b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a9906139b9565b60405180910390fd5b60008114806113c25750603c8110155b611401576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f8906139f9565b60405180910390fd5b80606a8190555050565b6000806000806000858060200190518101906114279190612c73565b94509450945094509450611439612429565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156114a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a090613a19565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611519576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151090613959565b60405180910390fd5b60008114806115295750603c8110155b611568576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155f906139f9565b60405180910390fd5b83606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080606a819055508160698190555061160185612263565b611609612512565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ffd805e12a6d02f83d7029c03fdfcf3f226ebcd409af51b3095237015eae503008660405161167d9190613691565b60405180910390a4505050505050565b5b6000606a54141580156116cf575042606a54606954606e6000606b548152602001908152602001600020546116c39190613c5d565b6116cd9190613c5d565b105b80156116de5750606c54606b54105b1561170057606b60008154809291906116f690613df0565b919050555061168e565b565b606b5481565b6000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008267ffffffffffffffff811115611776577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156117a45781602001602082028036833780820191505090505b509150600080606860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156118775750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561188257508482105b1561197057808483815181106118c1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050818061196890613df0565b92505061180d565b80925081845250509250929050565b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60695481565b606c5481565b6119b961235b565b73ffffffffffffffffffffffffffffffffffffffff166119d761130c565b73ffffffffffffffffffffffffffffffffffffffff1614611a2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a24906139b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015611a975750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b611ad6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611acd90613af9565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611ba3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b9a906138d9565b60405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427681604051611d2e9190613691565b60405180910390a15050565b611d4261235b565b73ffffffffffffffffffffffffffffffffffffffff16611d6061130c565b73ffffffffffffffffffffffffffffffffffffffff1614611db6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dad906139b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611ed3578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401611e4391906138be565b60206040518083038186803b158015611e5b57600080fd5b505afa158015611e6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e939190612e5d565b611ed2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ec990613a59565b60405180910390fd5b5b80606560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa2606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611f659190613691565b60405180910390a150565b611f7861235b565b73ffffffffffffffffffffffffffffffffffffffff16611f9661130c565b73ffffffffffffffffffffffffffffffffffffffff1614611fec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fe3906139b9565b60405180910390fd5b8060698190555050565b606c54606b541061203c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161203390613ad9565b60405180910390fd5b6000606e6000606b54815260200190815260200160002054905060695481426120659190613cb3565b10156120a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209d90613a79565b60405180910390fd5b6000606a541461210e5742606a54606954836120c29190613c5d565b6120cc9190613c5d565b101561210d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210490613919565b60405180910390fd5b5b61215e868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508561081e565b606d6000606b54815260200190815260200160002054146121b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121ab90613939565b60405180910390fd5b606b60008154809291906121c790613df0565b919050555061221c868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505085612663565b61225b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225290613b19565b60405180910390fd5b505050505050565b61226b61235b565b73ffffffffffffffffffffffffffffffffffffffff1661228961130c565b73ffffffffffffffffffffffffffffffffffffffff16146122df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122d6906139b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561234f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612346906138f9565b60405180910390fd5b61235881612363565b50565b600033905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600060019054906101000a900460ff168061244f575060008054906101000a900460ff16155b61248e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248590613979565b60405180910390fd5b60008060019054906101000a900460ff1615905080156124de576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6124e6612958565b6124ee612a31565b801561250f5760008060016101000a81548160ff0219169083151502179055505b50565b600073ffffffffffffffffffffffffffffffffffffffff1660686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125d890613ab9565b60405180910390fd5b600160686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461279557606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166375f0bb528686868660008060008060006040518060400160405280600281526020017f307800000000000000000000000000000000000000000000000000000000000081525060006040518c63ffffffff1660e01b81526004016127629b9a99989796959493929190613746565b600060405180830381600087803b15801561277c57600080fd5b505af1158015612790573d6000803e3d6000fd5b505050505b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663468721a7868686866040518563ffffffff1660e01b81526004016127f694939291906136fa565b602060405180830381600087803b15801561281057600080fd5b505af1158015612824573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128489190612e5d565b9050600073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461295057606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663932713687f3078000000000000000000000000000000000000000000000000000000000000836040518363ffffffff1660e01b815260040161291d929190613895565b600060405180830381600087803b15801561293757600080fd5b505af115801561294b573d6000803e3d6000fd5b505050505b949350505050565b600060019054906101000a900460ff168061297e575060008054906101000a900460ff16155b6129bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b490613979565b60405180910390fd5b60008060019054906101000a900460ff161590508015612a0d576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b8015612a2e5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff1680612a57575060008054906101000a900460ff16155b612a96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a8d90613979565b60405180910390fd5b60008060019054906101000a900460ff161590508015612ae6576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b612af6612af161235b565b612363565b8015612b175760008060016101000a81548160ff0219169083151502179055505b50565b6000612b2d612b2884613bbc565b613b8b565b905082815260208101848484011115612b4557600080fd5b612b50848285613dae565b509392505050565b600081359050612b6781613f45565b92915050565b600081519050612b7c81613f5c565b92915050565b600081519050612b9181613f73565b92915050565b60008083601f840112612ba957600080fd5b8235905067ffffffffffffffff811115612bc257600080fd5b602083019150836001820283011115612bda57600080fd5b9250929050565b600082601f830112612bf257600080fd5b8135612c02848260208601612b1a565b91505092915050565b600081359050612c1a81613f8a565b92915050565b600081359050612c2f81613f9a565b92915050565b600081519050612c4481613f9a565b92915050565b600060208284031215612c5c57600080fd5b6000612c6a84828501612b58565b91505092915050565b600080600080600060a08688031215612c8b57600080fd5b6000612c9988828901612b6d565b9550506020612caa88828901612b6d565b9450506040612cbb88828901612b6d565b9350506060612ccc88828901612c35565b9250506080612cdd88828901612c35565b9150509295509295909350565b60008060408385031215612cfd57600080fd5b6000612d0b85828601612b58565b9250506020612d1c85828601612b58565b9150509250929050565b60008060408385031215612d3957600080fd5b6000612d4785828601612b58565b9250506020612d5885828601612c20565b9150509250929050565b600080600080600060808688031215612d7a57600080fd5b6000612d8888828901612b58565b9550506020612d9988828901612c20565b945050604086013567ffffffffffffffff811115612db657600080fd5b612dc288828901612b97565b93509350506060612dd588828901612c0b565b9150509295509295909350565b60008060008060808587031215612df857600080fd5b6000612e0687828801612b58565b9450506020612e1787828801612c20565b935050604085013567ffffffffffffffff811115612e3457600080fd5b612e4087828801612be1565b9250506060612e5187828801612c0b565b91505092959194509250565b600060208284031215612e6f57600080fd5b6000612e7d84828501612b82565b91505092915050565b600060208284031215612e9857600080fd5b600082013567ffffffffffffffff811115612eb257600080fd5b612ebe84828501612be1565b91505092915050565b600060208284031215612ed957600080fd5b6000612ee784828501612c20565b91505092915050565b6000612efc8383612f17565b60208301905092915050565b612f1181613cf9565b82525050565b612f2081613ce7565b82525050565b612f2f81613ce7565b82525050565b612f46612f4182613ce7565b613e39565b82525050565b6000612f5782613bfc565b612f618185613c1f565b9350612f6c83613bec565b8060005b83811015612f9d578151612f848882612ef0565b9750612f8f83613c12565b925050600181019050612f70565b5085935050505092915050565b612fb381613d0b565b82525050565b612fc281613d17565b82525050565b612fd181613d21565b82525050565b6000612fe38385613c30565b9350612ff0838584613dae565b612ff983613f06565b840190509392505050565b600061300f82613c07565b6130198185613c30565b9350613029818560208601613dbd565b61303281613f06565b840191505092915050565b600061304882613c07565b6130528185613c41565b9350613062818560208601613dbd565b80840191505092915050565b61307781613d8a565b82525050565b61308e61308982613d8a565b613e67565b82525050565b61309d81613d9c565b82525050565b60006130b0601783613c4c565b91507f4d6f64756c6520616c72656164792064697361626c65640000000000000000006000830152602082019050919050565b60006130f0602683613c4c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613156601383613c4c565b91507f5472616e73616374696f6e2065787069726564000000000000000000000000006000830152602082019050919050565b6000613196601f83613c4c565b91507f5472616e73616374696f6e2068617368657320646f206e6f74206d61746368006000830152602082019050919050565b60006131d6601e83613c4c565b91507f5461726765742063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b6000613216602e83613c4c565b91507f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008301527f647920696e697469616c697a65640000000000000000000000000000000000006020830152604082019050919050565b600061327c602d83613c4c565b91507f4e6577206e6f6e6365206d75737420626520686967686572207468616e20637560008301527f7272656e742074784e6f6e6365000000000000000000000000000000000000006020830152604082019050919050565b60006132e2602083613c4c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613322602083613c4c565b91507f43616e6e6f7420626520686967686572207468616e2071756575654e6f6e63656000830152602082019050919050565b6000613362602d83613c4c565b91507f457870697261746974696f6e206d7573742062652030206f72206174206c656160008301527f7374203630207365636f6e6473000000000000000000000000000000000000006020830152604082019050919050565b60006133c8601e83613c4c565b91507f4176617461722063616e206e6f74206265207a65726f206164647265737300006000830152602082019050919050565b6000613408601583613c4c565b91507f4d6f64756c65206e6f7420617574686f72697a656400000000000000000000006000830152602082019050919050565b6000613448602083613c4c565b91507f477561726420646f6573206e6f7420696d706c656d656e7420494552433136356000830152602082019050919050565b6000613488602083613c4c565b91507f5472616e73616374696f6e206973207374696c6c20696e20636f6f6c646f776e6000830152602082019050919050565b60006134c8601683613c4c565b91507f4d6f64756c6520616c726561647920656e61626c6564000000000000000000006000830152602082019050919050565b6000613508602483613c4c565b91507f73657455704d6f64756c65732068617320616c7265616479206265656e20636160008301527f6c6c6564000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061356e601a83613c4c565b91507f5472616e73616374696f6e20717565756520697320656d7074790000000000006000830152602082019050919050565b60006135ae600e83613c4c565b91507f496e76616c6964206d6f64756c650000000000000000000000000000000000006000830152602082019050919050565b60006135ee601983613c4c565b91507f4d6f64756c65207472616e73616374696f6e206661696c6564000000000000006000830152602082019050919050565b61362a81613d80565b82525050565b61364161363c82613d80565b613e5d565b82525050565b60006136538287612f35565b6014820191506136638286613630565b602082019150613673828561303d565b915061367f828461307d565b60018201915081905095945050505050565b60006020820190506136a66000830184612f26565b92915050565b60006080820190506136c16000830188612f26565b6136ce6020830187613621565b81810360408301526136e1818587612fd7565b90506136f0606083018461306e565b9695505050505050565b600060808201905061370f6000830187612f26565b61371c6020830186613621565b818103604083015261372e8185613004565b905061373d606083018461306e565b95945050505050565b60006101608201905061375c600083018e612f26565b613769602083018d613621565b818103604083015261377b818c613004565b905061378a606083018b61306e565b613797608083018a613094565b6137a460a0830189613094565b6137b160c0830188613094565b6137be60e0830187612f26565b6137cc610100830186612f08565b8181036101208301526137df8185613004565b90506137ef610140830184612f26565b9c9b505050505050505050505050565b600060408201905081810360008301526138198185612f4c565b90506138286020830184612f26565b9392505050565b60006020820190506138446000830184612faa565b92915050565b600060408201905061385f6000830185612faa565b81810360208301526138718184613004565b90509392505050565b600060208201905061388f6000830184612fb9565b92915050565b60006040820190506138aa6000830185612fb9565b6138b76020830184612faa565b9392505050565b60006020820190506138d36000830184612fc8565b92915050565b600060208201905081810360008301526138f2816130a3565b9050919050565b60006020820190508181036000830152613912816130e3565b9050919050565b6000602082019050818103600083015261393281613149565b9050919050565b6000602082019050818103600083015261395281613189565b9050919050565b60006020820190508181036000830152613972816131c9565b9050919050565b6000602082019050818103600083015261399281613209565b9050919050565b600060208201905081810360008301526139b28161326f565b9050919050565b600060208201905081810360008301526139d2816132d5565b9050919050565b600060208201905081810360008301526139f281613315565b9050919050565b60006020820190508181036000830152613a1281613355565b9050919050565b60006020820190508181036000830152613a32816133bb565b9050919050565b60006020820190508181036000830152613a52816133fb565b9050919050565b60006020820190508181036000830152613a728161343b565b9050919050565b60006020820190508181036000830152613a928161347b565b9050919050565b60006020820190508181036000830152613ab2816134bb565b9050919050565b60006020820190508181036000830152613ad2816134fb565b9050919050565b60006020820190508181036000830152613af281613561565b9050919050565b60006020820190508181036000830152613b12816135a1565b9050919050565b60006020820190508181036000830152613b32816135e1565b9050919050565b6000602082019050613b4e6000830184613621565b92915050565b6000606082019050613b696000830186613621565b613b766020830185612fb9565b613b836040830184613621565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715613bb257613bb1613ed7565b5b8060405250919050565b600067ffffffffffffffff821115613bd757613bd6613ed7565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000613c6882613d80565b9150613c7383613d80565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613ca857613ca7613e79565b5b828201905092915050565b6000613cbe82613d80565b9150613cc983613d80565b925082821015613cdc57613cdb613e79565b5b828203905092915050565b6000613cf282613d60565b9050919050565b6000613d0482613d60565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050613d5b82613f31565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000613d9582613d4d565b9050919050565b6000613da782613d80565b9050919050565b82818337600083830152505050565b60005b83811015613ddb578082015181840152602081019050613dc0565b83811115613dea576000848401525b50505050565b6000613dfb82613d80565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e2e57613e2d613e79565b5b600182019050919050565b6000613e4482613e4b565b9050919050565b6000613e5682613f24565b9050919050565b6000819050919050565b6000613e7282613f17565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160f81b9050919050565b60008160601b9050919050565b60028110613f4257613f41613ea8565b5b50565b613f4e81613ce7565b8114613f5957600080fd5b50565b613f6581613cf9565b8114613f7057600080fd5b50565b613f7c81613d0b565b8114613f8757600080fd5b50565b60028110613f9757600080fd5b50565b613fa381613d80565b8114613fae57600080fd5b5056fea26469706673582212208b3a304c932203e860004264f50bdb0a6590ff171440793f5990e271f0f91f9c64736f6c6343000800003300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; From 173e8decce39b0ecf492fef208ef2195a379ac6f Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sun, 24 Sep 2023 01:46:34 +0200 Subject: [PATCH 02/82] Bump package.json version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a5ce9c76..a607b2a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.3.7", + "version": "3.3.8", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", From 897cf55d0a30ba03f273302caabd44ce96342c57 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Tue, 26 Sep 2023 16:57:09 +0200 Subject: [PATCH 03/82] Update Delay Mastercopy --- sdk/contracts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/contracts.ts b/sdk/contracts.ts index 9e5e5b2e..b61e4154 100644 --- a/sdk/contracts.ts +++ b/sdk/contracts.ts @@ -83,7 +83,7 @@ const CanonicalAddresses: Record< "1.0.0": "0x03B5eBD2CB2e3339E93774A1Eb7c8634B8C393A9", }, [KnownContracts.DELAY]: { - "1.0.0": "0xD62129BF40CD1694b3d9D9847367783a1A4d5cB4", + "1.0.0": "0xd54895B1121A2eE3f37b502F507631FA1331BED6", }, [KnownContracts.FACTORY]: { "1.0.0": "0x00000000062c52e29e8029dc2413172f6d619d85", From 9af544390c309adcea23aa443b2f7cf7fe67be47 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Tue, 26 Sep 2023 17:00:19 +0200 Subject: [PATCH 04/82] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a607b2a3..7a001a59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.3.8", + "version": "3.3.9", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", From 7e91e8c1b32e823a22ead36f75c1d10b4f7c8bd3 Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Fri, 29 Sep 2023 12:28:36 +0200 Subject: [PATCH 05/82] Revert "Merge pull request #126 from gnosis/add-roles-v2" This reverts commit 8a7704bfc2c767dbdbb46175ad7bc7fd802b0bb2, reversing changes made to deeda0418a9a166db165dabd5c05f5c08f7c2515. --- .prettierrc | 4 - sdk/abi/Integrity.json | 113 ------ sdk/abi/Packer.json | 43 --- sdk/abi/Roles.json | 791 +++++++++++--------------------------- sdk/contracts.ts | 17 - sdk/factory/types.ts | 2 - sdk/initData/Integrity.ts | 4 - sdk/initData/Packer.ts | 4 - sdk/initData/Roles.ts | 2 +- 9 files changed, 221 insertions(+), 759 deletions(-) delete mode 100644 .prettierrc delete mode 100644 sdk/abi/Integrity.json delete mode 100644 sdk/abi/Packer.json delete mode 100644 sdk/initData/Integrity.ts delete mode 100644 sdk/initData/Packer.ts diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 1fca6c54..00000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "trailingComma": "es5", - "semi": true -} diff --git a/sdk/abi/Integrity.json b/sdk/abi/Integrity.json deleted file mode 100644 index 10a82957..00000000 --- a/sdk/abi/Integrity.json +++ /dev/null @@ -1,113 +0,0 @@ -[ - { - "inputs": [], - "name": "NotBFS", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "UnsuitableChildCount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "UnsuitableChildTypeTree", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "UnsuitableCompValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "UnsuitableParameterType", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "UnsuitableParent", - "type": "error" - }, - { - "inputs": [], - "name": "UnsuitableRootNode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "UnsupportedOperator", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint8", - "name": "parent", - "type": "uint8" - }, - { - "internalType": "enum ParameterType", - "name": "paramType", - "type": "ParameterType" - }, - { - "internalType": "enum Operator", - "name": "operator", - "type": "Operator" - }, - { - "internalType": "bytes", - "name": "compValue", - "type": "bytes" - } - ], - "internalType": "struct ConditionFlat[]", - "name": "conditions", - "type": "tuple[]" - } - ], - "name": "enforce", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/sdk/abi/Packer.json b/sdk/abi/Packer.json deleted file mode 100644 index 4f9fa5ae..00000000 --- a/sdk/abi/Packer.json +++ /dev/null @@ -1,43 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint8", - "name": "parent", - "type": "uint8" - }, - { - "internalType": "enum ParameterType", - "name": "paramType", - "type": "ParameterType" - }, - { - "internalType": "enum Operator", - "name": "operator", - "type": "Operator" - }, - { - "internalType": "bytes", - "name": "compValue", - "type": "bytes" - } - ], - "internalType": "struct ConditionFlat[]", - "name": "conditionsFlat", - "type": "tuple[]" - } - ], - "name": "pack", - "outputs": [ - { - "internalType": "bytes", - "name": "buffer", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/sdk/abi/Roles.json b/sdk/abi/Roles.json index a44b9184..475a7710 100644 --- a/sdk/abi/Roles.json +++ b/sdk/abi/Roles.json @@ -20,75 +20,11 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [ - { - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "AlreadyDisabledModule", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "AlreadyEnabledModule", - "type": "error" - }, { "inputs": [], "name": "ArraysDifferentLength", "type": "error" }, - { - "inputs": [], - "name": "CalldataOutOfBounds", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "enum PermissionChecker.Status", - "name": "status", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "info", - "type": "bytes32" - } - ], - "name": "ConditionViolation", - "type": "error" - }, - { - "inputs": [], - "name": "FunctionSignatureTooShort", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "InvalidModule", - "type": "error" - }, - { - "inputs": [], - "name": "MalformedMultiEntrypoint", - "type": "error" - }, { "inputs": [], "name": "ModuleTransactionFailed", @@ -99,94 +35,11 @@ "name": "NoMembership", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "NotAuthorized", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "guard_", - "type": "address" - } - ], - "name": "NotIERC165Compliant", - "type": "error" - }, { "inputs": [], - "name": "SetupModulesAlreadyCalled", + "name": "SetUpModulesAlreadyCalled", "type": "error" }, - { - "inputs": [], - "name": "UnsuitableMaxBalanceForAllowance", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "targetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - }, - { - "indexed": false, - "internalType": "enum ExecutionOptions", - "name": "options", - "type": "uint8" - } - ], - "name": "AllowFunction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "targetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum ExecutionOptions", - "name": "options", - "type": "uint8" - } - ], - "name": "AllowTarget", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -198,9 +51,9 @@ }, { "indexed": false, - "internalType": "bytes32[]", - "name": "roleKeys", - "type": "bytes32[]" + "internalType": "uint16[]", + "name": "roles", + "type": "uint16[]" }, { "indexed": false, @@ -244,31 +97,6 @@ "name": "ChangedGuard", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "allowanceKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint128", - "name": "consumed", - "type": "uint128" - }, - { - "indexed": false, - "internalType": "uint128", - "name": "newBalance", - "type": "uint128" - } - ], - "name": "ConsumeAllowance", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -295,45 +123,6 @@ "name": "EnabledModule", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "ExecutionFromModuleFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "module", - "type": "address" - } - ], - "name": "ExecutionFromModuleSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -353,50 +142,6 @@ "name": "OwnershipTransferred", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "targetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - } - ], - "name": "RevokeFunction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "RevokeTarget", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -428,127 +173,6 @@ "name": "RolesModSetup", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "targetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "parent", - "type": "uint8" - }, - { - "internalType": "enum ParameterType", - "name": "paramType", - "type": "uint8" - }, - { - "internalType": "enum Operator", - "name": "operator", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "compValue", - "type": "bytes" - } - ], - "indexed": false, - "internalType": "struct ConditionFlat[]", - "name": "conditions", - "type": "tuple[]" - }, - { - "indexed": false, - "internalType": "enum ExecutionOptions", - "name": "options", - "type": "uint8" - } - ], - "name": "ScopeFunction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "ScopeTarget", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "allowanceKey", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint128", - "name": "balance", - "type": "uint128" - }, - { - "indexed": false, - "internalType": "uint128", - "name": "maxBalance", - "type": "uint128" - }, - { - "indexed": false, - "internalType": "uint128", - "name": "refillAmount", - "type": "uint128" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "refillInterval", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "refillTimestamp", - "type": "uint64" - } - ], - "name": "SetAllowance", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -560,9 +184,9 @@ }, { "indexed": false, - "internalType": "bytes32", - "name": "defaultRoleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "defaultRole", + "type": "uint16" } ], "name": "SetDefaultRole", @@ -574,23 +198,11 @@ { "indexed": false, "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - }, - { - "indexed": false, - "internalType": "contract ITransactionUnwrapper", - "name": "adapter", + "name": "multisendAddress", "type": "address" } ], - "name": "SetUnwrapAdapter", + "name": "SetMultisendAddress", "type": "event" }, { @@ -615,37 +227,9 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - }, - { - "internalType": "enum ExecutionOptions", - "name": "options", - "type": "uint8" - } - ], - "name": "allowFunction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "address", @@ -663,45 +247,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "allowances", - "outputs": [ - { - "internalType": "uint128", - "name": "refillAmount", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "maxBalance", - "type": "uint128" - }, - { - "internalType": "uint64", - "name": "refillInterval", - "type": "uint64" - }, - { - "internalType": "uint128", - "name": "balance", - "type": "uint128" - }, - { - "internalType": "uint64", - "name": "refillTimestamp", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -710,9 +255,9 @@ "type": "address" }, { - "internalType": "bytes32[]", - "name": "roleKeys", - "type": "bytes32[]" + "internalType": "uint16[]", + "name": "_roles", + "type": "uint16[]" }, { "internalType": "bool[]", @@ -749,9 +294,9 @@ "name": "defaultRoles", "outputs": [ { - "internalType": "bytes32", + "internalType": "uint16", "name": "", - "type": "bytes32" + "type": "uint16" } ], "stateMutability": "view", @@ -849,12 +394,12 @@ "outputs": [ { "internalType": "bool", - "name": "success", + "name": "", "type": "bool" }, { "internalType": "bytes", - "name": "returnData", + "name": "", "type": "bytes" } ], @@ -884,9 +429,9 @@ "type": "uint8" }, { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "bool", @@ -928,9 +473,9 @@ "type": "uint8" }, { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "bool", @@ -1028,6 +573,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "multisend", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "owner", @@ -1051,9 +609,27 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "revokeTarget", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "address", @@ -1062,11 +638,16 @@ }, { "internalType": "bytes4", - "name": "selector", + "name": "functionSig", "type": "bytes4" + }, + { + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" } ], - "name": "revokeFunction", + "name": "scopeAllowFunction", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1074,17 +655,47 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "address", "name": "targetAddress", "type": "address" + }, + { + "internalType": "bytes4", + "name": "functionSig", + "type": "bytes4" + }, + { + "internalType": "bool[]", + "name": "isParamScoped", + "type": "bool[]" + }, + { + "internalType": "enum ParameterType[]", + "name": "paramType", + "type": "uint8[]" + }, + { + "internalType": "enum Comparison[]", + "name": "paramComp", + "type": "uint8[]" + }, + { + "internalType": "bytes[]", + "name": "compValue", + "type": "bytes[]" + }, + { + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" } ], - "name": "revokeTarget", + "name": "scopeFunction", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1092,9 +703,9 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "address", @@ -1103,43 +714,16 @@ }, { "internalType": "bytes4", - "name": "selector", + "name": "functionSig", "type": "bytes4" }, - { - "components": [ - { - "internalType": "uint8", - "name": "parent", - "type": "uint8" - }, - { - "internalType": "enum ParameterType", - "name": "paramType", - "type": "uint8" - }, - { - "internalType": "enum Operator", - "name": "operator", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "compValue", - "type": "bytes" - } - ], - "internalType": "struct ConditionFlat[]", - "name": "conditions", - "type": "tuple[]" - }, { "internalType": "enum ExecutionOptions", "name": "options", "type": "uint8" } ], - "name": "scopeFunction", + "name": "scopeFunctionExecutionOptions", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1147,17 +731,42 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { "internalType": "address", "name": "targetAddress", "type": "address" + }, + { + "internalType": "bytes4", + "name": "functionSig", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "paramIndex", + "type": "uint256" + }, + { + "internalType": "enum ParameterType", + "name": "paramType", + "type": "uint8" + }, + { + "internalType": "enum Comparison", + "name": "paramComp", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "compValue", + "type": "bytes" } ], - "name": "scopeTarget", + "name": "scopeParameter", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1165,37 +774,78 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" }, { - "internalType": "uint128", - "name": "balance", - "type": "uint128" + "internalType": "address", + "name": "targetAddress", + "type": "address" }, { - "internalType": "uint128", - "name": "maxBalance", - "type": "uint128" + "internalType": "bytes4", + "name": "functionSig", + "type": "bytes4" }, { - "internalType": "uint128", - "name": "refillAmount", - "type": "uint128" + "internalType": "uint256", + "name": "paramIndex", + "type": "uint256" }, { - "internalType": "uint64", - "name": "refillInterval", - "type": "uint64" + "internalType": "enum ParameterType", + "name": "paramType", + "type": "uint8" }, { - "internalType": "uint64", - "name": "refillTimestamp", - "type": "uint64" + "internalType": "bytes[]", + "name": "compValues", + "type": "bytes[]" } ], - "name": "setAllowance", + "name": "scopeParameterAsOneOf", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "role", + "type": "uint16" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "functionSig", + "type": "bytes4" + } + ], + "name": "scopeRevokeFunction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "role", + "type": "uint16" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "scopeTarget", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1221,9 +871,9 @@ "type": "address" }, { - "internalType": "bytes32", - "name": "roleKey", - "type": "bytes32" + "internalType": "uint16", + "name": "role", + "type": "uint16" } ], "name": "setDefaultRole", @@ -1248,11 +898,11 @@ "inputs": [ { "internalType": "address", - "name": "_target", + "name": "_multisend", "type": "address" } ], - "name": "setTarget", + "name": "setMultisend", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1261,21 +911,11 @@ "inputs": [ { "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "selector", - "type": "bytes4" - }, - { - "internalType": "contract ITransactionUnwrapper", - "name": "adapter", + "name": "_target", "type": "address" } ], - "name": "setTransactionUnwrapper", + "name": "setTarget", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1322,20 +962,29 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "unwrappers", - "outputs": [ + "internalType": "uint16", + "name": "role", + "type": "uint16" + }, { - "internalType": "contract ITransactionUnwrapper", - "name": "", + "internalType": "address", + "name": "targetAddress", "type": "address" + }, + { + "internalType": "bytes4", + "name": "functionSig", + "type": "bytes4" + }, + { + "internalType": "uint8", + "name": "paramIndex", + "type": "uint8" } ], - "stateMutability": "view", + "name": "unscopeParameter", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" } ] diff --git a/sdk/contracts.ts b/sdk/contracts.ts index b61e4154..53a44019 100644 --- a/sdk/contracts.ts +++ b/sdk/contracts.ts @@ -7,13 +7,11 @@ import Erc20VotesAbi from "./abi/Erc20Votes.json"; import Erc721VotesAbi from "./abi/Erc721Votes.json"; import ExitErc20Abi from "./abi/ExitErc20.json"; import ExitErc721Abi from "./abi/ExitErc721.json"; -import IntegrityAbi from "./abi/Integrity.json"; import MetaGuardAbi from "./abi/MetaGuard.json"; import ModuleProxyFactoryAbi from "./abi/ModuleProxyFactory.json"; import MultisendEncoderAbi from "./abi/MultisendEncoder.json"; import OptimisticGovernorAbi from "./abi/OptimisticGovernor.json"; import OzGovernorAbi from "./abi/OzGovernor.json"; -import PackerAbi from "./abi/Packer.json"; import PermissionsAbi from "./abi/Permissions.json"; import RealityErc20Abi from "./abi/RealityErc20.json"; import RealityEthAbi from "./abi/RealityEth.json"; @@ -32,11 +30,9 @@ import * as Erc20VotesInitData from "./initData/Erc20Votes"; import * as Erc721VotesInitData from "./initData/Erc721Votes"; import * as ExitErc20InitData from "./initData/ExitErc20"; import * as ExitErc721InitData from "./initData/ExitErc721"; -import * as IntegrityInitData from "./initData/Integrity"; import * as ModuleProxyFactoryInitData from "./initData/ModuleProxyFactory"; import * as MultisendEncoderInitData from "./initData/MultisendEncoder"; import * as OzGovernorInitData from "./initData/OzGovernor"; -import * as PackerInitData from "./initData/Packer"; import * as PermissionsInitData from "./initData/Permissions"; import * as RealityErc20InitData from "./initData/RealityErc20"; import * as RealityEthInitData from "./initData/RealityEth"; @@ -114,7 +110,6 @@ const CanonicalAddresses: Record< [KnownContracts.ROLES]: { "1.0.0": "0x85388a8cd772b19a468F982Dc264C238856939C9", "1.1.0": "0xD8DfC1d938D7D163C5231688341e9635E9011889", - "2.0.0": "0xb8bB41FA7E5e64452DBCA1C8A0e7058D43abAf4f", }, [KnownContracts.PERMISSIONS]: { "1.0.0": "0x33D1C5A5B6a7f3885c7467e829aaa21698937597", @@ -140,12 +135,6 @@ const CanonicalAddresses: Record< [KnownContracts.CONNEXT]: { "1.0.0": "0x7dE07b9De0bf0FABf31A188DE1527034b2aF36dB", }, - [KnownContracts.PACKER]: { - "2.0.0": "0x60E89c71882e88f16772490d2f05819d9521EAb1", - }, - [KnownContracts.INTEGRITY]: { - "2.0.0": "0x52c342e002C5F7CF14Ef89b5e04Cf6D53c7F8e72", - }, }; /** @@ -255,8 +244,6 @@ export const ContractAbis: Record = { [KnownContracts.MULTISEND_ENCODER]: MultisendEncoderAbi, [KnownContracts.PERMISSIONS]: PermissionsAbi, [KnownContracts.CONNEXT]: ConnextAbi, - [KnownContracts.PACKER]: PackerAbi, - [KnownContracts.INTEGRITY]: IntegrityAbi, }; export const ContractFactories = { @@ -282,8 +269,6 @@ export const ContractFactories = { [KnownContracts.MULTISEND_ENCODER]: factories.MultisendEncoder__factory, [KnownContracts.PERMISSIONS]: factories.Permissions__factory, [KnownContracts.CONNEXT]: factories.Connext__factory, - [KnownContracts.PACKER]: factories.Packer__factory, - [KnownContracts.INTEGRITY]: factories.Integrity__factory, }; export const MasterCopyInitData: Record< @@ -310,6 +295,4 @@ export const MasterCopyInitData: Record< [KnownContracts.MULTISEND_ENCODER]: MultisendEncoderInitData, [KnownContracts.PERMISSIONS]: PermissionsInitData, [KnownContracts.CONNEXT]: ConnextInitData, - [KnownContracts.PACKER]: PackerInitData, - [KnownContracts.INTEGRITY]: IntegrityInitData, }; diff --git a/sdk/factory/types.ts b/sdk/factory/types.ts index d51ec200..863f5f2c 100644 --- a/sdk/factory/types.ts +++ b/sdk/factory/types.ts @@ -41,8 +41,6 @@ export enum KnownContracts { MULTISEND_ENCODER = "multisendEncoder", PERMISSIONS = "permissions", CONNEXT = "connext", - PACKER = "packer", - INTEGRITY = "integrity", } // type META_GUARD_VERSION = "v1.0.0"; diff --git a/sdk/initData/Integrity.ts b/sdk/initData/Integrity.ts deleted file mode 100644 index b8efe9d2..00000000 --- a/sdk/initData/Integrity.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const salt = - "0x0000000000000000000000000000000000000000000000000000000000000000"; -export const initCode = - "0x61158261003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063783a90471461003a575b600080fd5b61004d6100483660046112e9565b61004f565b005b610058816100a4565b60005b81518110156100975761008782828151811061007957610079611425565b602002602001015182610149565b61009081611451565b905061005b565b506100a181610668565b50565b6000805b82518110156100f457808382815181106100c4576100c4611425565b60200260200101516000015160ff16036100e4576100e182611451565b91505b6100ed81611451565b90506100a8565b5080600114158061012757508160008151811061011357610113611425565b60200260200101516000015160ff16600014155b1561014557604051632f48858160e21b815260040160405180910390fd5b5050565b604082015160208301516060840151600083601f81111561016c5761016c61146a565b036101a2576060850151511561019d57604051632d6ee65d60e21b8152600481018590526024015b60405180910390fd5b610661565b600183601f8111156101b6576101b661146a565b101580156101d65750600383601f8111156101d3576101d361146a565b11155b156102375760008260058111156101ef576101ef61146a565b146102105760405163de10075b60e01b815260048101859052602401610194565b6060850151511561019d57604051632d6ee65d60e21b815260048101859052602401610194565b600583601f81111561024b5761024b61146a565b036102e65760038260058111156102645761026461146a565b14158015610284575060048260058111156102815761028161146a565b14155b80156102a25750600582600581111561029f5761029f61146a565b14155b156102c35760405163de10075b60e01b815260048101859052602401610194565b80511561019d57604051632d6ee65d60e21b815260048101859052602401610194565b600683601f8111156102fa576102fa61146a565b14806103175750600783601f8111156103155761031561146a565b145b806103335750600883601f8111156103315761033161146a565b145b1561036e5760045b82600581111561034d5761034d61146a565b146102c35760405163de10075b60e01b815260048101859052602401610194565b600f83601f8111156103825761038261146a565b0361038e57600161033b565b601083601f8111156103a2576103a261146a565b036104735760018260058111156103bb576103bb61146a565b141580156103db575060028260058111156103d8576103d861146a565b14155b80156103f9575060038260058111156103f6576103f661146a565b14155b8015610417575060048260058111156104145761041461146a565b14155b156104385760405163de10075b60e01b815260048101859052602401610194565b8051158061045257506020815161044f9190611480565b15155b1561019d57604051632d6ee65d60e21b815260048101859052602401610194565b601183601f8111156104875761048761146a565b14806104a45750601283601f8111156104a2576104a261146a565b145b806104c05750601383601f8111156104be576104be61146a565b145b806104dc5750601483601f8111156104da576104da61146a565b145b1561053c5760015b8260058111156104f6576104f661146a565b146105175760405163de10075b60e01b815260048101859052602401610194565b805160201461019d57604051632d6ee65d60e21b815260048101859052602401610194565b601583601f8111156105505761055061146a565b036105aa5760018260058111156105695761056961146a565b14158015610589575060028260058111156105865761058661146a565b14155b156105175760405163de10075b60e01b815260048101859052602401610194565b601683601f8111156105be576105be61146a565b036105e857805160201461019d57604051632d6ee65d60e21b815260048101859052602401610194565b601c83601f8111156105fc576105fc61146a565b036106085760016104e4565b601d83601f81111561061c5761061c61146a565b14806106395750601e83601f8111156106375761063761146a565b145b156106455760006104e4565b604051630a7d7b8960e41b815260048101859052602401610194565b5050505050565b805160015b818110156106f25782818151811061068757610687611425565b60200260200101516000015160ff16836001836106a491906114a2565b815181106106b4576106b4611425565b60200260200101516000015160ff1611156106e257604051638484738160e01b815260040160405180910390fd5b6106eb81611451565b905061066d565b5060005b818110156107f557601d83828151811061071257610712611425565b602002602001015160400151601f81111561072f5761072f61146a565b14806107695750601e83828151811061074a5761074a611425565b602002602001015160400151601f8111156107675761076761146a565b145b80156107c4575060058384838151811061078557610785611425565b60200260200101516000015160ff16815181106107a4576107a4611425565b60200260200101516020015160058111156107c1576107c161146a565b14155b156107e557604051631d40413960e11b815260048101829052602401610194565b6107ee81611451565b90506106f6565b50600061080183610c60565b905060005b8351811015610b3257600084828151811061082357610823611425565b60200260200101519050600083838151811061084157610841611425565b602002602001015190506000600581111561085e5761085e61146a565b826020015160058111156108745761087461146a565b0361095057601d8260400151601f8111156108915761089161146a565b14806108b25750601e8260400151601f8111156108b0576108b061146a565b145b80156108c15750604081015115155b156108e25760405163f3379ddd60e01b815260048101849052602401610194565b60018260400151601f8111156108fa576108fa61146a565b1015801561091e575060038260400151601f81111561091b5761091b61146a565b11155b1561094b57806040015160000361094b5760405163f3379ddd60e01b815260048101849052602401610194565b610b1d565b6001826020015160058111156109685761096861146a565b148061098957506002826020015160058111156109875761098761146a565b145b156109b45760408101511561094b5760405163f3379ddd60e01b815260048101849052602401610194565b6003826020015160058111156109cc576109cc61146a565b14806109ed57506005826020015160058111156109eb576109eb61146a565b145b15610a1a57806040015160000361094b5760405163f3379ddd60e01b815260048101849052602401610194565b600482602001516005811115610a3257610a3261146a565b14610a3f57610a3f6114bb565b8060400151600003610a675760405163f3379ddd60e01b815260048101849052602401610194565b60068260400151601f811115610a7f57610a7f61146a565b1480610aa0575060078260400151601f811115610a9e57610a9e61146a565b145b8015610ab157508060400151600114155b15610ad25760405163f3379ddd60e01b815260048101849052602401610194565b60088260400151601f811115610aea57610aea61146a565b148015610afc57506101008160400151115b15610b1d5760405163f3379ddd60e01b815260048101849052602401610194565b50508080610b2a90611451565b915050610806565b5060005b8351811015610c16576000848281518110610b5357610b53611425565b602002602001015190506001601f811115610b7057610b7061146a565b8160400151601f811115610b8657610b8661146a565b10158015610baa575060038160400151601f811115610ba757610ba761146a565b11155b80610bca5750600481602001516005811115610bc857610bc861146a565b145b8015610bf357506001838381518110610be557610be5611425565b602002602001015160400151115b15610c0357610c03858385610db5565b5080610c0e81611451565b915050610b36565b506000610c2584600084610e71565b9050600581516005811115610c3c57610c3c61146a565b14610c5a57604051632f48858160e21b815260040160405180910390fd5b50505050565b805160609080610c7257610c726114bb565b806001600160401b03811115610c8a57610c8a6111f8565b604051908082528060200260200182016040528015610cdf57816020015b610ccc60405180606001604052806000815260200160008152602001600081525090565b815260200190600190039081610ca85790505b50915060001982600081518110610cf857610cf8611425565b60209081029190910101515260015b81811015610dae57600019838281518110610d2457610d24611425565b60200260200101516000018181525050600083858381518110610d4957610d49611425565b60200260200101516000015160ff1681518110610d6857610d68611425565b60200260200101519050600019816000015103610d83578181525b610d8e8260016114d1565b602082018190528151610da0916114a2565b604090910152600101610d07565b5050919050565b6000818381518110610dc957610dc9611425565b60200260200101516000015190506000828481518110610deb57610deb611425565b60200260200101516020015190506000610e0e610e09878587610e71565b6110f9565b90506000610e1d8460016114d1565b90505b82811015610e6857610e36610e09888388610e71565b8214610e58576040516303a3183b60e61b815260048101879052602401610194565b610e6181611451565b9050610e20565b50505050505050565b6040805180820190915260008152606060208201526000848481518110610e9a57610e9a611425565b602002602001015190506001601f811115610eb757610eb761146a565b8160400151601f811115610ecd57610ecd61146a565b10158015610ef1575060038160400151601f811115610eee57610eee61146a565b11155b15610f53576000838581518110610f0a57610f0a611425565b60200260200101516040015111610f2357610f236114bb565b610f4b85848681518110610f3957610f39611425565b60200260200101516000015185610e71565b9150506110f2565b602081015182906005811115610f6b57610f6b61146a565b90816005811115610f7e57610f7e61146a565b815250506000838581518110610f9657610f96611425565b60200260200101516040015111156110f0576000838581518110610fbc57610fbc611425565b60209081029190910101515190506000600483602001516005811115610fe457610fe461146a565b1461100c57848681518110610ffb57610ffb611425565b602002602001015160200151611036565b84868151811061101e5761101e611425565b602002602001015160000151600161103691906114d1565b905061104282826114a2565b6001600160401b03811115611059576110596111f8565b60405190808252806020026020018201604052801561109f57816020015b6040805180820190915260008152606060208201528152602001906001900390816110775790505b506020850152815b818110156110ec576110ba888288610e71565b60208601516110c985846114a2565b815181106110d9576110d9611425565b60209081029190910101526001016110a7565b5050505b505b9392505050565b60208101515160009080156111e55760008360200151516001600160401b03811115611127576111276111f8565b604051908082528060200260200182016040528015611150578160200160208202803683370190505b50905060005b828110156111b1576111848560200151828151811061117757611177611425565b60200260200101516110f9565b82828151811061119657611196611425565b60209081029190910101526111aa81611451565b9050611156565b5083516040516111c6919083906020016114e4565b6040516020818303038152906040528051906020012092505050919050565b825160058111156110f2576110f261146a565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715611230576112306111f8565b60405290565b604051601f8201601f191681016001600160401b038111828210171561125e5761125e6111f8565b604052919050565b80356020811061127557600080fd5b919050565b600082601f83011261128b57600080fd5b81356001600160401b038111156112a4576112a46111f8565b6112b7601f8201601f1916602001611236565b8181528460208386010111156112cc57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156112fc57600080fd5b82356001600160401b038082111561131357600080fd5b818501915085601f83011261132757600080fd5b813581811115611339576113396111f8565b8060051b611348858201611236565b918252838101850191858101908984111561136257600080fd5b86860192505b83831015611418578235858111156113805760008081fd5b86016080818c03601f19018113156113985760008081fd5b6113a061120e565b8983013560ff811681146113b45760008081fd5b8152604083810135600681106113ca5760008081fd5b828c015260606113db858201611266565b838301529284013592898411156113f457600091508182fd5b6114028f8d8688010161127a565b9083015250845250509186019190860190611368565b9998505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016114635761146361143b565b5060010190565b634e487b7160e01b600052602160045260246000fd5b60008261149d57634e487b7160e01b600052601260045260246000fd5b500690565b818103818111156114b5576114b561143b565b92915050565b634e487b7160e01b600052600160045260246000fd5b808201808211156114b5576114b561143b565b60006006841061150457634e487b7160e01b600052602160045260246000fd5b8360f81b82526001602d60f81b81840152600283018451602080870160005b8381101561153e578151855293820193908201908501611523565b50929897505050505050505056fea26469706673582212205e423fe1cd2426ef0d204ceda9a655789cef527fab3317eedbc793021f419fef64736f6c63430008110033"; diff --git a/sdk/initData/Packer.ts b/sdk/initData/Packer.ts deleted file mode 100644 index f487bd26..00000000 --- a/sdk/initData/Packer.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const salt = - "0x0000000000000000000000000000000000000000000000000000000000000000"; -export const initCode = - "0x61086d61003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063806362d21461003a575b600080fd5b61004d610048366004610600565b610063565b60405161005a919061073d565b60405180910390f35b606061006e82610188565b6100778261024d565b67ffffffffffffffff81111561008f5761008f61050c565b6040519080825280601f01601f1916602001820160405280156100b9576020820181803683370190505b50825190915060006100cc8260026107a1565b6100d79060206107b8565b905060005b828110156101805761010884828784815181106100fb576100fb6107cb565b60200260200101516102c5565b601085828151811061011c5761011c6107cb565b602002602001015160400151601f811115610139576101396107e1565b10610170576101628483878481518110610155576101556107cb565b6020026020010151610375565b61016d6020836107b8565b91505b610179816107f7565b90506100dc565b505050919050565b805160005b818110156102485760108382815181106101a9576101a96107cb565b602002602001015160400151601f8111156101c6576101c66107e1565b1480156101da57506101d883826103c0565b155b156102385760008382815181106101f3576101f36107cb565b602002602001015160600151905060008151905060208201915060208103825281858481518110610226576102266107cb565b60200260200101516060018190525050505b610241816107f7565b905061018d565b505050565b805160009061025d6002826107a1565b915060005b818110156102be57601084828151811061027e5761027e6107cb565b602002602001015160400151601f81111561029b5761029b6107e1565b106102ae576102ab6020846107b8565b92505b6102b7816107f7565b9050610262565b5050919050565b60006102d26002846107a1565b9050816000015160f81b8482815181106102ee576102ee6107cb565b60200101906001600160f81b031916908160001a9053508160400151601f81111561031b5761031b6107e1565b602083015160059081811115610333576103336107e1565b60ff16901b1760f81b846103488360016107b8565b81518110610358576103586107cb565b60200101906001600160f81b031916908160001a90535050505050565b600060108260400151601f81111561038f5761038f6107e1565b146103a75781606001516103a290610810565b6103b4565b8160600151805190602001205b93909201929092525050565b6000808383815181106103d5576103d56107cb565b6020026020010151602001519050600160058111156103f6576103f66107e1565b816005811115610408576104086107e1565b03610417576001915050610506565b600281600581111561042b5761042b6107e1565b148061044857506004816005811115610446576104466107e1565b145b8061046457506005816005811115610462576104626107e1565b145b15610473576000915050610506565b835160006104828560016107b8565b90505b818110156104fe5760008682815181106104a1576104a16107cb565b6020026020010151600001519050858160ff1610156104c057506104ee565b858160ff1611156104d157506104fe565b6104db87836103c0565b6104ec576000945050505050610506565b505b6104f7816107f7565b9050610485565b506001925050505b92915050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156105455761054561050c565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156105745761057461050c565b604052919050565b80356020811061058b57600080fd5b919050565b600082601f8301126105a157600080fd5b813567ffffffffffffffff8111156105bb576105bb61050c565b6105ce601f8201601f191660200161054b565b8181528460208386010111156105e357600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561061357600080fd5b823567ffffffffffffffff8082111561062b57600080fd5b818501915085601f83011261063f57600080fd5b8135818111156106515761065161050c565b8060051b61066085820161054b565b918252838101850191858101908984111561067a57600080fd5b86860192505b83831015610730578235858111156106985760008081fd5b86016080818c03601f19018113156106b05760008081fd5b6106b8610522565b8983013560ff811681146106cc5760008081fd5b8152604083810135600681106106e25760008081fd5b828c015260606106f385820161057c565b8383015292840135928984111561070c57600091508182fd5b61071a8f8d86880101610590565b9083015250845250509186019190860190610680565b9998505050505050505050565b600060208083528351808285015260005b8181101561076a5785810183015185820160400152820161074e565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176105065761050661078b565b808201808211156105065761050661078b565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b6000600182016108095761080961078b565b5060010190565b80516020808301519190811015610831576000198160200360031b1b821691505b5091905056fea26469706673582212204b6c5106cb5ade5f561523db757ff19a0809413e33e2d1b18ef196c044c32bbb64736f6c63430008110033"; diff --git a/sdk/initData/Roles.ts b/sdk/initData/Roles.ts index cc32133d..836e5ee6 100644 --- a/sdk/initData/Roles.ts +++ b/sdk/initData/Roles.ts @@ -1,4 +1,4 @@ export const salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; export const initCode = - "0x60806040523480156200001157600080fd5b506040516200636638038062006366833981016040819052620000349162000420565b604080516001600160a01b038581166020830152848116828401528316606080830191909152825180830390910181526080909101909152620000778162000081565b5050505062000474565b600054610100900460ff1615808015620000a25750600054600160ff909116105b80620000d25750620000bf306200026560201b620017801760201c565b158015620000d2575060005460ff166001145b6200013b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200015f576000805461ff0019166101001790555b6000806000848060200190518101906200017a919062000420565b919450925090506200018b62000274565b606680546001600160a01b038085166001600160a01b0319928316179092556067805492841692909116919091179055620001c683620002dc565b620001d06200032e565b6040516001600160a01b038281168252808416919085169033907f34d3b96a088381c6843a1f9d94d251afa88f83cc7a0d17fc23a7057506a3fc6d9060200160405180910390a4505050801562000261576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002d05760405162461bcd60e51b815260206004820152602b60248201526000805160206200632683398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000132565b620002da620003a0565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600052606860205260008051602062006346833981519152546001600160a01b031615620003715760405163dfd49ebd60e01b815260040160405180910390fd5b6001600081905260686020526000805160206200634683398151915280546001600160a01b0319169091179055565b600054610100900460ff16620003fc5760405162461bcd60e51b815260206004820152602b60248201526000805160206200632683398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000132565b620002da33620002dc565b6001600160a01b03811681146200041d57600080fd5b50565b6000806000606084860312156200043657600080fd5b8351620004438162000407565b6020850151909350620004568162000407565b6040850151909250620004698162000407565b809150509250925092565b615ea280620004846000396000f3fe608060405234801561001057600080fd5b50600436106101b05760003560e01c8063776d1a01116100ef578063b3dd25c711610092578063b3dd25c71461045d578063c6fe874714610470578063c910638914610483578063cc2f845214610494578063d4b83992146104b5578063e009cfde146104c8578063e19a9dd9146104db578063f2fde38b146104ee57600080fd5b8063776d1a01146103c75780637b0da5b2146103da5780637ceab3b1146103ed5780638da5cb5b14610400578063946d364e14610411578063957ed2b314610424578063a4f9edbf14610437578063a8ec43ee1461044a57600080fd5b8063468721a711610157578063468721a7146102b45780635229073f146102c75780635aef7de6146102da5780635e7c9fe8146102ed578063610b59251461038657806366523f7d14610399578063715018a6146103ac5780637508dd98146103b457600080fd5b80630172a43a146101b5578063086cfca8146101ca5780630c6c76b8146101dd5780632916a9af146101f05780632959513c146102035780632b99e506146102425780632d3c2547146102635780632d9ad53d14610291575b600080fd5b6101c86101c3366004614c17565b610501565b005b6101c86101d8366004614c47565b6105d8565b6101c86101eb366004614c17565b610632565b6101c86101fe366004614c7c565b610708565b61022c610211366004614cc5565b606b602052600090815260409020546001600160a01b031681565b6040516102399190614cde565b60405180910390f35b610255610250366004614d4e565b6107ae565b604051610239929190614e2d565b610283610271366004614c47565b606c6020526000908152604090205481565b604051908152602001610239565b6102a461029f366004614c47565b610895565b6040519015158152602001610239565b6102a46102c2366004614e48565b6108d0565b6102556102d5366004614e48565b61098a565b60665461022c906001600160a01b031681565b6103476102fb366004614cc5565b606a60205260009081526040902080546001909101546001600160801b0380831692600160801b90048116916001600160401b0380821692600160401b83041691600160c01b90041685565b604080516001600160801b03968716815294861660208601526001600160401b039384169085015293166060830152909116608082015260a001610239565b6101c8610394366004614c47565b610a4b565b6101c86103a7366004614ebb565b610b54565b6101c8610be1565b6101c86103c2366004615047565b610bf5565b6101c86103d5366004614c47565b610ccd565b6101c86103e83660046151c6565b610d27565b60655461022c906001600160a01b031681565b6033546001600160a01b031661022c565b6101c861041f3660046151fb565b610e03565b6101c861043236600461526b565b610e5c565b6101c86104453660046152ed565b610f74565b6101c861045836600461534f565b611141565b6101c861046b3660046153bc565b6112cb565b6102a461047e366004614d4e565b61134d565b6065546001600160a01b031661022c565b6104a76104a23660046151fb565b611424565b60405161023992919061540b565b60675461022c906001600160a01b031681565b6101c86104d6366004615468565b61151d565b6101c86104e9366004614c47565b611616565b6101c86104fc366004614c47565b611707565b61050961178f565b60408051808201825260008082526020808301829052858252606981528382206001600160a01b0386168352600190810190915292902081518154929391929091839160ff19169083600281111561056357610563615496565b021790555060208201518154829061ff00191661010083600381111561058b5761058b615496565b021790555050604080518481526001600160a01b03841660208201527f3ccf62aacc3286173cedf5c20ec550071636a2faf0a3b28d93841736a43f822b9250015b60405180910390a15050565b6105e061178f565b606680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f52ae88b092de36f87fb43fe794eb1381023b9c1bce563a871154022c63dce34290600090a35050565b61063a61178f565b6040805180820190915280600281526020016000905260008381526069602090815260408083206001600160a01b038616845260019081019092529091208251815491929091839160ff199091169083600281111561069b5761069b615496565b021790555060208201518154829061ff0019166101008360038111156106c3576106c3615496565b021790555050604080518481526001600160a01b03841660208201527f277465b84f512b759d745fab70327b693ee21ce592fca91a3f491739a25fa76a9250016105cc565b61071061178f565b60a082901c63ffffffff60401b16606084811b6001600160601b031916919091176000908152606b602090815260409182902080546001600160a01b0319166001600160a01b03868116918217909255835191881682526001600160e01b0319871692820192909252918201527f1330d96b64c7e86736f77e027ca34223dd3d1d08049281281c9d597d8098ed5991015b60405180910390a1505050565b336000908152606860205260408120546060906001600160a01b03166107f25733604051634a0bfec160e01b81526004016107e99190614cde565b60405180910390fd5b6000610802858b8b8b8b8b6117e9565b905061080d81611927565b6108508a8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611ad9915050565b9093509150838015610860575082155b1561087e5760405163d27b44a960e01b815260040160405180910390fd5b6108888184611cf3565b5097509795505050505050565b600060016001600160a01b038316148015906108ca57506001600160a01b038281166000908152606860205260409020541615155b92915050565b336000908152606860205260408120546001600160a01b03166109085733604051634a0bfec160e01b81526004016107e99190614cde565b336000908152606c60205260408120546109269088888888886117e9565b905061093181611927565b610974878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250611de4915050565b91506109808183611cf3565b5095945050505050565b336000908152606860205260408120546060906001600160a01b03166109c55733604051634a0bfec160e01b81526004016107e99190614cde565b336000908152606c60205260408120546109e39089898989896117e9565b90506109ee81611927565b610a31888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250611ad9915050565b9093509150610a408184611cf3565b509550959350505050565b610a5361178f565b6001600160a01b0381161580610a7257506001600160a01b0381166001145b15610a925780604051635c93ff2f60e11b81526004016107e99190614cde565b6001600160a01b038181166000908152606860205260409020541615610acd5780604051632061897360e01b81526004016107e99190614cde565b6068602052600080516020615e4d83398151915280546001600160a01b03838116600081815260408082208054949095166001600160a01b03199485161790945560019052835490911617909155517fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844090610b49908390614cde565b60405180910390a150565b610b5c61178f565b600083815260696020526040812060020190610b788484611fee565b8152602001908152602001600020600090557f32a3a599b308fc900a0e6513db2ad40bf0c94367da90048a4b308d8c6b2dd6ea8383836040516107a1939291909283526001600160a01b039190911660208301526001600160e01b031916604082015260600190565b610be961178f565b610bf3600061200e565b565b610bfd61178f565b60405163783a904760e01b81527352c342e002c5f7cf14ef89b5e04cf6d53c7f8e729063783a904790610c349085906004016154d0565b60006040518083038186803b158015610c4c57600080fd5b505af4158015610c60573d6000803e3d6000fd5b5050506000868152606960205260409020610c879150610c808686611fee565b8484612060565b7f4f6c340456f64db31a3d003c1224ba1de058557b1cdf71f21ae48ce4a4f64f528585858585604051610cbe95949392919061557f565b60405180910390a15050505050565b610cd561178f565b606780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f90cc2f570a6eb594b1580ea3e41247d2d73a55281889e86bd4ec2fc29c7e62d690600090a35050565b610d2f61178f565b604080518082019091528060018152602001826003811115610d5357610d53615496565b905260008481526069602090815260408083206001600160a01b038716845260019081019092529091208251815491929091839160ff1990911690836002811115610da057610da0615496565b021790555060208201518154829061ff001916610100836003811115610dc857610dc8615496565b02179055509050507f05e4ec9b54e94ad676ef61d57214f6d57d752ed2022dea5e5f956d5df7ccb2508383836040516107a19392919061564d565b610e0b61178f565b6001600160a01b0382166000818152606c6020908152604091829020849055815192835282018390527f60c85b61661a191efceebca036d48b290e04a1f08dd96472b920adbdd50c64e891016105cc565b610e6461178f565b828114610e84576040516374f4d53760e01b815260040160405180910390fd5b60005b61ffff8116841115610f265782828261ffff16818110610ea957610ea9615670565b9050602002016020810190610ebe9190615686565b6069600087878561ffff16818110610ed857610ed8615670565b6020908102929092013583525081810192909252604090810160009081206001600160a01b038b1682529092529020805460ff1916911515919091179055610f1f816156b9565b9050610e87565b50610f3085610895565b610f3d57610f3d85610a4b565b7f9f8368fa4ddcbd561efd7ad2a2174235bf5b840a73fb18f20db9705c114624988585858585604051610cbe9594939291906156da565b600054610100900460ff1615808015610f945750600054600160ff909116105b80610fb55750610fa330611780565b158015610fb5575060005460ff166001145b6110185760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016107e9565b6000805460ff19166001179055801561103b576000805461ff0019166101001790555b600080600084806020019051810190611054919061576c565b925092509250611062612116565b606680546001600160a01b038085166001600160a01b031992831617909255606780549284169290911691909117905561109b8361200e565b6110a3612145565b816001600160a01b0316836001600160a01b0316336001600160a01b03167f34d3b96a088381c6843a1f9d94d251afa88f83cc7a0d17fc23a7057506a3fc6d846040516110f09190614cde565b60405180910390a4505050801561113d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016105cc565b5050565b61114961178f565b6000846001600160801b031611611167576001600160801b03611169565b835b9350836001600160801b0316856001600160801b0316111561119e5760405163535f0e9160e01b815260040160405180910390fd5b6040805160a0810182526001600160801b03808616825286811660208084019182526001600160401b038088168587019081528b8516606087019081528883166080880190815260008f8152606a90955293889020965194518616600160801b029486169490941786555160019095018054935192518216600160c01b026001600160c01b0393909516600160401b026001600160c01b031990941695909116949094179190911716179055517f63d7ec44a20b176da1d60d75259d264ee67b3d8213706afa71a28f69ed8ebece906112bb908890889088908890889088909586526001600160801b0394851660208701529284166040860152921660608401526001600160401b0391821660808401521660a082015260c00190565b60405180910390a1505050505050565b6112d361178f565b6112dc816121b4565b6000858152606960205260408120600201906112f88686611fee565b8152602001908152602001600020819055507f9603b65b11492fec54ccc3d9feb93536f804d82e12228187ff730a253fc283ee8484848460405161133f94939291906157ae565b60405180910390a150505050565b336000908152606860205260408120546001600160a01b03166113855733604051634a0bfec160e01b81526004016107e99190614cde565b6000611395848a8a8a8a8a6117e9565b90506113a081611927565b6113e3898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b9250611de4915050565b91508280156113f0575081155b1561140e5760405163d27b44a960e01b815260040160405180910390fd5b6114188183611cf3565b50979650505050505050565b60606000826001600160401b0381111561144057611440614ef9565b604051908082528060200260200182016040528015611469578160200160208202803683370190505b506001600160a01b0380861660009081526068602052604081205492945091165b6001600160a01b038116158015906114ac57506001600160a01b038116600114155b80156114b757508482105b1561150f57808483815181106114cf576114cf615670565b6001600160a01b03928316602091820292909201810191909152918116600090815260689092526040909120541681611507816157e1565b92505061148a565b908352919491935090915050565b61152561178f565b6001600160a01b038116158061154457506001600160a01b0381166001145b156115645780604051635c93ff2f60e11b81526004016107e99190614cde565b6001600160a01b038281166000908152606860205260409020548116908216146115a35780604051638b4189ff60e01b81526004016107e99190614cde565b6001600160a01b03818116600081815260686020526040808220805487861684528284208054919096166001600160a01b0319918216179095559290915281549092169055517faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace4054276906105cc908390614cde565b61161e61178f565b6001600160a01b038116156116bb576040516301ffc9a760e01b815263736bd41d60e11b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa158015611678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169c91906157fa565b6116bb57806040516358b7533f60e11b81526004016107e99190614cde565b606580546001600160a01b0319166001600160a01b0383169081179091556040517f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa291610b4991614cde565b61170f61178f565b6001600160a01b0381166117745760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107e9565b61177d8161200e565b50565b6001600160a01b03163b151590565b6033546001600160a01b03163314610bf35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107e9565b6060600087900361180d57604051631fb1d3e560e31b815260040160405180910390fd5b6000878152606960209081526040808320338452918290529091205460ff1661184957604051631fb1d3e560e31b815260040160405180910390fd5b6000611891886118598789615817565b60a01c63ffffffff60401b1660609190911b6001600160601b031916176000908152606b60205260409020546001600160a01b031690565b9050600061189d614bae565b6001600160a01b0383166118c8576118be848b8b8b8b8b87600001516121d8565b90925090506118dd565b6118d783858c8c8c8c8c6123d5565b90925090505b60008260138111156118f1576118f1615496565b14611916576020810151604051631a1537eb60e31b81526107e9918491600401615847565b5193505050505b9695505050505050565b805160005b81811015611ad457600083828151811061194857611948615670565b60209081029190910181015180516040808301516000838152606a8652828120835160a08101855281546001600160801b038082168352600160801b90910481169882019890985260018201546001600160401b0380821696830196909652600160401b81049098166060820152600160c01b909704909316608087015293955091939192909181906119db9042612522565b9150915085602001516001600160801b0316826001600160801b031614611a0457611a04615865565b816001600160801b0316846001600160801b03161115611a2657611a26615865565b611a30848361587b565b6001840180546001600160401b03808516600160c01b026001600160c01b036001600160801b0395909516600160401b02949094169116179190911790557f90355d540c2980efb4c360996dfc5405ee87e812e4f3db843857547cbdb5af658585611a9b818661587b565b604080519384526001600160801b03928316602085015291169082015260600160405180910390a186600101965050505050505061192c565b505050565b6065546000906060906001600160a01b03168015611c66576040805180820182526002815261060f60f31b60208201529051633af85da960e11b81526001600160a01b038316916375f0bb5291611b47918b918b918b918b91600091829182918291829133906004016158ab565b600060405180830381600087803b158015611b6157600080fd5b505af1158015611b75573d6000803e3d6000fd5b5050606754604051635229073f60e01b81526001600160a01b039091169250635229073f9150611baf908a908a908a908a9060040161593a565b6000604051808303816000875af1158015611bce573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611bf691908101906159b5565b604051631264e26d60e31b815261060f60f31b6004820152821515602482015291945092506001600160a01b03821690639327136890604401600060405180830381600087803b158015611c4957600080fd5b505af1158015611c5d573d6000803e3d6000fd5b50505050611ce9565b606754604051635229073f60e01b81526001600160a01b0390911690635229073f90611c9c908a908a908a908a9060040161593a565b6000604051808303816000875af1158015611cbb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ce391908101906159b5565b90935091505b5094509492505050565b815160005b81811015611dde576000848281518110611d1457611d14615670565b602002602001015190506000816000015190508415611d9357604082015160208301517f90355d540c2980efb4c360996dfc5405ee87e812e4f3db843857547cbdb5af65918391611d6690829061587b565b604080519384526001600160801b03928316602085015291169082015260600160405180910390a1611dd4565b6020808301516000838152606a909252604090912060010180546001600160801b03909216600160401b02600160401b600160c01b03199092169190911790555b5050600101611cf8565b50505050565b6065546000906001600160a01b03168015611f68576040805180820182526002815261060f60f31b60208201529051633af85da960e11b81526001600160a01b038316916375f0bb5291611e4f918a918a918a918a91600091829182918291829133906004016158ab565b600060405180830381600087803b158015611e6957600080fd5b505af1158015611e7d573d6000803e3d6000fd5b505060675460405163468721a760e01b81526001600160a01b03909116925063468721a79150611eb790899089908990899060040161593a565b6020604051808303816000875af1158015611ed6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efa91906157fa565b604051631264e26d60e31b815261060f60f31b600482015281151560248201529092506001600160a01b03821690639327136890604401600060405180830381600087803b158015611f4b57600080fd5b505af1158015611f5f573d6000803e3d6000fd5b50505050611fe4565b60675460405163468721a760e01b81526001600160a01b039091169063468721a790611f9e90899089908990899060040161593a565b6020604051808303816000875af1158015611fbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe191906157fa565b91505b505b949350505050565b60a01c63ffffffff60401b1660609190911b6001600160601b0319161790565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051634031b16960e11b81526000907360e89c71882e88f16772490d2f05819d9521eab19063806362d29061209a9086906004016154d0565b600060405180830381865af41580156120b7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120df9190810190615a05565b905060006120ec82612617565b90506120fa84518483612747565b6000958652600290960160205250506040909220929092555050565b600054610100900460ff1661213d5760405162461bcd60e51b81526004016107e990615a39565b610bf361277a565b60016000526068602052600080516020615e4d833981519152546001600160a01b0316156121865760405163dfd49ebd60e01b815260040160405180910390fd5b600160008190526068602052600080516020615e4d83398151915280546001600160a01b0319169091179055565b6000600160d81b60e08360038111156121cf576121cf615496565b901b1792915050565b60006121e2614bae565b84158015906121f15750600485105b1561220f57604051632342609160e11b815260040160405180910390fd5b6001600160a01b03881660009081526001808b01602052604090912090815460ff16600281111561224257612242615496565b0361228057805461225e9089908790610100900460ff166127aa565b60405180604001604052808681526020016000801b81525092509250506123c9565b6002815460ff16600281111561229857612298615496565b036123ae5760006122b28a6122ad898b615817565b611fee565b600081815260028d01602052604081205491925081900361230657600360405180604001604052808881526020018b8b906122ed9190615817565b6001600160e01b031916815250945094505050506123c9565b60008061231283612860565b9150915060006123238d8b846127aa565b9050600081601381111561233957612339615496565b1461236257604080518082019091528981526000602082015290975095506123c9945050505050565b821561239157600060405180604001604052808b81526020016000801b815250975097505050505050506123c9565b61239f8f868f8f8f8e61288b565b975097505050505050506123c9565b50506040805180820190915282815260006020820152600291505b97509795505050505050565b60006123df614bae565b60405163c7a7b63560e01b81526001600160a01b038a169063c7a7b63590612413908a908a908a908a908a90600401615aad565b600060405180830381865afa92505050801561245157506040513d6000823e601f3d908101601f1916820160405261244e9190810190615ae4565b60015b61246e576040516315e649e960e01b815260040160405180910390fd5b60005b815181101561251457600082828151811061248e5761248e615670565b6020026020010151905060008160600151905060008260800151826124b39190615bbb565b90506124de8d846020015185604001518d8d879087926124d593929190615bce565b88518c516121d8565b909750955060008760138111156124f7576124f7615496565b146125065750505050506123c9565b836001019350505050612471565b505097509795505050505050565b60008083604001516001600160401b03166000148061255c5750836040015184608001516125509190615bf8565b6001600160401b031683105b1561257257505060608201516080830151612610565b600084604001518560800151856125899190615c18565b6125939190615c4e565b90506000816001600160401b031686600001516125b09190615c74565b86606001516125bf9190615c97565b905085602001516001600160801b0316816001600160801b0316106125e85785602001516125ea565b805b93508560400151826125fc9190615cb7565b866080015161260b9190615bf8565b925050505b9250929050565b600080612623836128ee565b90506000612688828051602091820120604080516001600160f81b03198185015273ce0042b868300000d44a59004da54a005ffdcf9f60601b602182015260006035820152605580820193909352815180820390930183526075019052805191012090565b9050803b60008181036127195760405163257b1f8160e11b815273ce0042b868300000d44a59004da54a005ffdcf9f90634af63f02906126cf908790600090600401615cda565b6020604051808303816000875af11580156126ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127129190615cfc565b905061271c565b50815b806001600160a01b0316836001600160a01b03161461273d5761273d615865565b5090949350505050565b60006001600160a01b03821660e084600381111561276757612767615496565b60f087901b911b171790505b9392505050565b600054610100900460ff166127a15760405162461bcd60e51b81526004016107e990615a39565b610bf33361200e565b600080841180156127cd575060018260038111156127ca576127ca615496565b14155b80156127eb575060038260038111156127e8576127e8615496565b14155b156127f857506004612773565b600183600181111561280c5761280c615496565b14801561282b5750600282600381111561282857612828615496565b14155b80156128495750600382600381111561284657612846615496565b14155b1561285657506001612773565b5060009392505050565b600160d81b81161515600060e083901c60ff16600381111561288457612884615496565b9050915091565b6000612895614bae565b6000806128a28a8a612926565b9150915060006128b3888885612af7565b90506128db89898986858b516000146128d5576128d08c89612b51565b612e83565b87612e83565b945094505050505b965096945050505050565b6060815160016128fe9190615bbb565b82604051602001612910929190615d19565b6040516020818303038152906040529050919050565b612952604080516080810190915280600081526020016000815260006020820152606060409091015290565b600082815260028401602052604081205460609160f082901c916001600160a01b03169061297f82613134565b905060008061298e83866131ad565b915091506000805b8351811015612ab55760008482815181106129b3576129b3615670565b6020026020010151604001519050601c601f8111156129d4576129d4615496565b81601f8111156129e6576129e6615496565b106129fb576129f4836157e1565b9250612aac565b600f81601f811115612a0f57612a0f615496565b03612aac576010858381518110612a2857612a28615670565b602002602001015160400190601f811115612a4557612a45615496565b9081601f811115612a5857612a58615496565b905250606654604051612a77916001600160a01b031690602001614cde565b60405160208183030381529060405280519060200120848381518110612a9f57612a9f615670565b6020026020010181815250505b50600101612996565b50612acc8383612ac4866133a0565b60008c6134f5565b8760008211612adb5787612ae6565b612ae68484846136d5565b975097505050505050509250929050565b612b1b60405180606001604052806000815260200160008152602001606081525090565b6000612b26836138c1565b9050612b3e8585600484856020015151600088613a51565b5060008152602081019290925250919050565b60608251600003612b635750806108ca565b8151600003612b735750816108ca565b81518351612b819190615bbb565b6001600160401b03811115612b9857612b98614ef9565b604051908082528060200260200182016040528015612be357816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181612bb65790505b50835190915060005b81811015612cdc57848181518110612c0657612c06615670565b602002602001015160000151838281518110612c2457612c24615670565b60200260200101516000018181525050848181518110612c4657612c46615670565b602002602001015160200151838281518110612c6457612c64615670565b6020026020010151602001906001600160801b031690816001600160801b031681525050848181518110612c9a57612c9a615670565b602002602001015160400151838281518110612cb857612cb8615670565b60209081029190910101516001600160801b03909116604090910152600101612bec565b5060005b8351811015612e6e57600080612d1387878581518110612d0257612d02615670565b602002602001015160000151613c03565b915091508015612d7657858381518110612d2f57612d2f615670565b602002602001015160400151858381518110612d4d57612d4d615670565b6020026020010151604001818151612d659190615c97565b6001600160801b0316905250612e64565b858381518110612d8857612d88615670565b602002602001015160000151858581518110612da657612da6615670565b60200260200101516000018181525050858381518110612dc857612dc8615670565b602002602001015160200151858581518110612de657612de6615670565b6020026020010151602001906001600160801b031690816001600160801b031681525050858381518110612e1c57612e1c615670565b602002602001015160400151858581518110612e3a57612e3a615670565b60209081029190910101516001600160801b0390911660409091015283612e60816157e1565b9450505b5050600101612ce0565b508151811015612e7c578082525b5092915050565b6000612e8d614bae565b6020850151601081601f811115612ea657612ea6615496565b101561300757600081601f811115612ec057612ec0615496565b03612ee45750506040805180820190915282815260006020820181905291506128e3565b600581601f811115612ef857612ef8615496565b03612f1557612f0b898989898989613c5b565b92509250506128e3565b600181601f811115612f2957612f29615496565b03612f3c57612f0b898989898989613d4b565b600281601f811115612f5057612f50615496565b03612f6357612f0b898989898989613dff565b600381601f811115612f7757612f77615496565b03612f8a57612f0b898989898989613e9f565b600681601f811115612f9e57612f9e615496565b03612fb157612f0b898989898989613f50565b600781601f811115612fc557612fc5615496565b03612fd857612f0b89898989898961400e565b600881601f811115612fec57612fec615496565b14612ff957612ff9615865565b612f0b8989898989896140bd565b601281601f81111561301b5761301b615496565b1161304e5761302c88888888614211565b60405180604001604052808681526020016000801b81525092509250506128e3565b601481601f81111561306257613062615496565b116130735761302c8888888861431c565b601581601f81111561308757613087615496565b036130985761302c8888888861439f565b601681601f8111156130ac576130ac615496565b036130bf57612f0b898989898989614480565b601c81601f8111156130d3576130d3615496565b036130e557612f0b8888888888614561565b601d81601f8111156130f9576130f9615496565b0361310957612f0b898786614598565b601e81601f81111561311d5761311d615496565b1461312a5761312a615865565b612f0b86856145e0565b6060813b6001811161314857613148615865565b600160006131568284615d70565b9050806001600160401b0381111561317057613170614ef9565b6040519080825280601f01601f19166020018201604052801561319a576020820181803683370190505b509350808260208601873c505050919050565b606080826001600160401b038111156131c8576131c8614ef9565b60405190808252806020026020018201604052801561320157816020015b6131ee614bc6565b8152602001906001900390816131e65790505b509150826001600160401b0381111561321c5761321c614ef9565b604051908082528060200260200182016040528015613245578160200160208202803683370190505b5090506000602081613258600287615d83565b613263906020615bbb565b905060005b8681101561339557878301519350613281600284615bbb565b925060008460f01c9050600087838151811061329f5761329f615670565b6020908102919091010151600883901c60ff1681529050600582811c600716908111156132ce576132ce615496565b816020019060058111156132e4576132e4615496565b908160058111156132f7576132f7615496565b905250601f8281169081111561330f5761330f615496565b8160400190601f81111561332557613325615496565b9081601f81111561333857613338615496565b90525060108160400151601f81111561335357613353615496565b1061338b57898401519550613369602085615bbb565b93508587848151811061337e5761337e615670565b6020026020010181815250505b5050600101613268565b505050509250929050565b8051606090806133b2576133b2615865565b806001600160401b038111156133ca576133ca614ef9565b60405190808252806020026020018201604052801561341f57816020015b61340c60405180606001604052806000815260200160008152602001600081525090565b8152602001906001900390816133e85790505b5091506000198260008151811061343857613438615670565b60209081029190910101515260015b818110156134ee5760001983828151811061346457613464615670565b6020026020010151600001818152505060008385838151811061348957613489615670565b60200260200101516000015160ff16815181106134a8576134a8615670565b602002602001015190506000198160000151036134c3578181525b6134ce826001615bbb565b6020820181905281516134e091615d70565b604090910152600101613447565b5050919050565b600085838151811061350957613509615670565b6020026020010151905080602001518260000190600581111561352e5761352e615496565b9081600581111561354157613541615496565b90525060408101516020830190601f81111561355f5761355f615496565b9081601f81111561357257613572615496565b8152505084838151811061358857613588615670565b60200260200101518260400181815250508383815181106135ab576135ab615670565b6020026020010151604001516000036135c457506136ce565b60008484815181106135d8576135d8615670565b602002602001015160000151905060008585815181106135fa576135fa615670565b6020026020010151604001519050806001600160401b0381111561362057613620614ef9565b60405190808252806020026020018201604052801561367d57816020015b61366a604080516080810190915280600081526020016000815260006020820152606060409091015290565b81526020019060019003908161363e5790505b50606085015260005b818110156136c9576136c189898961369e8588615bbb565b896060015186815181106136b4576136b4615670565b60200260200101516134f5565b600101613686565b505050505b5050505050565b8251606090826001600160401b038111156136f2576136f2614ef9565b60405190808252806020026020018201604052801561373d57816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816137105790505b5091506000805b828110156138ab57601c87828151811061376057613760615670565b602002602001015160400151601f81111561377d5761377d615496565b1061389b57600086828151811061379657613796615670565b6020026020010151905060006137ac8683613c03565b91505080156137bc57505061389b565b818685815181106137cf576137cf615670565b602090810291909101810151919091526000838152606a8252604090819020815160a08101835281546001600160801b038082168352600160801b9091048116948201949094526001909101546001600160401b0380821693830193909352600160401b81049093166060820152600160c01b9092041660808201526138559042612522565b5086858151811061386857613868615670565b6020026020010151602001816001600160801b03166001600160801b0316815250508380613895906157e1565b94505050505b6138a4816157e1565b9050613744565b50838110156138b8578083525b50509392505050565b6138c9614bf0565b60018260200151601f8111156138e1576138e1615496565b10158015613905575060038260200151601f81111561390257613902615496565b11155b156139465760008260600151511161391f5761391f615865565b6108ca826060015160008151811061393957613939615670565b60200260200101516138c1565b81518190600581111561395b5761395b615496565b9081600581111561396e5761396e615496565b90525060608201515115613a4c57600060048351600581111561399357613993615496565b146139a3578260600151516139a6565b60015b9050806001600160401b038111156139c0576139c0614ef9565b6040519080825280602002602001820160405280156139f957816020015b6139e6614bf0565b8152602001906001900390816139de5790505b50602083015260005b818110156134ee57613a238460600151828151811061393957613939615670565b83602001518281518110613a3957613a39615670565b6020908102919091010152600101613a02565b919050565b826001600160401b03811115613a6957613a69614ef9565b604051908082528060200260200182016040528015613abe57816020015b613aab60405180606001604052806000815260200160008152602001606081525090565b815260200190600190039081613a875790505b50604082015260008215613af657613af38560200151600081518110613ae657613ae6615670565b6020026020010151614627565b90505b6000805b85811015613bf75784613b2357613b2087602001518281518110613ae657613ae6615670565b92505b613b838a8a613b358d8d8d888a6146f5565b8a6020015189613b455785613b48565b60005b81518110613b5857613b58615670565b602002602001015188604001518681518110613b7657613b76615670565b6020026020010151614733565b600084604001518281518110613b9b57613b9b615670565b602002602001015160200151905083613bbe57613bb9816020615bbb565b613bc0565b805b85602001818151613bd19190615bbb565b90525083613be0576020613be2565b805b613bec9084615bbb565b925050600101613afa565b50505050505050505050565b81516000908190815b81811015613c4d5784868281518110613c2757613c27615670565b60200260200101516000015103613c45579250600191506126109050565b600101613c0c565b506000958695509350505050565b6000613c65614bae565b60408051808201825284815260006020820152908501515160608701515114613c9357600a925090506128e3565b60005b866060015151811015613d3a57613cef8a8a8a8a606001518581518110613cbf57613cbf615670565b60200260200101518a604001518681518110613cdd57613cdd615670565b60200260200101518760000151612e83565b90945091506000846013811115613d0857613d08615496565b14613d325783604051806040016040528087815260200184602001518152509350935050506128e3565b600101613c96565b506000999098509650505050505050565b6000613d55614bae565b50604080518082019091528281526000602082018190525b856060015151811015613def57613da989898989606001518581518110613d9657613d96615670565b6020026020010151898760000151612e83565b90935091506000836013811115613dc257613dc2615496565b14613de7575060408051808201909152838152602091820151918101919091526128e3565b600101613d6d565b5060009150965096945050505050565b6000613e09614bae565b60005b856060015151811015613e7b57600080613e478b8b8b8b606001518781518110613e3857613e38615670565b60200260200101518b8b612e83565b90925090506000826013811115613e6057613e60615496565b03613e715790935091506128e39050565b5050600101613e0c565b50506040805180820190915291825250600060208201526005969095509350505050565b6000613ea9614bae565b60005b856060015151811015613f2c576000613ee68a8a8a8a606001518681518110613ed757613ed7615670565b60200260200101518a8a612e83565b5090506000816013811115613efd57613efd615496565b03613f2357505060408051808201909152838152600060208201526006925090506128e3565b50600101613eac565b50506040805180820190915291825250600060208201819052969095509350505050565b6000613f5a614bae565b60005b846040015151811015613fea57600080613fb68b8b8b8b60600151600081518110613f8a57613f8a615670565b60200260200101518b604001518881518110613fa857613fa8615670565b60200260200101518b612e83565b90925090506000826013811115613fcf57613fcf615496565b03613fe05790935091506128e39050565b5050600101613f5d565b5050604080518082019091529182525060006020820152600c969095509350505050565b6000614018614bae565b50604080518082019091528281526000602082018190525b846040015151811015613def57614078898989896060015160008151811061405a5761405a615670565b602002602001015189604001518681518110613cdd57613cdd615670565b9093509150600083601381111561409157614091615496565b146140b55750506040805180820190915282815260006020820152600b91506128e3565b600101614030565b60006140c7614bae565b5060408051808201825283815260006020820152908401515115806140f55750846060015151846040015151115b1561410357600d91506128e3565b6000805b856040015151811015614200576000805b8860600151518110156141c6576001811b84166000036141b6576000806141818e8e8e8e60600151878151811061415157614151615670565b60200260200101518e604001518a8151811061416f5761416f615670565b60200260200101518c60000151612e83565b9092509050600082601381111561419a5761419a615496565b036141b357955050600180821b949094179391506141c6565b50505b6141bf816157e1565b9050614118565b50806141ef5750506040805180820190915284815260006020820152600d935091506128e39050565b506141f9816157e1565b9050614107565b506000925050965096945050505050565b602082015160408301516000919082601083601f81111561423457614234615496565b1461424d5761424888888760000151614891565b614278565b6142618888876000015188602001516148c9565b60405161426f929190615d9a565b60405180910390205b9050601083601f81111561428e5761428e615496565b14801561429b5750818114155b156142ac5760079350505050611fe6565b601183601f8111156142c0576142c0615496565b1480156142cd5750818111155b156142de5760089350505050611fe6565b601283601f8111156142f2576142f2615496565b1480156142ff5750818110155b156143105760099350505050611fe6565b60009350505050611fe6565b6020820151604083015182516000929190839061433c9089908990614891565b9050601383601f81111561435257614352615496565b14801561435f5750818113155b156143705760089350505050611fe6565b601483601f81111561438457614384615496565b1480156142ff57508181126143105760099350505050611fe6565b6040820151600090816001855160058111156143bd576143bd615496565b14905036600061440c8989856143d45760206143d7565b60005b89516143e69160ff1690615bbb565b866143f25760206143f5565b60005b60ff168a602001516144079190615d70565b6148c9565b909250905060f084901c81811061442b57600e95505050505050611fe6565b6001600160881b0319601086901b8116608887901b821660006144508686818a615bce565b61445991615daa565b9050818382161461446b57600f61446e565b60005b9e9d5050505050505050505050505050565b600061448a614bae565b6000856040015160601c90506000866040015160001c60a01b9050600080836001600160a01b031663416ad87a8d8d8d8c600001518d60200151896040518763ffffffff1660e01b81526004016144e696959493929190615dc8565b6040805180830381865afa158015614502573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145269190615e0a565b9150915081614536576010614539565b60005b6040518060400160405280898152602001838152509550955050505050965096945050505050565b600061456b614bae565b600061457c88888760000151614891565b90506145898187866148f3565b92509250509550959350505050565b60006145a2614bae565b6145ad8585856148f3565b909250905060008260138111156145c6576145c6615496565b146145d25760136145d5565b60005b91505b935093915050565b60006145ea614bae565b6145f6600185856148f3565b9092509050600082601381111561460f5761460f615496565b1461461b57601261461e565b60005b91509250929050565b8051600090600181600581111561464057614640615496565b0361464e5750600192915050565b600281600581111561466257614662615496565b148061467f5750600481600581111561467d5761467d615496565b145b8061469b5750600581600581111561469957614699615496565b145b156146a95750600092915050565b60208301515160005b818110156146ea576146d385602001518281518110613ae657613ae6615670565b6146e257506000949350505050565b6001016146b2565b506001949350505050565b6000806147028486615bbb565b9050821561471157905061472a565b61471c878783614891565b6147269086615bbb565b9150505b95945050505050565b8151600181600581111561474957614749615496565b0361475957602082810152614887565b600281600581111561476d5761476d615496565b0361479a57614785614780878787614891565b614a21565b614790906020615bbb565b6020830152614887565b60038160058111156147ae576147ae615496565b036147cd576147c886868686876020015151600088613a51565b614887565b60048160058111156147e1576147e1615496565b036148255761480a86866147f6876020615bbb565b866148028b8b8b614891565b600188613a51565b60208260200181815161481d9190615bbb565b905250614887565b600581600581111561483957614839615496565b0361488757614868868661484e876020615bbb565b614859906004615bbb565b86876020015151600088613a51565b614876614780878787614891565b614881906020615bbb565b60208301525b5091909152505050565b60008261489f836020615bbb565b11156148be57604051631d098e2d60e21b815260040160405180910390fd5b509190910135919050565b3660008584866148d98683615bbb565b926148e693929190615bce565b9150915094509492505050565b60006148fd614bae565b60008061490e858760400151613c03565b915091508061491f5761491f615865565b84828151811061493157614931615670565b6020026020010151602001516001600160801b031685838151811061495857614958615670565b6020026020010151604001516001600160801b0316886149789190615bbb565b11156149bd57601160405180604001604052808781526020018785815181106149a3576149a3615670565b6020026020010151600001518152509350935050506145d8565b6149c685614a50565b9450868583815181106149db576149db615670565b60200260200101516040018181516149f39190615c97565b6001600160801b03169052505060408051808201909152848152600060208201819052935091506145d89050565b600060206001614a318483615bbb565b614a3b9190615d70565b614a459190615e38565b6108ca906020615d83565b8051606090806001600160401b03811115614a6d57614a6d614ef9565b604051908082528060200260200182016040528015614ab857816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181614a8b5790505b50915060005b818110156134ee57838181518110614ad857614ad8615670565b602002602001015160000151838281518110614af657614af6615670565b60200260200101516000018181525050838181518110614b1857614b18615670565b602002602001015160200151838281518110614b3657614b36615670565b6020026020010151602001906001600160801b031690816001600160801b031681525050838181518110614b6c57614b6c615670565b602002602001015160400151838281518110614b8a57614b8a615670565b60209081029190910101516001600160801b03909116604090910152600101614abe565b60408051808201909152606081526000602082015290565b604080516080810190915260008082526020820190815260200160005b8152602001606081525090565b60408051808201909152806000614be3565b6001600160a01b038116811461177d57600080fd5b60008060408385031215614c2a57600080fd5b823591506020830135614c3c81614c02565b809150509250929050565b600060208284031215614c5957600080fd5b813561277381614c02565b80356001600160e01b031981168114613a4c57600080fd5b600080600060608486031215614c9157600080fd5b8335614c9c81614c02565b9250614caa60208501614c64565b91506040840135614cba81614c02565b809150509250925092565b600060208284031215614cd757600080fd5b5035919050565b6001600160a01b0391909116815260200190565b60008083601f840112614d0457600080fd5b5081356001600160401b03811115614d1b57600080fd5b60208301915083602082850101111561261057600080fd5b6002811061177d57600080fd5b801515811461177d57600080fd5b600080600080600080600060c0888a031215614d6957600080fd5b8735614d7481614c02565b96506020880135955060408801356001600160401b03811115614d9657600080fd5b614da28a828b01614cf2565b9096509450506060880135614db681614d33565b92506080880135915060a0880135614dcd81614d40565b8091505092959891949750929550565b60005b83811015614df8578181015183820152602001614de0565b50506000910152565b60008151808452614e19816020860160208601614ddd565b601f01601f19169290920160200192915050565b8215158152604060208201526000611fe66040830184614e01565b600080600080600060808688031215614e6057600080fd5b8535614e6b81614c02565b94506020860135935060408601356001600160401b03811115614e8d57600080fd5b614e9988828901614cf2565b9094509250506060860135614ead81614d33565b809150509295509295909350565b600080600060608486031215614ed057600080fd5b833592506020840135614ee281614c02565b9150614ef060408501614c64565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715614f3157614f31614ef9565b60405290565b60405160a081016001600160401b0381118282101715614f3157614f31614ef9565b604051601f8201601f191681016001600160401b0381118282101715614f8157614f81614ef9565b604052919050565b60006001600160401b03821115614fa257614fa2614ef9565b5060051b60200190565b803560208110613a4c57600080fd5b60006001600160401b03821115614fd457614fd4614ef9565b50601f01601f191660200190565b600082601f830112614ff357600080fd5b813561500661500182614fbb565b614f59565b81815284602083860101111561501b57600080fd5b816020850160208301376000918101602001919091529392505050565b803560048110613a4c57600080fd5b600080600080600060a0868803121561505f57600080fd5b853594506150706020870135614c02565b6020860135935061508360408701614c64565b92506001600160401b036060870135111561509d57600080fd5b6060860135860187601f8201126150b357600080fd5b6150c06150018235614f89565b81358082526020808301929160051b8401018a8111156150df57600080fd5b602084015b818110156151a6576001600160401b038135111561510157600080fd5b803585016080818e03601f1901121561511957600080fd5b615121614f0f565b602082013560ff81161461513457600080fd5b60208201358152600660408301351061514c57600080fd5b6040820135602082015261516260608301614fac565b60408201526001600160401b036080830135111561517f57600080fd5b6151928e60206080850135850101614fe2565b6060820152855250602093840193016150e4565b50508094505050506151ba60808701615038565b90509295509295909350565b6000806000606084860312156151db57600080fd5b8335925060208401356151ed81614c02565b9150614ef060408501615038565b6000806040838503121561520e57600080fd5b823561521981614c02565b946020939093013593505050565b60008083601f84011261523957600080fd5b5081356001600160401b0381111561525057600080fd5b6020830191508360208260051b850101111561261057600080fd5b60008060008060006060868803121561528357600080fd5b853561528e81614c02565b945060208601356001600160401b03808211156152aa57600080fd5b6152b689838a01615227565b909650945060408801359150808211156152cf57600080fd5b506152dc88828901615227565b969995985093965092949392505050565b6000602082840312156152ff57600080fd5b81356001600160401b0381111561531557600080fd5b611fe684828501614fe2565b80356001600160801b0381168114613a4c57600080fd5b80356001600160401b0381168114613a4c57600080fd5b60008060008060008060c0878903121561536857600080fd5b8635955061537860208801615321565b945061538660408801615321565b935061539460608801615321565b92506153a260808801615338565b91506153b060a08801615338565b90509295509295509295565b600080600080608085870312156153d257600080fd5b8435935060208501356153e481614c02565b92506153f260408601614c64565b915061540060608601615038565b905092959194509250565b604080825283519082018190526000906020906060840190828701845b8281101561544d5781516001600160a01b031684529284019290840190600101615428565b5050506001600160a01b039490941692019190915250919050565b6000806040838503121561547b57600080fd5b823561548681614c02565b91506020830135614c3c81614c02565b634e487b7160e01b600052602160045260246000fd5b600681106154bc576154bc615496565b9052565b602081106154bc576154bc615496565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561556157603f198984030185528151608060ff8251168552888201516155238a8701826154ac565b5087820151615534898701826154c0565b5060609182015191850181905261554d85820183614e01565b9689019694505050908601906001016154f7565b509098975050505050505050565b600481106154bc576154bc615496565b600060a08201878352602060018060a01b03881681850152604063ffffffff60e01b881681860152606060a08187015283885180865260c08801915060c08160051b8901019550848a0160005b828110156156355760bf198a89030184528151608060ff8251168a52888201516155f88a8c01826154ac565b5087820151615609898c01826154c0565b5086820151915080878b0152615621818b0183614e01565b9950505092860192908601906001016155cc565b505050505050508091505061191d608083018461556f565b8381526001600160a01b038316602082015260608101611fe6604083018461556f565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561569857600080fd5b813561277381614d40565b634e487b7160e01b600052601160045260246000fd5b600061ffff8083168181036156d0576156d06156a3565b6001019392505050565b6001600160a01b0386168152606060208083018290529082018590526000906001600160fb1b0386111561570d57600080fd5b8560051b808860808601378301838103608090810160408601528101859052859060009060a0015b8682101561575e57823561574881614d40565b1515815291830191600191909101908301615735565b9a9950505050505050505050565b60008060006060848603121561578157600080fd5b835161578c81614c02565b602085015190935061579d81614c02565b6040850151909250614cba81614c02565b8481526001600160a01b03841660208201526001600160e01b0319831660408201526080810161472a606083018461556f565b6000600182016157f3576157f36156a3565b5060010190565b60006020828403121561580c57600080fd5b815161277381614d40565b6001600160e01b0319813581811691600485101561583f5780818660040360031b1b83161692505b505092915050565b604081016014841061585b5761585b615496565b9281526020015290565b634e487b7160e01b600052600160045260246000fd5b6001600160801b03828116828216039080821115612e7c57612e7c6156a3565b600281106154bc576154bc615496565b6001600160a01b038c81168252602082018c9052610160604083018190526000916158d88483018e614e01565b91506158e7606085018d61589b565b8a60808501528960a08501528860c085015280881660e085015280871661010085015283820361012085015261591d8287614e01565b925080851661014085015250509c9b505050505050505050505050565b60018060a01b03851681528360208201526080604082015260006159616080830185614e01565b905061472a606083018461589b565b600082601f83011261598157600080fd5b815161598f61500182614fbb565b8181528460208386010111156159a457600080fd5b611fe6826020830160208701614ddd565b600080604083850312156159c857600080fd5b82516159d381614d40565b60208401519092506001600160401b038111156159ef57600080fd5b6159fb85828601615970565b9150509250929050565b600060208284031215615a1757600080fd5b81516001600160401b03811115615a2d57600080fd5b611fe684828501615970565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b0386168152846020820152608060408201526000615ad5608083018587615a84565b905061191d606083018461589b565b60006020808385031215615af757600080fd5b82516001600160401b03811115615b0d57600080fd5b8301601f81018513615b1e57600080fd5b8051615b2c61500182614f89565b81815260a09182028301840191848201919088841115615b4b57600080fd5b938501935b838510156114185780858a031215615b685760008081fd5b615b70614f37565b8551615b7b81614d33565b815285870151615b8a81614c02565b8188015260408681015190820152606080870151908201526080808701519082015283529384019391850191615b50565b808201808211156108ca576108ca6156a3565b60008085851115615bde57600080fd5b83861115615beb57600080fd5b5050820193919092039150565b6001600160401b03818116838216019080821115612e7c57612e7c6156a3565b6001600160401b03828116828216039080821115612e7c57612e7c6156a3565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b0380841680615c6857615c68615c38565b92169190910492915050565b6001600160801b0381811683821602808216919082811461583f5761583f6156a3565b6001600160801b03818116838216019080821115612e7c57612e7c6156a3565b6001600160401b0381811683821602808216919082811461583f5761583f6156a3565b604081526000615ced6040830185614e01565b90508260208301529392505050565b600060208284031215615d0e57600080fd5b815161277381614c02565b606360f81b815260e083901b6001600160e01b03191660018201526880600e6000396000f360b81b60058201526000600e82018190528251615d6281600f850160208701614ddd565b91909101600f019392505050565b818103818111156108ca576108ca6156a3565b80820281158282048414176108ca576108ca6156a3565b8183823760009101908152919050565b803560208310156108ca57600019602084900360031b1b1692915050565b86815260a060208201526000615de260a083018789615a84565b60408301959095525060608101929092526001600160a01b0319166080909101529392505050565b60008060408385031215615e1d57600080fd5b8251615e2881614d40565b6020939093015192949293505050565b600082615e4757615e47615c38565b50049056fe82eaf0fca2207f91f5027fcf68136c84edb7e928c081c42aa5bbc2a771c7d376a26469706673582212203c89de6fbdf80ff2795147a6273647af5b7403d341c681eb87ab9a5a4561dec964736f6c63430008110033496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206982eaf0fca2207f91f5027fcf68136c84edb7e928c081c42aa5bbc2a771c7d376000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"; + "0x60806040523480156200001157600080fd5b5060405162006aa738038062006aa7833981810160405281019062000037919062000892565b6000838383604051602001620000509392919062000991565b604051602081830303815290604052905062000072816200007c60201b60201c565b5050505062000b8d565b60008060008380602001905181019062000097919062000836565b925092509250620000ad620001d460201b60201c565b81606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506200014083620002d360201b60201c565b62000150620003e960201b60201c565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f34d3b96a088381c6843a1f9d94d251afa88f83cc7a0d17fc23a7057506a3fc6d84604051620001c6919062000974565b60405180910390a450505050565b600060019054906101000a900460ff1680620001fb575060008054906101000a900460ff16155b6200023d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200023490620009f0565b60405180910390fd5b60008060019054906101000a900460ff1615905080156200028e576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6200029e6200053260201b60201c565b620002ae6200061160201b60201c565b8015620002d05760008060016101000a81548160ff0219169083151502179055505b50565b620002e36200071060201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003096200071860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000362576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003599062000a12565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620003d5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003cc90620009ce565b60405180910390fd5b620003e6816200074260201b60201c565b50565b600073ffffffffffffffffffffffffffffffffffffffff1660686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614620004b0576040517ff736703400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600060019054906101000a900460ff168062000559575060008054906101000a900460ff16155b6200059b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200059290620009f0565b60405180910390fd5b60008060019054906101000a900460ff161590508015620005ec576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b80156200060e5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff168062000638575060008054906101000a900460ff16155b6200067a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200067190620009f0565b60405180910390fd5b60008060019054906101000a900460ff161590508015620006cb576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b620006eb620006df6200071060201b60201c565b6200074260201b60201c565b80156200070d5760008060016101000a81548160ff0219169083151502179055505b50565b600033905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600081519050620008198162000b59565b92915050565b600081519050620008308162000b73565b92915050565b60008060006060848603121562000852576200085162000a8d565b5b600062000862868287016200081f565b935050602062000875868287016200081f565b925050604062000888868287016200081f565b9150509250925092565b600080600060608486031215620008ae57620008ad62000a8d565b5b6000620008be8682870162000808565b9350506020620008d18682870162000808565b9250506040620008e48682870162000808565b9150509250925092565b620008f98162000a45565b82525050565b60006200090e60268362000a34565b91506200091b8262000a92565b604082019050919050565b600062000935602e8362000a34565b9150620009428262000ae1565b604082019050919050565b60006200095c60208362000a34565b9150620009698262000b30565b602082019050919050565b60006020820190506200098b6000830184620008ee565b92915050565b6000606082019050620009a86000830186620008ee565b620009b76020830185620008ee565b620009c66040830184620008ee565b949350505050565b60006020820190508181036000830152620009e981620008ff565b9050919050565b6000602082019050818103600083015262000a0b8162000926565b9050919050565b6000602082019050818103600083015262000a2d816200094d565b9050919050565b600082825260208201905092915050565b600062000a528262000a6d565b9050919050565b600062000a668262000a6d565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600080fd5b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b62000b648162000a45565b811462000b7057600080fd5b50565b62000b7e8162000a59565b811462000b8a57600080fd5b50565b615f0a8062000b9d6000396000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c8063610b59251161011a578063a4f9edbf116100ad578063cc2f84521161007c578063cc2f8452146105a9578063d4b83992146105da578063e009cfde146105f8578063e19a9dd914610614578063f2fde38b1461063057610206565b8063a4f9edbf14610522578063a6edf38f1461053e578063b0c199121461055a578063c91063891461058b57610206565b80637ceab3b1116100e95780637ceab3b1146104ae5780638b95eccd146104cc5780638da5cb5b146104e8578063939337721461050657610206565b8063610b59251461043c5780636928e74b14610458578063715018a614610488578063776d1a011461049257610206565b80632e506a481161019d578063468721a71161016c578063468721a71461038557806351fa1d73146103b55780635229073f146103d15780635aef7de6146104025780635e8266951461042057610206565b80632e506a48146103155780632fcf52d11461033157806333a0480c1461034d5780633c1952b81461036957610206565b80632933ef1c116101d95780632933ef1c1461027b578063294402cc146102975780632d3c2547146102b55780632d9ad53d146102e557610206565b8063086cfca81461020b5780630de729c714610227578063102b7fe61461024357806315b77d3f1461025f575b600080fd5b61022560048036038101906102209190613f5e565b61064c565b005b610241600480360381019061023c919061479c565b61078e565b005b61025d600480360381019061025891906140b3565b610896565b005b6102796004803603810190610274919061455d565b6109a9565b005b610295600480360381019061029091906143d6565b610ab4565b005b61029f610bbc565b6040516102ac9190614f16565b60405180910390f35b6102cf60048036038101906102ca9190613f5e565b610be2565b6040516102dc91906155e6565b60405180910390f35b6102ff60048036038101906102fa9190613f5e565b610c03565b60405161030c91906150d8565b60405180910390f35b61032f600480360381019061032a9190614735565b610cd5565b005b61034b6004803603810190610346919061455d565b610de0565b005b61036760048036038101906103629190614429565b610eeb565b005b610383600480360381019061037e9190614673565b61100b565b005b61039f600480360381019061039a9190614133565b611122565b6040516103ac91906150d8565b60405180910390f35b6103cf60048036038101906103ca9190614396565b611349565b005b6103eb60048036038101906103e69190614133565b61144e565b6040516103f99291906150f3565b60405180910390f35b61040a61167b565b6040516104179190614f16565b60405180910390f35b61043a60048036038101906104359190614396565b6116a1565b005b61045660048036038101906104519190613f5e565b6117a6565b005b610472600480360381019061046d91906141bb565b611b30565b60405161047f91906150d8565b60405180910390f35b610490611d4e565b005b6104ac60048036038101906104a79190613f5e565b611dd6565b005b6104b6611f18565b6040516104c39190614f16565b60405180910390f35b6104e660048036038101906104e19190613f5e565b611f3e565b005b6104f0612057565b6040516104fd9190614f16565b60405180910390f35b610520600480360381019061051b91906145c4565b612081565b005b61053c60048036038101906105379190614320565b612195565b005b6105586004803603810190610553919061401e565b6122d1565b005b610574600480360381019061056f91906141bb565b6124d8565b6040516105829291906150f3565b60405180910390f35b610593612700565b6040516105a09190614f16565b60405180910390f35b6105c360048036038101906105be91906140f3565b61272a565b6040516105d19291906150a8565b60405180910390f35b6105e261292b565b6040516105ef9190614f16565b60405180910390f35b610612600480360381019061060d9190613fde565b612951565b005b61062e60048036038101906106299190613f5e565b612cda565b005b61064a60048036038101906106459190613f5e565b612f10565b005b610654613008565b73ffffffffffffffffffffffffffffffffffffffff16610672612057565b73ffffffffffffffffffffffffffffffffffffffff16146106c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bf906151c7565b60405180910390fd5b6000606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f52ae88b092de36f87fb43fe794eb1381023b9c1bce563a871154022c63dce34260405160405180910390a35050565b610796613008565b73ffffffffffffffffffffffffffffffffffffffff166107b4612057565b73ffffffffffffffffffffffffffffffffffffffff161461080a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610801906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763a2f6f6d0606b60008661ffff1661ffff1681526020019081526020016000208585856040518563ffffffff1660e01b815260040161086194939291906155a1565b60006040518083038186803b15801561087957600080fd5b505af415801561088d573d6000803e3d6000fd5b50505050505050565b61089e613008565b73ffffffffffffffffffffffffffffffffffffffff166108bc612057565b73ffffffffffffffffffffffffffffffffffffffff1614610912576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610909906151c7565b60405180910390fd5b80606a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548161ffff021916908361ffff1602179055507f197e61bb67ba4b0f657afcb5d2dbed385d50b697c51090f466cdbcc4c30a21ce828260405161099d929190614f7a565b60405180910390a15050565b6109b1613008565b73ffffffffffffffffffffffffffffffffffffffff166109cf612057565b73ffffffffffffffffffffffffffffffffffffffff1614610a25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1c906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763163592dd606b60008761ffff1661ffff168152602001908152602001600020868686866040518663ffffffff1660e01b8152600401610a7e9594939291906153fc565b60006040518083038186803b158015610a9657600080fd5b505af4158015610aaa573d6000803e3d6000fd5b5050505050505050565b610abc613008565b73ffffffffffffffffffffffffffffffffffffffff16610ada612057565b73ffffffffffffffffffffffffffffffffffffffff1614610b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b27906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa216989375976377cff804606b60008661ffff1661ffff1681526020019081526020016000208585856040518563ffffffff1660e01b8152600401610b879493929190615308565b60006040518083038186803b158015610b9f57600080fd5b505af4158015610bb3573d6000803e3d6000fd5b50505050505050565b606960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606a6020528060005260406000206000915054906101000a900461ffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff1614158015610cce5750600073ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b610cdd613008565b73ffffffffffffffffffffffffffffffffffffffff16610cfb612057565b73ffffffffffffffffffffffffffffffffffffffff1614610d51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d48906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa21698937597633c5a24e2606b60008761ffff1661ffff168152602001908152602001600020868686866040518663ffffffff1660e01b8152600401610daa95949392919061554e565b60006040518083038186803b158015610dc257600080fd5b505af4158015610dd6573d6000803e3d6000fd5b5050505050505050565b610de8613008565b73ffffffffffffffffffffffffffffffffffffffff16610e06612057565b73ffffffffffffffffffffffffffffffffffffffff1614610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa21698937597635ebbaa68606b60008761ffff1661ffff168152602001908152602001600020868686866040518663ffffffff1660e01b8152600401610eb59594939291906153fc565b60006040518083038186803b158015610ecd57600080fd5b505af4158015610ee1573d6000803e3d6000fd5b5050505050505050565b610ef3613008565b73ffffffffffffffffffffffffffffffffffffffff16610f11612057565b73ffffffffffffffffffffffffffffffffffffffff1614610f67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5e906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa21698937597632af6aecb606b60008e61ffff1661ffff1681526020019081526020016000208d8d8d8d8d8d8d8d8d8d8d6040518d63ffffffff1660e01b8152600401610fce9c9b9a9998979695949392919061534d565b60006040518083038186803b158015610fe657600080fd5b505af4158015610ffa573d6000803e3d6000fd5b505050505050505050505050505050565b611013613008565b73ffffffffffffffffffffffffffffffffffffffff16611031612057565b73ffffffffffffffffffffffffffffffffffffffff1614611087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107e906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763edf909e3606b60008b61ffff1661ffff1681526020019081526020016000208a8a8a8a8a8a8a8a6040518a63ffffffff1660e01b81526004016110e8999897969594939291906154c7565b60006040518083038186803b15801561110057600080fd5b505af4158015611114573d6000803e3d6000fd5b505050505050505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156111f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e9906151e7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763db50e575606b6000606a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff1661ffff168152602001908152602001600020606960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1689898989896040518863ffffffff1660e01b81526004016112be9796959493929190615267565b60006040518083038186803b1580156112d657600080fd5b505af41580156112ea573d6000803e3d6000fd5b5050505061133e868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505085613010565b905095945050505050565b611351613008565b73ffffffffffffffffffffffffffffffffffffffff1661136f612057565b73ffffffffffffffffffffffffffffffffffffffff16146113c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bc906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763cfe4317a606b60008561ffff1661ffff16815260200190815260200160002084846040518463ffffffff1660e01b815260040161141a939291906152d1565b60006040518083038186803b15801561143257600080fd5b505af4158015611446573d6000803e3d6000fd5b505050505050565b60006060600073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611521576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611518906151e7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763db50e575606b6000606a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900461ffff1661ffff1661ffff168152602001908152602001600020606960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a8a8a8a8a6040518863ffffffff1660e01b81526004016115ed9796959493929190615267565b60006040518083038186803b15801561160557600080fd5b505af4158015611619573d6000803e3d6000fd5b5050505061166d878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505086613305565b915091509550959350505050565b606660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6116a9613008565b73ffffffffffffffffffffffffffffffffffffffff166116c7612057565b73ffffffffffffffffffffffffffffffffffffffff161461171d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611714906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763ee54ca53606b60008561ffff1661ffff16815260200190815260200160002084846040518463ffffffff1660e01b8152600401611772939291906152d1565b60006040518083038186803b15801561178a57600080fd5b505af415801561179e573d6000803e3d6000fd5b505050505050565b6117ae613008565b73ffffffffffffffffffffffffffffffffffffffff166117cc612057565b73ffffffffffffffffffffffffffffffffffffffff1614611822576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611819906151c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561188c5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6118cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c290615247565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161199090615227565b60405180910390fd5b60686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844081604051611b259190614f16565b60405180910390a150565b60008073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611c00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf7906151e7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763db50e575606b60008661ffff1661ffff168152602001908152602001600020606960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b6040518863ffffffff1660e01b8152600401611c7f9796959493929190615267565b60006040518083038186803b158015611c9757600080fd5b505af4158015611cab573d6000803e3d6000fd5b50505050611cff888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505087613010565b9050818015611d0c575080155b15611d43576040517fd27b44a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b979650505050505050565b611d56613008565b73ffffffffffffffffffffffffffffffffffffffff16611d74612057565b73ffffffffffffffffffffffffffffffffffffffff1614611dca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc1906151c7565b60405180910390fd5b611dd46000613609565b565b611dde613008565b73ffffffffffffffffffffffffffffffffffffffff16611dfc612057565b73ffffffffffffffffffffffffffffffffffffffff1614611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e49906151c7565b60405180910390fd5b6000606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f90cc2f570a6eb594b1580ea3e41247d2d73a55281889e86bd4ec2fc29c7e62d660405160405180910390a35050565b606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611f46613008565b73ffffffffffffffffffffffffffffffffffffffff16611f64612057565b73ffffffffffffffffffffffffffffffffffffffff1614611fba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb1906151c7565b60405180910390fd5b80606960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f5fe6aabf4e790843df43ae0e22b58620066fb389295bedc06a92df6c3b28777d606960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405161204c9190614f16565b60405180910390a150565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612089613008565b73ffffffffffffffffffffffffffffffffffffffff166120a7612057565b73ffffffffffffffffffffffffffffffffffffffff16146120fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120f4906151c7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763512ce0f2606b60008a61ffff1661ffff168152602001908152602001600020898989898989896040518963ffffffff1660e01b815260040161215c98979695949392919061544f565b60006040518083038186803b15801561217457600080fd5b505af4158015612188573d6000803e3d6000fd5b5050505050505050505050565b6000806000838060200190518101906121ae9190613f8b565b9250925092506121bc6136cf565b81606660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080606760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061224783612f10565b61224f6137b8565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f34d3b96a088381c6843a1f9d94d251afa88f83cc7a0d17fc23a7057506a3fc6d846040516122c39190614f16565b60405180910390a450505050565b6122d9613008565b73ffffffffffffffffffffffffffffffffffffffff166122f7612057565b73ffffffffffffffffffffffffffffffffffffffff161461234d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612344906151c7565b60405180910390fd5b81819050848490501461238c576040517f74f4d53700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b848490508161ffff16101561247a5782828261ffff168181106123b5576123b4615b73565b5b90506020020160208101906123ca919061426a565b606b600087878561ffff168181106123e5576123e4615b73565b5b90506020020160208101906123fa9190614369565b61ffff1661ffff16815260200190815260200160002060000160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550808061247290615aa1565b91505061238f565b5061248485610c03565b61249257612491856117a6565b5b7f4dcd99505817a4d3e4d3f751a4a49739ec38cb0f83319ff1224a3b289597e86c85858585856040516124c9959493929190614f31565b60405180910390a15050505050565b60006060600073ffffffffffffffffffffffffffffffffffffffff16606860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156125ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a2906151e7565b60405180910390fd5b7333d1c5a5b6a7f3885c7467e829aaa2169893759763db50e575606b60008761ffff1661ffff168152602001908152602001600020606960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c6040518863ffffffff1660e01b815260040161262a9796959493929190615267565b60006040518083038186803b15801561264257600080fd5b505af4158015612656573d6000803e3d6000fd5b505050506126aa898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505088613305565b80925081935050508280156126bd575081155b156126f4576040517fd27b44a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b97509795505050505050565b6000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008267ffffffffffffffff81111561274857612747615ba2565b5b6040519080825280602002602001820160405280156127765781602001602082028036833780820191505090505b509150600080606860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128495750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561285457508482105b1561291c578084838151811061286d5761286c615b73565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050818061291490615acc565b9250506127df565b80925081845250509250929050565b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b612959613008565b73ffffffffffffffffffffffffffffffffffffffff16612977612057565b73ffffffffffffffffffffffffffffffffffffffff16146129cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c4906151c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612a375750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b612a76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a6d90615247565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612b43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3a90615167565b60405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16606860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427681604051612cce9190614f16565b60405180910390a15050565b612ce2613008565b73ffffffffffffffffffffffffffffffffffffffff16612d00612057565b73ffffffffffffffffffffffffffffffffffffffff1614612d56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4d906151c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612e73578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401612de3919061514c565b60206040518083038186803b158015612dfb57600080fd5b505afa158015612e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e339190614297565b612e72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6990615207565b60405180910390fd5b5b80606560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa2606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051612f059190614f16565b60405180910390a150565b612f18613008565b73ffffffffffffffffffffffffffffffffffffffff16612f36612057565b73ffffffffffffffffffffffffffffffffffffffff1614612f8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f83906151c7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612ffc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ff390615187565b60405180910390fd5b61300581613609565b50565b600033905090565b60008073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461314257606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166375f0bb528686868660008060008060006040518060400160405280600281526020017f307800000000000000000000000000000000000000000000000000000000000081525060006040518c63ffffffff1660e01b815260040161310f9b9a99989796959493929190614fef565b600060405180830381600087803b15801561312957600080fd5b505af115801561313d573d6000803e3d6000fd5b505050505b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663468721a7868686866040518563ffffffff1660e01b81526004016131a39493929190614fa3565b602060405180830381600087803b1580156131bd57600080fd5b505af11580156131d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f59190614297565b9050600073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146132fd57606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663932713687f3078000000000000000000000000000000000000000000000000000000000000836040518363ffffffff1660e01b81526004016132ca929190615123565b600060405180830381600087803b1580156132e457600080fd5b505af11580156132f8573d6000803e3d6000fd5b505050505b949350505050565b60006060600073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461343a57606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166375f0bb528787878760008060008060006040518060400160405280600281526020017f307800000000000000000000000000000000000000000000000000000000000081525060006040518c63ffffffff1660e01b81526004016134079b9a99989796959493929190614fef565b600060405180830381600087803b15801561342157600080fd5b505af1158015613435573d6000803e3d6000fd5b505050505b606760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635229073f878787876040518563ffffffff1660e01b815260040161349b9493929190614fa3565b600060405180830381600087803b1580156134b557600080fd5b505af11580156134c9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906134f291906142c4565b8092508193505050600073ffffffffffffffffffffffffffffffffffffffff16606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461360057606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663932713687f3078000000000000000000000000000000000000000000000000000000000000846040518363ffffffff1660e01b81526004016135cd929190615123565b600060405180830381600087803b1580156135e757600080fd5b505af11580156135fb573d6000803e3d6000fd5b505050505b94509492505050565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600060019054906101000a900460ff16806136f5575060008054906101000a900460ff16155b613734576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372b906151a7565b60405180910390fd5b60008060019054906101000a900460ff161590508015613784576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b61378c613900565b6137946139d9565b80156137b55760008060016101000a81548160ff0219169083151502179055505b50565b600073ffffffffffffffffffffffffffffffffffffffff1660686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461387e576040517ff736703400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160686000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600060019054906101000a900460ff1680613926575060008054906101000a900460ff16155b613965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161395c906151a7565b60405180910390fd5b60008060019054906101000a900460ff1615905080156139b5576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b80156139d65760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff16806139ff575060008054906101000a900460ff16155b613a3e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a35906151a7565b60405180910390fd5b60008060019054906101000a900460ff161590508015613a8e576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b613a9e613a99613008565b613609565b8015613abf5760008060016101000a81548160ff0219169083151502179055505b50565b6000613ad5613ad084615626565b615601565b90508083825260208201905082856020860282011115613af857613af7615be5565b5b60005b85811015613b4657813567ffffffffffffffff811115613b1e57613b1d615bdb565b5b808601613b2b8982613e6f565b85526020850194506020840193505050600181019050613afb565b5050509392505050565b6000613b63613b5e84615652565b615601565b905082815260208101848484011115613b7f57613b7e615bea565b5b613b8a848285615a2e565b509392505050565b6000613ba5613ba084615652565b615601565b905082815260208101848484011115613bc157613bc0615bea565b5b613bcc848285615a3d565b509392505050565b600081359050613be381615df3565b92915050565b600081519050613bf881615e0a565b92915050565b60008083601f840112613c1457613c13615bdb565b5b8235905067ffffffffffffffff811115613c3157613c30615bd6565b5b602083019150836020820283011115613c4d57613c4c615be5565b5b9250929050565b60008083601f840112613c6a57613c69615bdb565b5b8235905067ffffffffffffffff811115613c8757613c86615bd6565b5b602083019150836020820283011115613ca357613ca2615be5565b5b9250929050565b600082601f830112613cbf57613cbe615bdb565b5b8135613ccf848260208601613ac2565b91505092915050565b60008083601f840112613cee57613ced615bdb565b5b8235905067ffffffffffffffff811115613d0b57613d0a615bd6565b5b602083019150836020820283011115613d2757613d26615be5565b5b9250929050565b60008083601f840112613d4457613d43615bdb565b5b8235905067ffffffffffffffff811115613d6157613d60615bd6565b5b602083019150836020820283011115613d7d57613d7c615be5565b5b9250929050565b60008083601f840112613d9a57613d99615bdb565b5b8235905067ffffffffffffffff811115613db757613db6615bd6565b5b602083019150836020820283011115613dd357613dd2615be5565b5b9250929050565b600081359050613de981615e21565b92915050565b600081519050613dfe81615e21565b92915050565b600081359050613e1381615e38565b92915050565b60008083601f840112613e2f57613e2e615bdb565b5b8235905067ffffffffffffffff811115613e4c57613e4b615bd6565b5b602083019150836001820283011115613e6857613e67615be5565b5b9250929050565b600082601f830112613e8457613e83615bdb565b5b8135613e94848260208601613b50565b91505092915050565b600082601f830112613eb257613eb1615bdb565b5b8151613ec2848260208601613b92565b91505092915050565b600081359050613eda81615e4f565b92915050565b600081359050613eef81615e5f565b92915050565b600081359050613f0481615e6f565b92915050565b600081359050613f1981615e7f565b92915050565b600081359050613f2e81615e8f565b92915050565b600081359050613f4381615ea6565b92915050565b600081359050613f5881615ebd565b92915050565b600060208284031215613f7457613f73615bf9565b5b6000613f8284828501613bd4565b91505092915050565b600080600060608486031215613fa457613fa3615bf9565b5b6000613fb286828701613be9565b9350506020613fc386828701613be9565b9250506040613fd486828701613be9565b9150509250925092565b60008060408385031215613ff557613ff4615bf9565b5b600061400385828601613bd4565b925050602061401485828601613bd4565b9150509250929050565b60008060008060006060868803121561403a57614039615bf9565b5b600061404888828901613bd4565b955050602086013567ffffffffffffffff81111561406957614068615bef565b5b61407588828901613d84565b9450945050604086013567ffffffffffffffff81111561409857614097615bef565b5b6140a488828901613bfe565b92509250509295509295909350565b600080604083850312156140ca576140c9615bf9565b5b60006140d885828601613bd4565b92505060206140e985828601613f1f565b9150509250929050565b6000806040838503121561410a57614109615bf9565b5b600061411885828601613bd4565b925050602061412985828601613f34565b9150509250929050565b60008060008060006080868803121561414f5761414e615bf9565b5b600061415d88828901613bd4565b955050602061416e88828901613f34565b945050604086013567ffffffffffffffff81111561418f5761418e615bef565b5b61419b88828901613e19565b935093505060606141ae88828901613ef5565b9150509295509295909350565b600080600080600080600060c0888a0312156141da576141d9615bf9565b5b60006141e88a828b01613bd4565b97505060206141f98a828b01613f34565b965050604088013567ffffffffffffffff81111561421a57614219615bef565b5b6142268a828b01613e19565b955095505060606142398a828b01613ef5565b935050608061424a8a828b01613f1f565b92505060a061425b8a828b01613dda565b91505092959891949750929550565b6000602082840312156142805761427f615bf9565b5b600061428e84828501613dda565b91505092915050565b6000602082840312156142ad576142ac615bf9565b5b60006142bb84828501613def565b91505092915050565b600080604083850312156142db576142da615bf9565b5b60006142e985828601613def565b925050602083015167ffffffffffffffff81111561430a57614309615bef565b5b61431685828601613e9d565b9150509250929050565b60006020828403121561433657614335615bf9565b5b600082013567ffffffffffffffff81111561435457614353615bef565b5b61436084828501613e6f565b91505092915050565b60006020828403121561437f5761437e615bf9565b5b600061438d84828501613f1f565b91505092915050565b600080604083850312156143ad576143ac615bf9565b5b60006143bb85828601613f1f565b92505060206143cc85828601613bd4565b9150509250929050565b6000806000606084860312156143ef576143ee615bf9565b5b60006143fd86828701613f1f565b935050602061440e86828701613bd4565b925050604061441f86828701613e04565b9150509250925092565b60008060008060008060008060008060006101008c8e03121561444f5761444e615bf9565b5b600061445d8e828f01613f1f565b9b5050602061446e8e828f01613bd4565b9a5050604061447f8e828f01613e04565b99505060608c013567ffffffffffffffff8111156144a05761449f615bef565b5b6144ac8e828f01613bfe565b985098505060808c013567ffffffffffffffff8111156144cf576144ce615bef565b5b6144db8e828f01613d2e565b965096505060a08c013567ffffffffffffffff8111156144fe576144fd615bef565b5b61450a8e828f01613cd8565b945094505060c08c013567ffffffffffffffff81111561452d5761452c615bef565b5b6145398e828f01613caa565b92505060e061454a8e828f01613ee0565b9150509295989b509295989b9093969950565b6000806000806080858703121561457757614576615bf9565b5b600061458587828801613f1f565b945050602061459687828801613bd4565b93505060406145a787828801613e04565b92505060606145b887828801613ee0565b91505092959194509250565b600080600080600080600060c0888a0312156145e3576145e2615bf9565b5b60006145f18a828b01613f1f565b97505060206146028a828b01613bd4565b96505060406146138a828b01613e04565b95505060606146248a828b01613f34565b94505060806146358a828b01613f0a565b93505060a088013567ffffffffffffffff81111561465657614655615bef565b5b6146628a828b01613c54565b925092505092959891949750929550565b60008060008060008060008060e0898b03121561469357614692615bf9565b5b60006146a18b828c01613f1f565b98505060206146b28b828c01613bd4565b97505060406146c38b828c01613e04565b96505060606146d48b828c01613f34565b95505060806146e58b828c01613f0a565b94505060a06146f68b828c01613ecb565b93505060c089013567ffffffffffffffff81111561471757614716615bef565b5b6147238b828c01613e19565b92509250509295985092959890939650565b6000806000806080858703121561474f5761474e615bf9565b5b600061475d87828801613f1f565b945050602061476e87828801613bd4565b935050604061477f87828801613e04565b925050606061479087828801613f49565b91505092959194509250565b6000806000606084860312156147b5576147b4615bf9565b5b60006147c386828701613f1f565b93505060206147d486828701613bd4565b92505060406147e586828701613ee0565b9150509250925092565b60006147fb83836148b8565b60208301905092915050565b60006148138383614bff565b60208301905092915050565b600061482b8383614c1d565b60208301905092915050565b6000614844848484614c86565b90509392505050565b60006148598383614cec565b905092915050565b600061486d8383614d34565b60208301905092915050565b60006148858383614d7f565b60208301905092915050565b600061489d8383614ebc565b60208301905092915050565b6148b2816158dd565b82525050565b6148c1816158cb565b82525050565b6148d0816158cb565b82525050565b6148df816158cb565b82525050565b60006148f0826156d5565b6148fa8185615751565b935061490583615683565b8060005b8381101561493657815161491d88826147ef565b9750614928836156f6565b925050600181019050614909565b5085935050505092915050565b600061494f8385615762565b935061495a82615693565b8060005b8581101561499357614970828461580c565b61497a8882614807565b975061498583615703565b92505060018101905061495e565b5085925050509392505050565b60006149ac8385615773565b93506149b782615693565b8060005b858110156149f0576149cd828461580c565b6149d7888261481f565b97506149e283615703565b9250506001810190506149bb565b5085925050509392505050565b6000614a098385615784565b935083602084028501614a1b8461569d565b8060005b87811015614a61578484038952614a368284615823565b614a41868284614837565b9550614a4c84615710565b935060208b019a505050600181019050614a1f565b50829750879450505050509392505050565b6000614a7e826156e0565b614a888185615784565b935083602082028501614a9a856156a7565b8060005b85811015614ad65784840389528151614ab7858261484d565b9450614ac28361571d565b925060208a01995050600181019050614a9e565b50829750879550505050505092915050565b6000614af48385615795565b9350614aff826156b7565b8060005b85811015614b3857614b158284615886565b614b1f8882614861565b9750614b2a8361572a565b925050600181019050614b03565b5085925050509392505050565b6000614b5183856157a6565b9350614b5c826156c1565b8060005b85811015614b9557614b72828461589d565b614b7c8882614879565b9750614b8783615737565b925050600181019050614b60565b5085925050509392505050565b6000614bae83856157b7565b9350614bb9826156cb565b8060005b85811015614bf257614bcf82846158b4565b614bd98882614891565b9750614be483615744565b925050600181019050614bbd565b5085925050509392505050565b614c08816158ef565b82525050565b614c17816158ef565b82525050565b614c26816158ef565b82525050565b614c35816158fb565b82525050565b614c4481615905565b82525050565b614c5381615905565b82525050565b6000614c6583856157d9565b9350614c72838584615a2e565b614c7b83615bfe565b840190509392505050565b6000614c9283856157ea565b9350614c9f838584615a2e565b614ca883615bfe565b840190509392505050565b6000614cbe826156eb565b614cc881856157c8565b9350614cd8818560208601615a3d565b614ce181615bfe565b840191505092915050565b6000614cf7826156eb565b614d0181856157ea565b9350614d11818560208601615a3d565b614d1a81615bfe565b840191505092915050565b614d2e816159c2565b82525050565b614d3d816159c2565b82525050565b614d4c816159d4565b82525050565b614d5b816159e6565b82525050565b614d6a816159e6565b82525050565b614d79816159f8565b82525050565b614d88816159f8565b82525050565b614d9781615a0a565b82525050565b6000614daa6017836157fb565b9150614db582615c0f565b602082019050919050565b6000614dcd6026836157fb565b9150614dd882615c38565b604082019050919050565b6000614df0602e836157fb565b9150614dfb82615c87565b604082019050919050565b6000614e136020836157fb565b9150614e1e82615cd6565b602082019050919050565b6000614e366015836157fb565b9150614e4182615cff565b602082019050919050565b6000614e596020836157fb565b9150614e6482615d28565b602082019050919050565b6000614e7c6016836157fb565b9150614e8782615d51565b602082019050919050565b6000614e9f600e836157fb565b9150614eaa82615d7a565b602082019050919050565b8082525050565b614ec58161597d565b82525050565b614ed48161597d565b82525050565b614ee38161597d565b82525050565b614ef2816159ab565b82525050565b614f01816159ab565b82525050565b614f1081615a1c565b82525050565b6000602082019050614f2b60008301846148c7565b92915050565b6000606082019050614f4660008301886148c7565b8181036020830152614f59818688614ba2565b90508181036040830152614f6e818486614943565b90509695505050505050565b6000604082019050614f8f60008301856148c7565b614f9c6020830184614ecb565b9392505050565b6000608082019050614fb860008301876148c7565b614fc56020830186614ee9565b8181036040830152614fd78185614cb3565b9050614fe66060830184614d52565b95945050505050565b600061016082019050615005600083018e6148c7565b615012602083018d614ee9565b8181036040830152615024818c614cb3565b9050615033606083018b614d52565b615040608083018a614d8e565b61504d60a0830189614d8e565b61505a60c0830188614d8e565b61506760e08301876148c7565b6150756101008301866148a9565b8181036101208301526150888185614cb3565b90506150986101408301846148c7565b9c9b505050505050505050505050565b600060408201905081810360008301526150c281856148e5565b90506150d160208301846148c7565b9392505050565b60006020820190506150ed6000830184614c0e565b92915050565b60006040820190506151086000830185614c0e565b818103602083015261511a8184614cb3565b90509392505050565b60006040820190506151386000830185614c2c565b6151456020830184614c0e565b9392505050565b60006020820190506151616000830184614c3b565b92915050565b6000602082019050818103600083015261518081614d9d565b9050919050565b600060208201905081810360008301526151a081614dc0565b9050919050565b600060208201905081810360008301526151c081614de3565b9050919050565b600060208201905081810360008301526151e081614e06565b9050919050565b6000602082019050818103600083015261520081614e29565b9050919050565b6000602082019050818103600083015261522081614e4c565b9050919050565b6000602082019050818103600083015261524081614e6f565b9050919050565b6000602082019050818103600083015261526081614e92565b9050919050565b600060c08201905061527c600083018a614eb5565b61528960208301896148d6565b61529660408301886148d6565b6152a36060830187614ef8565b81810360808301526152b6818587614c59565b90506152c560a0830184614d61565b98975050505050505050565b60006060820190506152e66000830186614eb5565b6152f36020830185614eda565b61530060408301846148d6565b949350505050565b600060808201905061531d6000830187614eb5565b61532a6020830186614eda565b61533760408301856148d6565b6153446060830184614c4a565b95945050505050565b600061012082019050615363600083018f614eb5565b615370602083018e614eda565b61537d604083018d6148d6565b61538a606083018c614c4a565b818103608083015261539d818a8c6149a0565b905081810360a08301526153b281888a614b45565b905081810360c08301526153c7818688614ae8565b905081810360e08301526153db8185614a73565b90506153eb610100830184614d43565b9d9c50505050505050505050505050565b600060a0820190506154116000830188614eb5565b61541e6020830187614eda565b61542b60408301866148d6565b6154386060830185614c4a565b6154456080830184614d43565b9695505050505050565b600060e082019050615464600083018b614eb5565b615471602083018a614eda565b61547e60408301896148d6565b61548b6060830188614c4a565b6154986080830187614ef8565b6154a560a0830186614d70565b81810360c08301526154b88184866149fd565b90509998505050505050505050565b6000610100820190506154dd600083018c614eb5565b6154ea602083018b614eda565b6154f7604083018a6148d6565b6155046060830189614c4a565b6155116080830188614ef8565b61551e60a0830187614d70565b61552b60c0830186614d25565b81810360e083015261553e818486614c59565b90509a9950505050505050505050565b600060a0820190506155636000830188614eb5565b6155706020830187614eda565b61557d60408301866148d6565b61558a6060830185614c4a565b6155976080830184614f07565b9695505050505050565b60006080820190506155b66000830187614eb5565b6155c36020830186614eda565b6155d060408301856148d6565b6155dd6060830184614d43565b95945050505050565b60006020820190506155fb6000830184614ecb565b92915050565b600061560b61561c565b90506156178282615a70565b919050565b6000604051905090565b600067ffffffffffffffff82111561564157615640615ba2565b5b602082029050602081019050919050565b600067ffffffffffffffff82111561566d5761566c615ba2565b5b61567682615bfe565b9050602081019050919050565b6000819050602082019050919050565b6000819050919050565b6000819050919050565b6000819050602082019050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600061581b6020840184613dda565b905092915050565b600080833560016020038436030381126158405761583f615bf4565b5b83810192508235915060208301925067ffffffffffffffff82111561586857615867615bd1565b5b60018202360384131561587e5761587d615be0565b5b509250929050565b60006158956020840184613ecb565b905092915050565b60006158ac6020840184613f0a565b905092915050565b60006158c36020840184613f1f565b905092915050565b60006158d68261598b565b9050919050565b60006158e88261598b565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061593f82615da3565b919050565b600081905061595282615db7565b919050565b600081905061596582615dcb565b919050565b600081905061597882615ddf565b919050565b600061ffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60006159cd82615931565b9050919050565b60006159df82615944565b9050919050565b60006159f182615957565b9050919050565b6000615a038261596a565b9050919050565b6000615a15826159ab565b9050919050565b6000615a27826159b5565b9050919050565b82818337600083830152505050565b60005b83811015615a5b578082015181840152602081019050615a40565b83811115615a6a576000848401525b50505050565b615a7982615bfe565b810181811067ffffffffffffffff82111715615a9857615a97615ba2565b5b80604052505050565b6000615aac8261597d565b915061ffff821415615ac157615ac0615b15565b5b600182019050919050565b6000615ad7826159ab565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615b0a57615b09615b15565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4d6f64756c6520616c72656164792064697361626c6564000000000000000000600082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f4d6f64756c65206e6f7420617574686f72697a65640000000000000000000000600082015250565b7f477561726420646f6573206e6f7420696d706c656d656e742049455243313635600082015250565b7f4d6f64756c6520616c726561647920656e61626c656400000000000000000000600082015250565b7f496e76616c6964206d6f64756c65000000000000000000000000000000000000600082015250565b60048110615db457615db3615b44565b5b50565b60048110615dc857615dc7615b44565b5b50565b60028110615ddc57615ddb615b44565b5b50565b60038110615df057615def615b44565b5b50565b615dfc816158cb565b8114615e0757600080fd5b50565b615e13816158dd565b8114615e1e57600080fd5b50565b615e2a816158ef565b8114615e3557600080fd5b50565b615e4181615905565b8114615e4c57600080fd5b50565b60048110615e5c57600080fd5b50565b60048110615e6c57600080fd5b50565b60028110615e7c57600080fd5b50565b60038110615e8c57600080fd5b50565b615e988161597d565b8114615ea357600080fd5b50565b615eaf816159ab565b8114615eba57600080fd5b50565b615ec6816159b5565b8114615ed157600080fd5b5056fea26469706673582212201b02673520ea9284b2f57287bb54a9784eae9a7d7b2ce9eb5f58478be826f60064736f6c63430008060033000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"; From 0b04d6c1b73ee42f7f745ef490b07cfbe61fb9a9 Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Fri, 29 Sep 2023 12:30:32 +0200 Subject: [PATCH 06/82] format --- sdk/factory/moduleDeployer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/factory/moduleDeployer.ts b/sdk/factory/moduleDeployer.ts index 3e27852c..9f055f06 100644 --- a/sdk/factory/moduleDeployer.ts +++ b/sdk/factory/moduleDeployer.ts @@ -1,5 +1,6 @@ import { Provider } from "@ethersproject/providers"; import { ethers, Contract, Signer, BigNumber } from "ethers"; +import { KnownContracts } from "./types"; import { ContractAddresses, ContractAbis, @@ -8,8 +9,6 @@ import { } from "../contracts"; import { ModuleProxyFactory__factory } from "../types"; -import { KnownContracts } from "./types"; - type ABI = any[] | readonly any[]; type TxAndExpectedAddress = { From 555d7ece02e219962fa78931f27baf958cf5c3e0 Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Fri, 29 Sep 2023 12:30:51 +0200 Subject: [PATCH 07/82] bump patch --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7a001a59..facb29b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.3.9", + "version": "3.3.10", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", @@ -93,4 +93,4 @@ "@openzeppelin/contracts-upgradeable": "^4.8.1", "ethers": "^5.7.1" } -} +} \ No newline at end of file From 786a799fe0f891978a406b34f02dba7c417af79e Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 01:09:58 +0200 Subject: [PATCH 08/82] First crack at the base class that does the EIP712 appended signature split and extraction --- contracts/signature/Eip712Signature.sol | 86 +++++++++++++++++++ contracts/test/TestSignature.sol | 18 ++++ test/06_Eip712Signature.spec.ts | 107 ++++++++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 contracts/signature/Eip712Signature.sol create mode 100644 contracts/test/TestSignature.sol create mode 100644 test/06_Eip712Signature.spec.ts diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol new file mode 100644 index 00000000..d563ce9d --- /dev/null +++ b/contracts/signature/Eip712Signature.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +abstract contract Eip712Signature { + uint256 private nonce; + + function eip712Nonce() internal returns (uint256 signed) { + return nonce; + } + + function eip712Increment() internal { + nonce = nonce + 1; + } + + function eip712SignedBy() internal returns (address signer) { + if (msg.data.length >= 4 + 65) { + ( + bytes calldata dataTrimmed, + uint8 v, + bytes32 r, + bytes32 s + ) = signatureSplit(msg.data); + + bytes32 txHash = transactionHash(msg.value, dataTrimmed, nonce); + + signer = ecrecover(txHash, v, r, s); + } + } + + function signatureSplit( + bytes calldata data + ) + internal + pure + returns (bytes calldata dataTrimmed, uint8 v, bytes32 r, bytes32 s) + { + uint256 length = data.length; + dataTrimmed = data[0:data.length - 65]; + r = bytes32(data[length - 65:]); + s = bytes32(data[length - 33:]); + v = uint8(bytes1(data[length - 1:])); + } + + // keccak256( + // "EIP712Domain(uint256 chainId,address verifyingContract)" + // ); + bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = + 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; + + // keccak256( + // "Transaction(uint256 value,bytes data,uint256 nonce)" + // ); + bytes32 private constant TRANSACTION_TYPEHASH = + 0x04c518a746e9715fde6a6d3ebdf678ea51c6d591b95e35d73b7e312afa44dd71; + + function transactionHash( + uint256 value, + bytes calldata data, + uint256 _nonce + ) private view returns (bytes32) { + uint256 chainId; + assembly { + chainId := chainid() + } + + bytes32 domainSeparator = keccak256( + abi.encode(DOMAIN_SEPARATOR_TYPEHASH, chainId, this) + ); + return + keccak256( + abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + domainSeparator, + keccak256( + abi.encode( + TRANSACTION_TYPEHASH, + value, + keccak256(data), + _nonce + ) + ) + ) + ); + } +} diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol new file mode 100644 index 00000000..8aca7f68 --- /dev/null +++ b/contracts/test/TestSignature.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0; + +import "../signature/Eip712Signature.sol"; + +contract TestSignature is Eip712Signature { + event Hello(address signer); + + event Goodbye(address signer); + + function hello() public { + emit Hello(eip712SignedBy()); + } + + function goodbye(uint256, bytes memory) public { + emit Goodbye(eip712SignedBy()); + } +} diff --git a/test/06_Eip712Signature.spec.ts b/test/06_Eip712Signature.spec.ts new file mode 100644 index 00000000..8a4d82bd --- /dev/null +++ b/test/06_Eip712Signature.spec.ts @@ -0,0 +1,107 @@ +import hre from "hardhat"; +import { TestSignature__factory } from "../typechain-types"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import { BigNumberish, PopulatedTransaction } from "ethers"; +import { expect } from "chai"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; + +describe("Eip712Signature", async () => { + async function setup() { + const [signer, relayer] = await hre.ethers.getSigners(); + const TestSignature = await hre.ethers.getContractFactory("TestSignature"); + const testSignature = await TestSignature.deploy(); + + return { + testSignature: TestSignature__factory.connect( + testSignature.address, + relayer + ), + signer, + relayer, + }; + } + + const AddressZero = "0x0000000000000000000000000000000000000000"; + + it("correctly detects an appended signature, for an entrypoint no arguments", async () => { + const { testSignature, signer, relayer } = await loadFixture(setup); + + const transaction = await testSignature.populateTransaction.hello(); + const signature = await sign(testSignature.address, transaction, signer); + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(signer.address); + }); + + it("correctly detects an appended signature, entrypoint with arguments", async () => { + const { testSignature, signer, relayer } = await loadFixture(setup); + + const transaction = await testSignature.populateTransaction.goodbye( + 0, + "0xbadfed" + ); + const signature = await sign(testSignature.address, transaction, signer); + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(signer.address); + }); +}); + +async function sign( + contract: string, + transaction: PopulatedTransaction, + signer: SignerWithAddress +) { + const { domain, types, message } = typedDataForTransaction( + { contract, chainId: 31337, nonce: 0 }, + { value: transaction.value || 0, data: transaction.data || "0x" } + ); + return await signer._signTypedData(domain, types, message); +} + +function typedDataForTransaction( + { + contract, + chainId, + nonce, + }: { + contract: string; + chainId: BigNumberish; + nonce: BigNumberish; + }, + { value, data }: { value: BigNumberish; data: string } +) { + const domain = { verifyingContract: contract, chainId }; + const types = { + Transaction: [ + { type: "uint256", name: "value" }, + { type: "bytes", name: "data" }, + { type: "uint256", name: "nonce" }, + ], + }; + const message = { + value, + data, + nonce, + }; + + return { domain, types, message }; +} From 0e0fb8ef7185a025bf302f1ba73aa62751019612 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 02:05:05 +0200 Subject: [PATCH 09/82] Include EIP712 signature auth logic into Modifier.sol, This new module auth mode is backwards compatible, and transparent with respect to current module ABIs --- contracts/core/Modifier.sol | 18 ++++- contracts/signature/Eip712Signature.sol | 6 +- contracts/test/TestSignature.sol | 4 +- test/03_Modifier.spec.ts | 101 +++++++++++++++++++++++- test/06_Eip712Signature.spec.ts | 35 +------- test/typesDataForTransaction.ts | 30 +++++++ 6 files changed, 154 insertions(+), 40 deletions(-) create mode 100644 test/typesDataForTransaction.ts diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index e992e552..3456d182 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -3,10 +3,11 @@ /// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. pragma solidity >=0.7.0 <0.9.0; -import "../interfaces/IAvatar.sol"; import "./Module.sol"; +import "../interfaces/IAvatar.sol"; +import "../signature/EIP712Signature.sol"; -abstract contract Modifier is Module, IAvatar { +abstract contract Modifier is Module, IAvatar, EIP712Signature { address internal constant SENTINEL_MODULES = address(0x1); /// Mapping of modules. mapping(address => address) internal modules; @@ -73,7 +74,18 @@ abstract contract Modifier is Module, IAvatar { */ modifier moduleOnly() { - if (modules[msg.sender] == address(0)) revert NotAuthorized(msg.sender); + bool wasSent = modules[msg.sender] != address(0); + bool wasSigned = !wasSent && modules[eip712SignedBy()] != address(0); + bool isAuthorized = wasSent || wasSigned; + + if (!isAuthorized) { + revert NotAuthorized(msg.sender); + } + + if (wasSigned) { + eip712NextNonce(); + } + _; } diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index d563ce9d..a4aa9ee6 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -abstract contract Eip712Signature { +abstract contract EIP712Signature { uint256 private nonce; - function eip712Nonce() internal returns (uint256 signed) { + function eip712Nonce() public returns (uint256 signed) { return nonce; } - function eip712Increment() internal { + function eip712NextNonce() internal { nonce = nonce + 1; } diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index 8aca7f68..a5e94de8 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0; -import "../signature/Eip712Signature.sol"; +import "../signature/EIP712Signature.sol"; -contract TestSignature is Eip712Signature { +contract TestSignature is EIP712Signature { event Hello(address signer); event Goodbye(address signer); diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index dfef65e5..1324507f 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -2,7 +2,10 @@ import { AddressZero } from "@ethersproject/constants"; import { AddressOne } from "@gnosis.pm/safe-contracts"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; +import { PopulatedTransaction } from "ethers"; import hre from "hardhat"; +import typedDataForTransaction from "./typesDataForTransaction"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; @@ -291,7 +294,6 @@ describe("Modifier", async () => { .to.be.revertedWithCustomError(modifier, "NotAuthorized") .withArgs("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); }); - it("execute a transaction.", async () => { const { modifier, tx } = await loadFixture(setupTests); const [user1] = await hre.ethers.getSigners(); @@ -308,6 +310,48 @@ describe("Modifier", async () => { ) ).to.emit(modifier, "executed"); }); + it("execute a transaction with signature.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, user2, relayer] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModule( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const signatureOk = await sign(modifier.address, transaction, user1); + const signatureBad = await sign(modifier.address, transaction, user2); + + const transactionWithOkSig = { + ...transaction, + data: `${transaction.data}${signatureOk.slice(2)}`, + }; + + const transactionWithBadSig = { + ...transaction, + data: `${transaction.data}${signatureBad.slice(2)}`, + }; + + await expect(user1.sendTransaction(transaction)).to.emit( + modifier, + "executed" + ); + + await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( + modifier, + "executed" + ); + + await expect( + relayer.sendTransaction(transactionWithBadSig) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); + }); }); describe("execTransactionFromModuleReturnData", async () => { @@ -341,5 +385,60 @@ describe("Modifier", async () => { ) ).to.emit(modifier, "executedAndReturnedData"); }); + + it("execute a transaction with signature.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, user2, relayer] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModuleReturnData( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const signatureOk = await sign(modifier.address, transaction, user1); + const signatureBad = await sign(modifier.address, transaction, user2); + + const transactionWithOkSig = { + ...transaction, + data: `${transaction.data}${signatureOk.slice(2)}`, + }; + + const transactionWithBadSig = { + ...transaction, + data: `${transaction.data}${signatureBad.slice(2)}`, + }; + + await expect(user1.sendTransaction(transaction)).to.emit( + modifier, + "executedAndReturnedData" + ); + + await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( + modifier, + "executedAndReturnedData" + ); + + await expect( + relayer.sendTransaction(transactionWithBadSig) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); + }); }); }); + +async function sign( + contract: string, + transaction: PopulatedTransaction, + signer: SignerWithAddress +) { + const { domain, types, message } = typedDataForTransaction( + { contract, chainId: 31337, nonce: 0 }, + { value: transaction.value || 0, data: transaction.data || "0x" } + ); + return signer._signTypedData(domain, types, message); +} diff --git a/test/06_Eip712Signature.spec.ts b/test/06_Eip712Signature.spec.ts index 8a4d82bd..1018c4f1 100644 --- a/test/06_Eip712Signature.spec.ts +++ b/test/06_Eip712Signature.spec.ts @@ -1,11 +1,13 @@ import hre from "hardhat"; import { TestSignature__factory } from "../typechain-types"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; -import { BigNumberish, PopulatedTransaction } from "ethers"; +import { PopulatedTransaction } from "ethers"; import { expect } from "chai"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -describe("Eip712Signature", async () => { +import typedDataForTransaction from "./typesDataForTransaction"; + +describe("EIP712Signature", async () => { async function setup() { const [signer, relayer] = await hre.ethers.getSigners(); const TestSignature = await hre.ethers.getContractFactory("TestSignature"); @@ -76,32 +78,3 @@ async function sign( ); return await signer._signTypedData(domain, types, message); } - -function typedDataForTransaction( - { - contract, - chainId, - nonce, - }: { - contract: string; - chainId: BigNumberish; - nonce: BigNumberish; - }, - { value, data }: { value: BigNumberish; data: string } -) { - const domain = { verifyingContract: contract, chainId }; - const types = { - Transaction: [ - { type: "uint256", name: "value" }, - { type: "bytes", name: "data" }, - { type: "uint256", name: "nonce" }, - ], - }; - const message = { - value, - data, - nonce, - }; - - return { domain, types, message }; -} diff --git a/test/typesDataForTransaction.ts b/test/typesDataForTransaction.ts new file mode 100644 index 00000000..b95d3c4e --- /dev/null +++ b/test/typesDataForTransaction.ts @@ -0,0 +1,30 @@ +import { BigNumberish } from "ethers"; + +export default function typedDataForTransaction( + { + contract, + chainId, + nonce, + }: { + contract: string; + chainId: BigNumberish; + nonce: BigNumberish; + }, + { value, data }: { value: BigNumberish; data: string } +) { + const domain = { verifyingContract: contract, chainId }; + const types = { + Transaction: [ + { type: "uint256", name: "value" }, + { type: "bytes", name: "data" }, + { type: "uint256", name: "nonce" }, + ], + }; + const message = { + value, + data, + nonce, + }; + + return { domain, types, message }; +} From 2289d490a18c771f75d54fb3e7065b303030dbfd Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 02:26:05 +0200 Subject: [PATCH 10/82] Add tests ensuring Modifier is managing nonce correctly --- contracts/signature/Eip712Signature.sol | 2 +- test/03_Modifier.spec.ts | 58 +++++++++++++++++++++++++ test/06_Eip712Signature.spec.ts | 5 +++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index a4aa9ee6..4ce4067f 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0 <0.9.0; abstract contract EIP712Signature { uint256 private nonce; - function eip712Nonce() public returns (uint256 signed) { + function eip712Nonce() public view returns (uint256 signed) { return nonce; } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 1324507f..0fa15654 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -6,6 +6,7 @@ import { PopulatedTransaction } from "ethers"; import hre from "hardhat"; import typedDataForTransaction from "./typesDataForTransaction"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { TestModifier__factory } from "../typechain-types"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; @@ -352,6 +353,63 @@ describe("Modifier", async () => { relayer.sendTransaction(transactionWithBadSig) ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); }); + it("execute a transaction via sender nonce stays same.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + await expect( + modifier.execTransactionFromModule( + tx.to, + tx.value, + tx.data, + tx.operation + ) + ).to.emit(modifier, "executed"); + + expect( + await TestModifier__factory.connect( + modifier.address, + hre.ethers.provider + ).eip712Nonce() + ).to.equal(0); + }); + it("execute a transaction with signature nonce is incremented.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, user2, relayer] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModule( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const signature = await sign(modifier.address, transaction, user1); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(relayer.sendTransaction(transactionWithSig)).to.emit( + modifier, + "executed" + ); + + expect( + await TestModifier__factory.connect( + modifier.address, + hre.ethers.provider + ).eip712Nonce() + ).to.equal(1); + }); }); describe("execTransactionFromModuleReturnData", async () => { diff --git a/test/06_Eip712Signature.spec.ts b/test/06_Eip712Signature.spec.ts index 1018c4f1..444e320e 100644 --- a/test/06_Eip712Signature.spec.ts +++ b/test/06_Eip712Signature.spec.ts @@ -65,6 +65,11 @@ describe("EIP712Signature", async () => { .to.emit(testSignature, "Goodbye") .withArgs(signer.address); }); + + it("it publicly exposes the eip712 nonce", async () => { + const { testSignature } = await loadFixture(setup); + expect(await testSignature.eip712Nonce()).to.equal(0); + }); }); async function sign( From aa8b40c6139591e177f2de6aec2377639eb65003 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 03:04:34 +0200 Subject: [PATCH 11/82] Naming improvements --- contracts/core/Modifier.sol | 2 +- contracts/signature/Eip712Signature.sol | 38 ++++++++++++------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 3456d182..aa2b963c 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -83,7 +83,7 @@ abstract contract Modifier is Module, IAvatar, EIP712Signature { } if (wasSigned) { - eip712NextNonce(); + eip712BumpNonce(); } _; diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index 4ce4067f..2e5a0d1e 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -8,7 +8,7 @@ abstract contract EIP712Signature { return nonce; } - function eip712NextNonce() internal { + function eip712BumpNonce() internal { nonce = nonce + 1; } @@ -19,41 +19,29 @@ abstract contract EIP712Signature { uint8 v, bytes32 r, bytes32 s - ) = signatureSplit(msg.data); + ) = _splitSignature(msg.data); - bytes32 txHash = transactionHash(msg.value, dataTrimmed, nonce); + bytes32 txHash = _transactionHash(msg.value, dataTrimmed, nonce); signer = ecrecover(txHash, v, r, s); } } - function signatureSplit( + function _splitSignature( bytes calldata data ) - internal + private pure returns (bytes calldata dataTrimmed, uint8 v, bytes32 r, bytes32 s) { uint256 length = data.length; - dataTrimmed = data[0:data.length - 65]; + dataTrimmed = data[0:length - 65]; r = bytes32(data[length - 65:]); s = bytes32(data[length - 33:]); v = uint8(bytes1(data[length - 1:])); } - // keccak256( - // "EIP712Domain(uint256 chainId,address verifyingContract)" - // ); - bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = - 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; - - // keccak256( - // "Transaction(uint256 value,bytes data,uint256 nonce)" - // ); - bytes32 private constant TRANSACTION_TYPEHASH = - 0x04c518a746e9715fde6a6d3ebdf678ea51c6d591b95e35d73b7e312afa44dd71; - - function transactionHash( + function _transactionHash( uint256 value, bytes calldata data, uint256 _nonce @@ -83,4 +71,16 @@ abstract contract EIP712Signature { ) ); } + + // keccak256( + // "EIP712Domain(uint256 chainId,address verifyingContract)" + // ); + bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = + 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; + + // keccak256( + // "Transaction(uint256 value,bytes data,uint256 nonce)" + // ); + bytes32 private constant TRANSACTION_TYPEHASH = + 0x04c518a746e9715fde6a6d3ebdf678ea51c6d591b95e35d73b7e312afa44dd71; } From 01cdfeab7df77cee6d49326e9c1dab672cce5814 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 05:26:03 +0200 Subject: [PATCH 12/82] Use block.chainid instead of opening an assembley block --- contracts/signature/Eip712Signature.sol | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index 2e5a0d1e..8144020b 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -46,13 +46,8 @@ abstract contract EIP712Signature { bytes calldata data, uint256 _nonce ) private view returns (bytes32) { - uint256 chainId; - assembly { - chainId := chainid() - } - bytes32 domainSeparator = keccak256( - abi.encode(DOMAIN_SEPARATOR_TYPEHASH, chainId, this) + abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) ); return keccak256( From 5377f13638e84477bb24a3d5759e23f4afd309c6 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 05:34:52 +0200 Subject: [PATCH 13/82] Move moduleOnly only to more straigthforward shape --- contracts/core/Modifier.sol | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index aa2b963c..7b5a6c1b 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -74,15 +74,10 @@ abstract contract Modifier is Module, IAvatar, EIP712Signature { */ modifier moduleOnly() { - bool wasSent = modules[msg.sender] != address(0); - bool wasSigned = !wasSent && modules[eip712SignedBy()] != address(0); - bool isAuthorized = wasSent || wasSigned; - - if (!isAuthorized) { - revert NotAuthorized(msg.sender); - } - - if (wasSigned) { + if (modules[msg.sender] == address(0)) { + if (modules[eip712SignedBy()] == address(0)) { + revert NotAuthorized(msg.sender); + } eip712BumpNonce(); } From c0577f281f48afc21889af0cd3aa37da54c2b8aa Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 05:39:56 +0200 Subject: [PATCH 14/82] Signer should not define the relayer's message value. --- contracts/signature/Eip712Signature.sol | 8 +++----- test/03_Modifier.spec.ts | 3 ++- test/06_Eip712Signature.spec.ts | 2 +- test/typesDataForTransaction.ts | 4 +--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index 8144020b..8d6a8482 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -21,7 +21,7 @@ abstract contract EIP712Signature { bytes32 s ) = _splitSignature(msg.data); - bytes32 txHash = _transactionHash(msg.value, dataTrimmed, nonce); + bytes32 txHash = _transactionHash(dataTrimmed, nonce); signer = ecrecover(txHash, v, r, s); } @@ -42,7 +42,6 @@ abstract contract EIP712Signature { } function _transactionHash( - uint256 value, bytes calldata data, uint256 _nonce ) private view returns (bytes32) { @@ -58,7 +57,6 @@ abstract contract EIP712Signature { keccak256( abi.encode( TRANSACTION_TYPEHASH, - value, keccak256(data), _nonce ) @@ -74,8 +72,8 @@ abstract contract EIP712Signature { 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; // keccak256( - // "Transaction(uint256 value,bytes data,uint256 nonce)" + // "Transaction(bytes data,uint256 nonce)" // ); bytes32 private constant TRANSACTION_TYPEHASH = - 0x04c518a746e9715fde6a6d3ebdf678ea51c6d591b95e35d73b7e312afa44dd71; + 0x095b95bd4097eddc78a04047eaaf54c1bf5007ccce3f4f54118d21b4c01d9845; } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 0fa15654..0c18a7bb 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -7,6 +7,7 @@ import hre from "hardhat"; import typedDataForTransaction from "./typesDataForTransaction"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { TestModifier__factory } from "../typechain-types"; +import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; @@ -496,7 +497,7 @@ async function sign( ) { const { domain, types, message } = typedDataForTransaction( { contract, chainId: 31337, nonce: 0 }, - { value: transaction.value || 0, data: transaction.data || "0x" } + transaction.data || "0x" ); return signer._signTypedData(domain, types, message); } diff --git a/test/06_Eip712Signature.spec.ts b/test/06_Eip712Signature.spec.ts index 444e320e..b54eb60a 100644 --- a/test/06_Eip712Signature.spec.ts +++ b/test/06_Eip712Signature.spec.ts @@ -79,7 +79,7 @@ async function sign( ) { const { domain, types, message } = typedDataForTransaction( { contract, chainId: 31337, nonce: 0 }, - { value: transaction.value || 0, data: transaction.data || "0x" } + transaction.data || "0x" ); return await signer._signTypedData(domain, types, message); } diff --git a/test/typesDataForTransaction.ts b/test/typesDataForTransaction.ts index b95d3c4e..331a26ad 100644 --- a/test/typesDataForTransaction.ts +++ b/test/typesDataForTransaction.ts @@ -10,18 +10,16 @@ export default function typedDataForTransaction( chainId: BigNumberish; nonce: BigNumberish; }, - { value, data }: { value: BigNumberish; data: string } + data: string ) { const domain = { verifyingContract: contract, chainId }; const types = { Transaction: [ - { type: "uint256", name: "value" }, { type: "bytes", name: "data" }, { type: "uint256", name: "nonce" }, ], }; const message = { - value, data, nonce, }; From 7dd5f9e737278a39c94810004b40bcb743c188f1 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 05:44:00 +0200 Subject: [PATCH 15/82] Rename root type for EIP712 data structure --- contracts/signature/Eip712Signature.sol | 4 ++-- test/typesDataForTransaction.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index 8d6a8482..708ce541 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -72,8 +72,8 @@ abstract contract EIP712Signature { 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; // keccak256( - // "Transaction(bytes data,uint256 nonce)" + // "ModuleTx(bytes data,uint256 nonce)" // ); bytes32 private constant TRANSACTION_TYPEHASH = - 0x095b95bd4097eddc78a04047eaaf54c1bf5007ccce3f4f54118d21b4c01d9845; + 0xd6c6b5df57eef4e79cab990a377d29dc4c5bbb016a6293120d53f49c54144227; } diff --git a/test/typesDataForTransaction.ts b/test/typesDataForTransaction.ts index 331a26ad..351bd952 100644 --- a/test/typesDataForTransaction.ts +++ b/test/typesDataForTransaction.ts @@ -14,7 +14,7 @@ export default function typedDataForTransaction( ) { const domain = { verifyingContract: contract, chainId }; const types = { - Transaction: [ + ModuleTx: [ { type: "bytes", name: "data" }, { type: "uint256", name: "nonce" }, ], From ce0d878ccb08ec16dc176bb61a17ef0c0de6fa21 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 11:43:41 +0200 Subject: [PATCH 16/82] Add natspec --- contracts/signature/Eip712Signature.sol | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index 708ce541..bab97a69 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -1,17 +1,28 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; +/// @title EIP712Signature - A contract that extracts and inspects EIP-712 signatures appended to calldata. + abstract contract EIP712Signature { uint256 private nonce; - function eip712Nonce() public view returns (uint256 signed) { + /** + * @dev Returns the current nonce value. + */ + function eip712Nonce() public view returns (uint256) { return nonce; } + /** + * @dev Increments nonce. + */ function eip712BumpNonce() internal { nonce = nonce + 1; } + /** + * @dev When signature present, returns the signer address. + */ function eip712SignedBy() internal returns (address signer) { if (msg.data.length >= 4 + 65) { ( @@ -27,6 +38,10 @@ abstract contract EIP712Signature { } } + /** + * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`. + * @param data current transaction calldata. + */ function _splitSignature( bytes calldata data ) @@ -41,6 +56,12 @@ abstract contract EIP712Signature { v = uint8(bytes1(data[length - 1:])); } + /** + * @dev Hashes the EIP-712 data structure that will be signed by owner. + * @param data The data for the transaction. + * @param _nonce The nonce value. + * @return the bytes32 hash to be signed by owners. + */ function _transactionHash( bytes calldata data, uint256 _nonce From 07acfa7511352523adbf17aed0d73a8b8f5bb276 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 12:53:01 +0200 Subject: [PATCH 17/82] Extract badSignature checks to their own test cases, instead of mixed with success case tests --- contracts/signature/Eip712Signature.sol | 8 +- test/03_Modifier.spec.ts | 104 ++++++++++++++++++------ 2 files changed, 79 insertions(+), 33 deletions(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index bab97a69..3e3079d9 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -76,11 +76,7 @@ abstract contract EIP712Signature { bytes1(0x01), domainSeparator, keccak256( - abi.encode( - TRANSACTION_TYPEHASH, - keccak256(data), - _nonce - ) + abi.encode(MODULE_TX_TYPEHASH, keccak256(data), _nonce) ) ) ); @@ -95,6 +91,6 @@ abstract contract EIP712Signature { // keccak256( // "ModuleTx(bytes data,uint256 nonce)" // ); - bytes32 private constant TRANSACTION_TYPEHASH = + bytes32 private constant MODULE_TX_TYPEHASH = 0xd6c6b5df57eef4e79cab990a377d29dc4c5bbb016a6293120d53f49c54144227; } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 0c18a7bb..5d74a274 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -313,6 +313,37 @@ describe("Modifier", async () => { ).to.emit(modifier, "executed"); }); it("execute a transaction with signature.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, relayer] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModule( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const signature = await sign(modifier.address, transaction, user1); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect( + relayer.sendTransaction(transaction) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); + + await expect(relayer.sendTransaction(transactionWithSig)).to.emit( + modifier, + "executed" + ); + }); + it("reverts if signature not valid.", async () => { const { modifier, tx } = await loadFixture(setupTests); const [user1, user2, relayer] = await hre.ethers.getSigners(); await expect(await modifier.enableModule(user1.address)) @@ -330,29 +361,24 @@ describe("Modifier", async () => { const signatureOk = await sign(modifier.address, transaction, user1); const signatureBad = await sign(modifier.address, transaction, user2); - const transactionWithOkSig = { + const transactionWithBadSig = { ...transaction, - data: `${transaction.data}${signatureOk.slice(2)}`, + data: `${transaction.data}${signatureBad.slice(2)}`, }; - const transactionWithBadSig = { + const transactionWithOkSig = { ...transaction, - data: `${transaction.data}${signatureBad.slice(2)}`, + data: `${transaction.data}${signatureOk.slice(2)}`, }; - await expect(user1.sendTransaction(transaction)).to.emit( - modifier, - "executed" - ); + await expect( + relayer.sendTransaction(transactionWithBadSig) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( modifier, "executed" ); - - await expect( - relayer.sendTransaction(transactionWithBadSig) - ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); }); it("execute a transaction via sender nonce stays same.", async () => { const { modifier, tx } = await loadFixture(setupTests); @@ -427,7 +453,6 @@ describe("Modifier", async () => { .to.be.revertedWithCustomError(modifier, "NotAuthorized") .withArgs("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); }); - it("execute a transaction.", async () => { const { modifier, tx } = await loadFixture(setupTests); const [user1] = await hre.ethers.getSigners(); @@ -444,10 +469,9 @@ describe("Modifier", async () => { ) ).to.emit(modifier, "executedAndReturnedData"); }); - it("execute a transaction with signature.", async () => { const { modifier, tx } = await loadFixture(setupTests); - const [user1, user2, relayer] = await hre.ethers.getSigners(); + const [user1, relayer] = await hre.ethers.getSigners(); await expect(await modifier.enableModule(user1.address)) .to.emit(modifier, "EnabledModule") .withArgs(user1.address); @@ -460,32 +484,58 @@ describe("Modifier", async () => { tx.operation ); - const signatureOk = await sign(modifier.address, transaction, user1); - const signatureBad = await sign(modifier.address, transaction, user2); + const signature = await sign(modifier.address, transaction, user1); - const transactionWithOkSig = { + const transactionWithSig = { ...transaction, - data: `${transaction.data}${signatureOk.slice(2)}`, + data: `${transaction.data}${signature.slice(2)}`, }; + await expect( + relayer.sendTransaction(transaction) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); + + await expect(relayer.sendTransaction(transactionWithSig)).to.emit( + modifier, + "executedAndReturnedData" + ); + }); + it("reverts if signature not valid.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, user2, relayer] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModuleReturnData( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const signatureBad = await sign(modifier.address, transaction, user2); + const signatureOk = await sign(modifier.address, transaction, user1); + const transactionWithBadSig = { ...transaction, data: `${transaction.data}${signatureBad.slice(2)}`, }; - await expect(user1.sendTransaction(transaction)).to.emit( - modifier, - "executedAndReturnedData" - ); + const transactionWithOkSig = { + ...transaction, + data: `${transaction.data}${signatureOk.slice(2)}`, + }; + + await expect( + relayer.sendTransaction(transactionWithBadSig) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( modifier, "executedAndReturnedData" ); - - await expect( - relayer.sendTransaction(transactionWithBadSig) - ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); }); }); }); From ee8eb26c14b31096fcdf20b1e4415ec5e1ed0233 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 28 Sep 2023 22:07:16 +0200 Subject: [PATCH 18/82] Rename helper function --- contracts/signature/Eip712Signature.sol | 26 +++++++++++-------------- test/03_Modifier.spec.ts | 1 - 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/Eip712Signature.sol index 3e3079d9..bb9cdcb6 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/Eip712Signature.sol @@ -21,10 +21,10 @@ abstract contract EIP712Signature { } /** - * @dev When signature present, returns the signer address. + * @dev When signature present in calldata, returns the address of the signer. */ function eip712SignedBy() internal returns (address signer) { - if (msg.data.length >= 4 + 65) { + if (msg.data.length >= 4 + 32 + 32 + 1) { ( bytes calldata dataTrimmed, uint8 v, @@ -32,7 +32,7 @@ abstract contract EIP712Signature { bytes32 s ) = _splitSignature(msg.data); - bytes32 txHash = _transactionHash(dataTrimmed, nonce); + bytes32 txHash = _moduleTxHash(dataTrimmed, nonce); signer = ecrecover(txHash, v, r, s); } @@ -62,24 +62,20 @@ abstract contract EIP712Signature { * @param _nonce The nonce value. * @return the bytes32 hash to be signed by owners. */ - function _transactionHash( + function _moduleTxHash( bytes calldata data, uint256 _nonce ) private view returns (bytes32) { bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) ); - return - keccak256( - abi.encodePacked( - bytes1(0x19), - bytes1(0x01), - domainSeparator, - keccak256( - abi.encode(MODULE_TX_TYPEHASH, keccak256(data), _nonce) - ) - ) - ); + bytes memory moduleTxData = abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + domainSeparator, + keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), _nonce)) + ); + return keccak256(moduleTxData); } // keccak256( diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 5d74a274..4f1b6d0f 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -7,7 +7,6 @@ import hre from "hardhat"; import typedDataForTransaction from "./typesDataForTransaction"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { TestModifier__factory } from "../typechain-types"; -import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; From dfaa8a3446debcd335180d6fb313046104471ed1 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Fri, 29 Sep 2023 15:46:44 +0200 Subject: [PATCH 19/82] Renames in preparation for eip-1271 signatures --- contracts/core/Modifier.sol | 8 ++++---- .../{Eip712Signature.sol => SignatureChecker.sol} | 12 ++++++------ contracts/test/TestSignature.sol | 8 ++++---- test/03_Modifier.spec.ts | 4 ++-- test/06_Eip712Signature.spec.ts | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) rename contracts/signature/{Eip712Signature.sol => SignatureChecker.sol} (86%) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 7b5a6c1b..160898c1 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -5,9 +5,9 @@ pragma solidity >=0.7.0 <0.9.0; import "./Module.sol"; import "../interfaces/IAvatar.sol"; -import "../signature/EIP712Signature.sol"; +import "../signature/SignatureChecker.sol"; -abstract contract Modifier is Module, IAvatar, EIP712Signature { +abstract contract Modifier is Module, IAvatar, SignatureChecker { address internal constant SENTINEL_MODULES = address(0x1); /// Mapping of modules. mapping(address => address) internal modules; @@ -75,10 +75,10 @@ abstract contract Modifier is Module, IAvatar, EIP712Signature { modifier moduleOnly() { if (modules[msg.sender] == address(0)) { - if (modules[eip712SignedBy()] == address(0)) { + if (modules[moduleTxSignedBy()] == address(0)) { revert NotAuthorized(msg.sender); } - eip712BumpNonce(); + moduleTxNonceBump(); } _; diff --git a/contracts/signature/Eip712Signature.sol b/contracts/signature/SignatureChecker.sol similarity index 86% rename from contracts/signature/Eip712Signature.sol rename to contracts/signature/SignatureChecker.sol index bb9cdcb6..f1d3d072 100644 --- a/contracts/signature/Eip712Signature.sol +++ b/contracts/signature/SignatureChecker.sol @@ -1,29 +1,29 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -/// @title EIP712Signature - A contract that extracts and inspects EIP-712 signatures appended to calldata. - -abstract contract EIP712Signature { +/// @title SignatureChecker - A contract that extracts and inspects signatures appended to calldata. +/// @notice currently supporting eip-712 and eip-1271 signatures +abstract contract SignatureChecker { uint256 private nonce; /** * @dev Returns the current nonce value. */ - function eip712Nonce() public view returns (uint256) { + function moduleTxNonce() public view returns (uint256) { return nonce; } /** * @dev Increments nonce. */ - function eip712BumpNonce() internal { + function moduleTxNonceBump() internal { nonce = nonce + 1; } /** * @dev When signature present in calldata, returns the address of the signer. */ - function eip712SignedBy() internal returns (address signer) { + function moduleTxSignedBy() internal view returns (address signer) { if (msg.data.length >= 4 + 32 + 32 + 1) { ( bytes calldata dataTrimmed, diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index a5e94de8..e1afb074 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0; -import "../signature/EIP712Signature.sol"; +import "../signature/SignatureChecker.sol"; -contract TestSignature is EIP712Signature { +contract TestSignature is SignatureChecker { event Hello(address signer); event Goodbye(address signer); function hello() public { - emit Hello(eip712SignedBy()); + emit Hello(moduleTxSignedBy()); } function goodbye(uint256, bytes memory) public { - emit Goodbye(eip712SignedBy()); + emit Goodbye(moduleTxSignedBy()); } } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 4f1b6d0f..7bcb91df 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -399,7 +399,7 @@ describe("Modifier", async () => { await TestModifier__factory.connect( modifier.address, hre.ethers.provider - ).eip712Nonce() + ).moduleTxNonce() ).to.equal(0); }); it("execute a transaction with signature nonce is incremented.", async () => { @@ -433,7 +433,7 @@ describe("Modifier", async () => { await TestModifier__factory.connect( modifier.address, hre.ethers.provider - ).eip712Nonce() + ).moduleTxNonce() ).to.equal(1); }); }); diff --git a/test/06_Eip712Signature.spec.ts b/test/06_Eip712Signature.spec.ts index b54eb60a..03411de5 100644 --- a/test/06_Eip712Signature.spec.ts +++ b/test/06_Eip712Signature.spec.ts @@ -68,7 +68,7 @@ describe("EIP712Signature", async () => { it("it publicly exposes the eip712 nonce", async () => { const { testSignature } = await loadFixture(setup); - expect(await testSignature.eip712Nonce()).to.equal(0); + expect(await testSignature.moduleTxNonce()).to.equal(0); }); }); From 9ffff3a5ad101c90fa7f72b6bf2bd94b8ca6944b Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sat, 30 Sep 2023 22:43:16 +0200 Subject: [PATCH 20/82] Add eip-1271 support --- contracts/signature/IERC1271.sol | 19 ++ contracts/signature/SignatureChecker.sol | 68 ++++++- contracts/test/TestSignature.sol | 29 +++ test/06_Eip712Signature.spec.ts | 85 -------- test/06_SignatureChecker.spec.ts | 234 +++++++++++++++++++++++ 5 files changed, 341 insertions(+), 94 deletions(-) create mode 100644 contracts/signature/IERC1271.sol delete mode 100644 test/06_Eip712Signature.spec.ts create mode 100644 test/06_SignatureChecker.spec.ts diff --git a/contracts/signature/IERC1271.sol b/contracts/signature/IERC1271.sol new file mode 100644 index 00000000..90e1927b --- /dev/null +++ b/contracts/signature/IERC1271.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-3.0-only +/* solhint-disable one-contract-per-file */ +pragma solidity >=0.7.0 <0.9.0; + +interface IERC1271 { + /** + * @notice EIP1271 method to validate a signature. + * @param hash Hash of the data signed on the behalf of address(this). + * @param signature Signature byte array associated with _data. + * + * MUST return the bytes4 magic value 0x1626ba7e when function passes. + * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) + * MUST allow external calls + */ + function isValidSignature( + bytes32 hash, + bytes memory signature + ) external view returns (bytes4); +} diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index f1d3d072..bff85941 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; +import "./IERC1271.sol"; + /// @title SignatureChecker - A contract that extracts and inspects signatures appended to calldata. /// @notice currently supporting eip-712 and eip-1271 signatures abstract contract SignatureChecker { @@ -24,17 +26,29 @@ abstract contract SignatureChecker { * @dev When signature present in calldata, returns the address of the signer. */ function moduleTxSignedBy() internal view returns (address signer) { - if (msg.data.length >= 4 + 32 + 32 + 1) { + bytes calldata data = msg.data; + if (data.length >= 4 + 65) { ( - bytes calldata dataTrimmed, - uint8 v, bytes32 r, - bytes32 s - ) = _splitSignature(msg.data); + bytes32 s, + uint8 v, + bool isContractSignature, + uint256 start, + uint256 end + ) = _splitSignature(data); - bytes32 txHash = _moduleTxHash(dataTrimmed, nonce); + bytes32 hash = _moduleTxHash(data[:start], nonce); - signer = ecrecover(txHash, v, r, s); + if (isContractSignature) { + // When handling contract signatures the address + // of the contract is encoded into r + signer = address(uint160(uint256(r))); + if (!isValidContractSignature(signer, hash, data[start:end])) { + signer = address(0); + } + } else { + signer = ecrecover(hash, v, r, s); + } } } @@ -47,13 +61,22 @@ abstract contract SignatureChecker { ) private pure - returns (bytes calldata dataTrimmed, uint8 v, bytes32 r, bytes32 s) + returns ( + bytes32 r, + bytes32 s, + uint8 v, + bool isEIP1271, + uint256 start, + uint256 end + ) { uint256 length = data.length; - dataTrimmed = data[0:length - 65]; r = bytes32(data[length - 65:]); s = bytes32(data[length - 33:]); v = uint8(bytes1(data[length - 1:])); + isEIP1271 = v == 0 && (uint256(s) < (length - 65)); + start = isEIP1271 ? uint256(s) : length - 65; + end = isEIP1271 ? length - 65 : length; } /** @@ -78,6 +101,30 @@ abstract contract SignatureChecker { return keccak256(moduleTxData); } + function isValidContractSignature( + address signer, + bytes32 hash, + bytes calldata signature + ) internal view returns (bool result) { + uint256 size; + assembly { + size := extcodesize(signer) + } + if (size == 0) { + return false; + } + + (bool success, bytes memory returnData) = signer.staticcall( + abi.encodeWithSelector( + IERC1271.isValidSignature.selector, + hash, + signature + ) + ); + + return success == true && bytes4(returnData) == EIP1271_MAGIC_VALUE; + } + // keccak256( // "EIP712Domain(uint256 chainId,address verifyingContract)" // ); @@ -89,4 +136,7 @@ abstract contract SignatureChecker { // ); bytes32 private constant MODULE_TX_TYPEHASH = 0xd6c6b5df57eef4e79cab990a377d29dc4c5bbb016a6293120d53f49c54144227; + + // bytes4(keccak256("isValidSignature(bytes32,bytes)") + bytes4 private constant EIP1271_MAGIC_VALUE = 0x1626ba7e; } diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index e1afb074..5a76edd9 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -3,6 +3,35 @@ pragma solidity >=0.8.0; import "../signature/SignatureChecker.sol"; +contract ContractSignerYes is IERC1271 { + function isValidSignature( + bytes32, + bytes memory + ) external pure override returns (bytes4) { + return 0x1626ba7e; + } +} + +contract ContractSignerNo is IERC1271 { + function isValidSignature( + bytes32, + bytes memory + ) external pure override returns (bytes4) { + return 0x33333333; + } +} + +contract ContractSignerFaulty {} + +contract ContractSignerReturnSize { + function isValidSignature( + bytes32, + bytes memory + ) external pure returns (bytes2) { + return 0x1626; + } +} + contract TestSignature is SignatureChecker { event Hello(address signer); diff --git a/test/06_Eip712Signature.spec.ts b/test/06_Eip712Signature.spec.ts deleted file mode 100644 index 03411de5..00000000 --- a/test/06_Eip712Signature.spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -import hre from "hardhat"; -import { TestSignature__factory } from "../typechain-types"; -import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; -import { PopulatedTransaction } from "ethers"; -import { expect } from "chai"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; - -import typedDataForTransaction from "./typesDataForTransaction"; - -describe("EIP712Signature", async () => { - async function setup() { - const [signer, relayer] = await hre.ethers.getSigners(); - const TestSignature = await hre.ethers.getContractFactory("TestSignature"); - const testSignature = await TestSignature.deploy(); - - return { - testSignature: TestSignature__factory.connect( - testSignature.address, - relayer - ), - signer, - relayer, - }; - } - - const AddressZero = "0x0000000000000000000000000000000000000000"; - - it("correctly detects an appended signature, for an entrypoint no arguments", async () => { - const { testSignature, signer, relayer } = await loadFixture(setup); - - const transaction = await testSignature.populateTransaction.hello(); - const signature = await sign(testSignature.address, transaction, signer); - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transaction)) - .to.emit(testSignature, "Hello") - .withArgs(AddressZero); - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Hello") - .withArgs(signer.address); - }); - - it("correctly detects an appended signature, entrypoint with arguments", async () => { - const { testSignature, signer, relayer } = await loadFixture(setup); - - const transaction = await testSignature.populateTransaction.goodbye( - 0, - "0xbadfed" - ); - const signature = await sign(testSignature.address, transaction, signer); - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transaction)) - .to.emit(testSignature, "Goodbye") - .withArgs(AddressZero); - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Goodbye") - .withArgs(signer.address); - }); - - it("it publicly exposes the eip712 nonce", async () => { - const { testSignature } = await loadFixture(setup); - expect(await testSignature.moduleTxNonce()).to.equal(0); - }); -}); - -async function sign( - contract: string, - transaction: PopulatedTransaction, - signer: SignerWithAddress -) { - const { domain, types, message } = typedDataForTransaction( - { contract, chainId: 31337, nonce: 0 }, - transaction.data || "0x" - ); - return await signer._signTypedData(domain, types, message); -} diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts new file mode 100644 index 00000000..9ba46598 --- /dev/null +++ b/test/06_SignatureChecker.spec.ts @@ -0,0 +1,234 @@ +import hre from "hardhat"; +import { TestSignature__factory } from "../typechain-types"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import { PopulatedTransaction } from "ethers"; +import { expect } from "chai"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; + +import typedDataForTransaction from "./typesDataForTransaction"; +import { defaultAbiCoder, solidityPack } from "ethers/lib/utils"; + +describe("SignatureChecker", async () => { + async function setup() { + const [signer, relayer] = await hre.ethers.getSigners(); + const TestSignature = await hre.ethers.getContractFactory("TestSignature"); + const testSignature = await TestSignature.deploy(); + + return { + testSignature: TestSignature__factory.connect( + testSignature.address, + relayer + ), + signer, + relayer, + }; + } + + const AddressZero = "0x0000000000000000000000000000000000000000"; + + it("correctly detects an appended signature, for an entrypoint no arguments", async () => { + const { testSignature, signer, relayer } = await loadFixture(setup); + + const transaction = await testSignature.populateTransaction.hello(); + const signature = await sign(testSignature.address, transaction, signer); + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(signer.address); + }); + + it("correctly detects an appended signature, entrypoint with arguments", async () => { + const { testSignature, signer, relayer } = await loadFixture(setup); + + const transaction = await testSignature.populateTransaction.goodbye( + 0, + "0xbadfed" + ); + const signature = await sign(testSignature.address, transaction, signer); + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(signer.address); + }); + + it("contract signature, signer returns isValid yes", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerYes" + ); + const contractSigner = await ContractSigner.deploy(); + + const transaction = await testSignature.populateTransaction.goodbye( + 0, + "0xbadfed" + ); + + const signature = makeContractSignature( + contractSigner.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(contractSigner.address); + }); + + it("contract signature, signer returns isValid no", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const Signer = await hre.ethers.getContractFactory("ContractSignerNo"); + const signer = await Signer.deploy(); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signer.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("contract signature, bad return size", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const Signer = await hre.ethers.getContractFactory( + "ContractSignerReturnSize" + ); + const signer = await Signer.deploy(); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signer.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("contract signature, signer with faulty entrypoint", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const Signer = await hre.ethers.getContractFactory("ContractSignerFaulty"); + const signer = await Signer.deploy(); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signer.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("contract signature, signer with no code deployed", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const signerAddress = "0x1234567890000000000000000000000123456789"; + + await expect(await hre.ethers.provider.getCode(signerAddress)).to.equal( + "0x" + ); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signerAddress, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("it publicly exposes the eip712 nonce", async () => { + const { testSignature } = await loadFixture(setup); + expect(await testSignature.moduleTxNonce()).to.equal(0); + }); +}); + +async function sign( + contract: string, + transaction: PopulatedTransaction, + signer: SignerWithAddress +) { + const { domain, types, message } = typedDataForTransaction( + { contract, chainId: 31337, nonce: 0 }, + transaction.data || "0x" + ); + return await signer._signTypedData(domain, types, message); +} + +function makeContractSignature( + contract: string, + transaction: PopulatedTransaction, + signature: string +) { + const dataBytesLength = (transaction.data?.length as number) / 2 - 1; + + const r = defaultAbiCoder.encode(["address"], [contract]); + const s = defaultAbiCoder.encode(["uint256"], [dataBytesLength]); + const v = solidityPack(["uint8"], [0]); + + return `${signature}${r.slice(2)}${s.slice(2)}${v.slice(2)}`; +} From c9f5b9e6cf33aa48e86f35dcabbe85a5d5fd843d Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sat, 30 Sep 2023 23:05:44 +0200 Subject: [PATCH 21/82] Rename helper function --- contracts/signature/SignatureChecker.sol | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index bff85941..755eca3d 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -32,18 +32,19 @@ abstract contract SignatureChecker { bytes32 r, bytes32 s, uint8 v, - bool isContractSignature, - uint256 start, - uint256 end + bool isEIP1271, + uint256 start ) = _splitSignature(data); bytes32 hash = _moduleTxHash(data[:start], nonce); - if (isContractSignature) { + if (isEIP1271) { // When handling contract signatures the address // of the contract is encoded into r signer = address(uint160(uint256(r))); - if (!isValidContractSignature(signer, hash, data[start:end])) { + uint256 end = data.length - 65; + + if (!_isValidContractSignature(signer, hash, data[start:end])) { signer = address(0); } } else { @@ -61,14 +62,7 @@ abstract contract SignatureChecker { ) private pure - returns ( - bytes32 r, - bytes32 s, - uint8 v, - bool isEIP1271, - uint256 start, - uint256 end - ) + returns (bytes32 r, bytes32 s, uint8 v, bool isEIP1271, uint256 start) { uint256 length = data.length; r = bytes32(data[length - 65:]); @@ -76,7 +70,6 @@ abstract contract SignatureChecker { v = uint8(bytes1(data[length - 1:])); isEIP1271 = v == 0 && (uint256(s) < (length - 65)); start = isEIP1271 ? uint256(s) : length - 65; - end = isEIP1271 ? length - 65 : length; } /** @@ -101,7 +94,7 @@ abstract contract SignatureChecker { return keccak256(moduleTxData); } - function isValidContractSignature( + function _isValidContractSignature( address signer, bytes32 hash, bytes calldata signature From 5de81009751d2ede60f930d63dfa57f85d92a0a0 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sun, 1 Oct 2023 08:24:12 +0200 Subject: [PATCH 22/82] Change visibility of moduleTxHash. Comments --- contracts/signature/SignatureChecker.sol | 142 +++++++++++++++-------- 1 file changed, 91 insertions(+), 51 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 755eca3d..91886fb3 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -4,58 +4,100 @@ pragma solidity >=0.8.0 <0.9.0; import "./IERC1271.sol"; /// @title SignatureChecker - A contract that extracts and inspects signatures appended to calldata. -/// @notice currently supporting eip-712 and eip-1271 signatures +/// @notice currently supports eip-712 and eip-1271 abstract contract SignatureChecker { uint256 private nonce; /** - * @dev Returns the current nonce value. + * @notice Returns the current nonce value. */ function moduleTxNonce() public view returns (uint256) { return nonce; } /** - * @dev Increments nonce. + * @notice Increments nonce. */ function moduleTxNonceBump() internal { nonce = nonce + 1; } /** - * @dev When signature present in calldata, returns the address of the signer. + * @notice Searches for a valid signature, and returns address of signer. + * @dev When signature not found or not valid, Zero address is returned + * @return the address of the signer. */ - function moduleTxSignedBy() internal view returns (address signer) { + function moduleTxSignedBy() internal view returns (address) { bytes calldata data = msg.data; - if (data.length >= 4 + 65) { - ( - bytes32 r, - bytes32 s, - uint8 v, - bool isEIP1271, - uint256 start - ) = _splitSignature(data); - - bytes32 hash = _moduleTxHash(data[:start], nonce); - - if (isEIP1271) { - // When handling contract signatures the address - // of the contract is encoded into r - signer = address(uint160(uint256(r))); - uint256 end = data.length - 65; - - if (!_isValidContractSignature(signer, hash, data[start:end])) { - signer = address(0); - } - } else { - signer = ecrecover(hash, v, r, s); - } + + /* + * The overarching idea is to provide transparent checking to + * modules using `onlyModule` + * + * Since it's a generic mechanism we don't have a definitive way to + * know if the trailling bytes are a signature. We just slice those + * bytes and recover a signature + * + * Hence, we require the calldata to be at least as long as a function + * selector plus a signature - 4 + 65. Anything than that is guaranteed + * to not contain a signature + */ + if (data.length < 4 + 65) { + return address(0); + } + + ( + bytes32 r, + bytes32 s, + uint8 v, + bool isContractSignature, + uint256 start + ) = _splitSignature(data); + + bytes32 txHash = moduleTxHash(data[:start], nonce); + + if (isContractSignature) { + // When handling contract signatures the address + // of the contract is encoded into r + address signer = address(uint160(uint256(r))); + return + _isValidContractSignature( + signer, + txHash, + data[start:data.length - 65] + ) + ? signer + : address(0); + } else { + return ecrecover(txHash, v, r, s); } } + /** + * @dev Hashes the EIP-712 data structure that will be signed. + * @param data The current transaction's calldata. + * @param _nonce The nonce value. + * @return The 32-byte hash that is to be signed. + */ + function moduleTxHash( + bytes calldata data, + uint256 _nonce + ) public view returns (bytes32) { + bytes32 domainSeparator = keccak256( + abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) + ); + bytes memory moduleTxData = abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + domainSeparator, + keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), _nonce)) + ); + return keccak256(moduleTxData); + } + /** * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`. - * @param data current transaction calldata. + * @param data The current transaction's calldata. */ function _splitSignature( bytes calldata data @@ -64,6 +106,19 @@ abstract contract SignatureChecker { pure returns (bytes32 r, bytes32 s, uint8 v, bool isEIP1271, uint256 start) { + /* + * When handling contract signatures: + * v - is zero + * r - contains the signer + * s - contains the offset within calldata where the signer specific + * signature is located + * + * We detect contract signatures by the following three conditions: + * 1- v is zero + * 2- s points within te buffer + * 3- the position pointed by S has non zero length + */ + uint256 length = data.length; r = bytes32(data[length - 65:]); s = bytes32(data[length - 33:]); @@ -73,30 +128,15 @@ abstract contract SignatureChecker { } /** - * @dev Hashes the EIP-712 data structure that will be signed by owner. - * @param data The data for the transaction. - * @param _nonce The nonce value. - * @return the bytes32 hash to be signed by owners. + * @dev Calls the signer contract, and validates the provided signature. + * @param signer The address of the signer. + * @param txHash The hash of the message that was signed. + * @param signature The signature to validate. + * @return result indicates whether the signature is valid. */ - function _moduleTxHash( - bytes calldata data, - uint256 _nonce - ) private view returns (bytes32) { - bytes32 domainSeparator = keccak256( - abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) - ); - bytes memory moduleTxData = abi.encodePacked( - bytes1(0x19), - bytes1(0x01), - domainSeparator, - keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), _nonce)) - ); - return keccak256(moduleTxData); - } - function _isValidContractSignature( address signer, - bytes32 hash, + bytes32 txHash, bytes calldata signature ) internal view returns (bool result) { uint256 size; @@ -110,7 +150,7 @@ abstract contract SignatureChecker { (bool success, bytes memory returnData) = signer.staticcall( abi.encodeWithSelector( IERC1271.isValidSignature.selector, - hash, + txHash, signature ) ); From 9a9e38025ad7518f6e5350aeac673435a7db70f1 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sun, 1 Oct 2023 10:54:53 +0200 Subject: [PATCH 23/82] Update comments. Use v,s,r order. Add test cases --- contracts/signature/SignatureChecker.sol | 68 ++-- test/06_SignatureChecker.spec.ts | 412 +++++++++++++++-------- 2 files changed, 312 insertions(+), 168 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 91886fb3..65163cfc 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -3,21 +3,17 @@ pragma solidity >=0.8.0 <0.9.0; import "./IERC1271.sol"; -/// @title SignatureChecker - A contract that extracts and inspects signatures appended to calldata. -/// @notice currently supports eip-712 and eip-1271 +/// @title SignatureChecker - A contract that validates signatures appended to calldata. +/// @dev currently supports eip-712 and eip-1271 abstract contract SignatureChecker { uint256 private nonce; - /** - * @notice Returns the current nonce value. - */ + /// @notice Returns the current nonce value. function moduleTxNonce() public view returns (uint256) { return nonce; } - /** - * @notice Increments nonce. - */ + /// @notice Increments nonce. function moduleTxNonceBump() internal { nonce = nonce + 1; } @@ -31,25 +27,25 @@ abstract contract SignatureChecker { bytes calldata data = msg.data; /* - * The overarching idea is to provide transparent checking to - * modules using `onlyModule` + * The idea is to extend `onlyModule` and provide signature checking + * to modules, without code changes. * * Since it's a generic mechanism we don't have a definitive way to * know if the trailling bytes are a signature. We just slice those - * bytes and recover a signature + * out and recover signer. * * Hence, we require the calldata to be at least as long as a function - * selector plus a signature - 4 + 65. Anything than that is guaranteed - * to not contain a signature + * selector plus a signature - 4 + 65. Anything less than that is + * guaranteed to not contain a signature */ if (data.length < 4 + 65) { return address(0); } ( + uint8 v, bytes32 r, bytes32 s, - uint8 v, bool isContractSignature, uint256 start ) = _splitSignature(data); @@ -57,8 +53,6 @@ abstract contract SignatureChecker { bytes32 txHash = moduleTxHash(data[:start], nonce); if (isContractSignature) { - // When handling contract signatures the address - // of the contract is encoded into r address signer = address(uint160(uint256(r))); return _isValidContractSignature( @@ -74,7 +68,8 @@ abstract contract SignatureChecker { } /** - * @dev Hashes the EIP-712 data structure that will be signed. + * @notice Hashes the EIP-712 data structure. + * @dev The produced hash is intended to be signed. * @param data The current transaction's calldata. * @param _nonce The nonce value. * @return The 32-byte hash that is to be signed. @@ -98,13 +93,24 @@ abstract contract SignatureChecker { /** * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`. * @param data The current transaction's calldata. + * @return v The ECDSA v value + * @return r The ECDSA r value + * @return s The ECDSA s value + * @return isEIP1271Signature Indicates whether it is a contract signature + * @return start offset in calldata where signature starts */ function _splitSignature( bytes calldata data ) private pure - returns (bytes32 r, bytes32 s, uint8 v, bool isEIP1271, uint256 start) + returns ( + uint8 v, + bytes32 r, + bytes32 s, + bool isEIP1271Signature, + uint256 start + ) { /* * When handling contract signatures: @@ -113,22 +119,26 @@ abstract contract SignatureChecker { * s - contains the offset within calldata where the signer specific * signature is located * - * We detect contract signatures by the following three conditions: - * 1- v is zero - * 2- s points within te buffer - * 3- the position pointed by S has non zero length + * We detect contract signatures by the following two conditions: + * 1- `v` is zero + * 2- `s` points within the buffer, is after selector and before sig + * + * The data pointed by s should be non zero, as EIP-1271 describes a + * a non-zero length signer specific signature */ - uint256 length = data.length; + v = uint8(bytes1(data[length - 1:])); r = bytes32(data[length - 65:]); s = bytes32(data[length - 33:]); - v = uint8(bytes1(data[length - 1:])); - isEIP1271 = v == 0 && (uint256(s) < (length - 65)); - start = isEIP1271 ? uint256(s) : length - 65; + isEIP1271Signature = + v == 0 && + uint256(s) > 3 && + uint256(s) < (length - 65); + start = isEIP1271Signature ? uint256(s) : length - 65; } /** - * @dev Calls the signer contract, and validates the provided signature. + * @dev Calls the signer contract, and validates signature. * @param signer The address of the signer. * @param txHash The hash of the message that was signed. * @param signature The signature to validate. @@ -147,7 +157,7 @@ abstract contract SignatureChecker { return false; } - (bool success, bytes memory returnData) = signer.staticcall( + (, bytes memory returnData) = signer.staticcall( abi.encodeWithSelector( IERC1271.isValidSignature.selector, txHash, @@ -155,7 +165,7 @@ abstract contract SignatureChecker { ) ); - return success == true && bytes4(returnData) == EIP1271_MAGIC_VALUE; + return bytes4(returnData) == EIP1271_MAGIC_VALUE; } // keccak256( diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 9ba46598..5d7c0de3 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -67,144 +67,277 @@ describe("SignatureChecker", async () => { .withArgs(signer.address); }); - it("contract signature, signer returns isValid yes", async () => { - const { testSignature, relayer } = await loadFixture(setup); - - const ContractSigner = await hre.ethers.getContractFactory( - "ContractSignerYes" - ); - const contractSigner = await ContractSigner.deploy(); - - const transaction = await testSignature.populateTransaction.goodbye( - 0, - "0xbadfed" - ); - - const signature = makeContractSignature( - contractSigner.address, - transaction, - "0xaabbccddeeff" - ); - - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transaction)) - .to.emit(testSignature, "Goodbye") - .withArgs(AddressZero); - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Goodbye") - .withArgs(contractSigner.address); - }); - - it("contract signature, signer returns isValid no", async () => { - const { testSignature, relayer } = await loadFixture(setup); - - const Signer = await hre.ethers.getContractFactory("ContractSignerNo"); - const signer = await Signer.deploy(); - - const transaction = await testSignature.populateTransaction.hello(); - - const signature = makeContractSignature( - signer.address, - transaction, - "0xaabbccddeeff" - ); - - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Hello") - .withArgs(AddressZero); - }); - - it("contract signature, bad return size", async () => { - const { testSignature, relayer } = await loadFixture(setup); - - const Signer = await hre.ethers.getContractFactory( - "ContractSignerReturnSize" - ); - const signer = await Signer.deploy(); - - const transaction = await testSignature.populateTransaction.hello(); - - const signature = makeContractSignature( - signer.address, - transaction, - "0xaabbccddeeff" - ); - - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Hello") - .withArgs(AddressZero); - }); - - it("contract signature, signer with faulty entrypoint", async () => { - const { testSignature, relayer } = await loadFixture(setup); - - const Signer = await hre.ethers.getContractFactory("ContractSignerFaulty"); - const signer = await Signer.deploy(); - - const transaction = await testSignature.populateTransaction.hello(); - - const signature = makeContractSignature( - signer.address, - transaction, - "0xaabbccddeeff" - ); - - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Hello") - .withArgs(AddressZero); - }); - - it("contract signature, signer with no code deployed", async () => { - const { testSignature, relayer } = await loadFixture(setup); - - const signerAddress = "0x1234567890000000000000000000000123456789"; - - await expect(await hre.ethers.provider.getCode(signerAddress)).to.equal( - "0x" - ); - - const transaction = await testSignature.populateTransaction.hello(); - - const signature = makeContractSignature( - signerAddress, - transaction, - "0xaabbccddeeff" - ); - - const transactionWithSig = { - ...transaction, - data: `${transaction.data}${signature.slice(2)}`, - }; - - await expect(await relayer.sendTransaction(transactionWithSig)) - .to.emit(testSignature, "Hello") - .withArgs(AddressZero); - }); - it("it publicly exposes the eip712 nonce", async () => { const { testSignature } = await loadFixture(setup); expect(await testSignature.moduleTxNonce()).to.equal(0); }); + + describe("contract signature", () => { + it("s pointing out of bounds fails", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerYes" + ); + const signer = (await ContractSigner.deploy()).address; + + const transaction = await testSignature.populateTransaction.hello(); + + // 4 bytes of selector plus 3 bytes of custom signature + // an s of 4, 5 or 6 should be okay. 7 and higher should fail + let signature = makeContractSignature( + signer, + transaction, + "0xdddddd", + defaultAbiCoder.encode(["uint256"], [1000]) + ); + + await expect( + await relayer.sendTransaction({ + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }) + ) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + + signature = makeContractSignature( + signer, + transaction, + "0xdddddd", + defaultAbiCoder.encode(["uint256"], [6]) + ); + + await expect( + await relayer.sendTransaction({ + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }) + ) + .to.emit(testSignature, "Hello") + .withArgs(signer); + }); + it("s pointing to selector fails", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerYes" + ); + const signer = (await ContractSigner.deploy()).address; + + const transaction = await testSignature.populateTransaction.hello(); + + let signature = makeContractSignature( + signer, + transaction, + "0xdddddd", + defaultAbiCoder.encode(["uint256"], [3]) + ); + + await expect( + await relayer.sendTransaction({ + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }) + ) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + + signature = makeContractSignature( + signer, + transaction, + "0xdddddd", + defaultAbiCoder.encode(["uint256"], [4]) + ); + + await expect( + await relayer.sendTransaction({ + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }) + ) + .to.emit(testSignature, "Hello") + .withArgs(signer); + }); + it("s pointing to signature fails", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerYes" + ); + const signer = (await ContractSigner.deploy()).address; + + const transaction = await testSignature.populateTransaction.hello(); + + let signature = makeContractSignature( + signer, + transaction, + "0xdddddd", + defaultAbiCoder.encode(["uint256"], [60]) + ); + + await expect( + await relayer.sendTransaction({ + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }) + ) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + + signature = makeContractSignature( + signer, + transaction, + "0xdddddd", + defaultAbiCoder.encode(["uint256"], [6]) + ); + + await expect( + await relayer.sendTransaction({ + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }) + ) + .to.emit(testSignature, "Hello") + .withArgs(signer); + }); + + it("signer returns isValid yes", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerYes" + ); + const contractSigner = await ContractSigner.deploy(); + + const transaction = await testSignature.populateTransaction.goodbye( + 0, + "0xbadfed" + ); + + const signature = makeContractSignature( + contractSigner.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(contractSigner.address); + }); + + it("signer returns isValid no", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const Signer = await hre.ethers.getContractFactory("ContractSignerNo"); + const signer = await Signer.deploy(); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signer.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("signer bad return size", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const Signer = await hre.ethers.getContractFactory( + "ContractSignerReturnSize" + ); + const signer = await Signer.deploy(); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signer.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("signer with faulty entrypoint", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const Signer = await hre.ethers.getContractFactory( + "ContractSignerFaulty" + ); + const signer = await Signer.deploy(); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signer.address, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + + it("signer with no code deployed", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const signerAddress = "0x1234567890000000000000000000000123456789"; + + await expect(await hre.ethers.provider.getCode(signerAddress)).to.equal( + "0x" + ); + + const transaction = await testSignature.populateTransaction.hello(); + + const signature = makeContractSignature( + signerAddress, + transaction, + "0xaabbccddeeff" + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signature.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(testSignature, "Hello") + .withArgs(AddressZero); + }); + }); }); async function sign( @@ -220,15 +353,16 @@ async function sign( } function makeContractSignature( - contract: string, + signer: string, transaction: PopulatedTransaction, - signature: string + signerSpecificSignature: string, + s?: string ) { const dataBytesLength = (transaction.data?.length as number) / 2 - 1; - const r = defaultAbiCoder.encode(["address"], [contract]); - const s = defaultAbiCoder.encode(["uint256"], [dataBytesLength]); + const r = defaultAbiCoder.encode(["address"], [signer]); + s = s || defaultAbiCoder.encode(["uint256"], [dataBytesLength]); const v = solidityPack(["uint8"], [0]); - return `${signature}${r.slice(2)}${s.slice(2)}${v.slice(2)}`; + return `${signerSpecificSignature}${r.slice(2)}${s.slice(2)}${v.slice(2)}`; } From 23e5ea83177f2203626415702cf9f9a5e9d7b242 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sun, 1 Oct 2023 23:00:03 +0200 Subject: [PATCH 24/82] Adjust comments --- contracts/signature/SignatureChecker.sol | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 65163cfc..b8a933f5 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0 <0.9.0; import "./IERC1271.sol"; -/// @title SignatureChecker - A contract that validates signatures appended to calldata. +/// @title SignatureChecker - A contract that validates signatures appended to transaction calldata. /// @dev currently supports eip-712 and eip-1271 abstract contract SignatureChecker { uint256 private nonce; @@ -19,24 +19,24 @@ abstract contract SignatureChecker { } /** - * @notice Searches for a valid signature, and returns address of signer. - * @dev When signature not found or not valid, Zero address is returned + * @notice Searches for a signature, validates it, and returns the signer's address. + * @dev When signature not found or invalid, zero address is returned * @return the address of the signer. */ function moduleTxSignedBy() internal view returns (address) { bytes calldata data = msg.data; /* - * The idea is to extend `onlyModule` and provide signature checking - * to modules, without code changes. + * The idea is to extend `onlyModule` and provide signature checking, + * without code changes to inheriting contracts. * - * Since it's a generic mechanism we don't have a definitive way to - * know if the trailling bytes are a signature. We just slice those + * Since it's a generic mechanism, there is no way to conclusively + * identify the trailing bytes as a signature. We simply slice those * out and recover signer. * - * Hence, we require the calldata to be at least as long as a function - * selector plus a signature - 4 + 65. Anything less than that is - * guaranteed to not contain a signature + * As a result, we impose a minimum calldata length equal to a function + * selector plus a signature (i.e., 4 + 65 bytes). Any calldata shorter + * than that is guaranteed to not contain a signature. */ if (data.length < 4 + 65) { return address(0); @@ -68,7 +68,7 @@ abstract contract SignatureChecker { } /** - * @notice Hashes the EIP-712 data structure. + * @notice Hashes the transaction EIP-712 data structure. * @dev The produced hash is intended to be signed. * @param data The current transaction's calldata. * @param _nonce The nonce value. @@ -96,7 +96,7 @@ abstract contract SignatureChecker { * @return v The ECDSA v value * @return r The ECDSA r value * @return s The ECDSA s value - * @return isEIP1271Signature Indicates whether it is a contract signature + * @return isEIP1271Signature Indicates whether the split signature is a contract signature * @return start offset in calldata where signature starts */ function _splitSignature( @@ -121,7 +121,8 @@ abstract contract SignatureChecker { * * We detect contract signatures by the following two conditions: * 1- `v` is zero - * 2- `s` points within the buffer, is after selector and before sig + * 2- `s` points within the buffer and is after selector and before + * signature * * The data pointed by s should be non zero, as EIP-1271 describes a * a non-zero length signer specific signature @@ -138,8 +139,8 @@ abstract contract SignatureChecker { } /** - * @dev Calls the signer contract, and validates signature. - * @param signer The address of the signer. + * @dev Calls the signer contract, and validates the contract signature. + * @param signer The address of the signer contract. * @param txHash The hash of the message that was signed. * @param signature The signature to validate. * @return result indicates whether the signature is valid. From a8dc26255f270d4ce51d2500417adfaf6b4f943d Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Mon, 2 Oct 2023 07:25:48 +0200 Subject: [PATCH 25/82] Adjust comments --- contracts/signature/SignatureChecker.sol | 47 ++++++++++++------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index b8a933f5..292c244e 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -3,12 +3,12 @@ pragma solidity >=0.8.0 <0.9.0; import "./IERC1271.sol"; -/// @title SignatureChecker - A contract that validates signatures appended to transaction calldata. -/// @dev currently supports eip-712 and eip-1271 +/// @title SignatureChecker - A contract that retrieves and validates signatures appended to transaction calldata. +/// @dev currently supports eip-712 and eip-1271 signatures abstract contract SignatureChecker { uint256 private nonce; - /// @notice Returns the current nonce value. + /// @notice Returns the current nonce. function moduleTxNonce() public view returns (uint256) { return nonce; } @@ -21,22 +21,22 @@ abstract contract SignatureChecker { /** * @notice Searches for a signature, validates it, and returns the signer's address. * @dev When signature not found or invalid, zero address is returned - * @return the address of the signer. + * @return The address of the signer. */ function moduleTxSignedBy() internal view returns (address) { bytes calldata data = msg.data; /* - * The idea is to extend `onlyModule` and provide signature checking, - * without code changes to inheriting contracts. + * The idea is to extend `onlyModule` and provide signature checking + * without code changes to inheriting contracts (Modifiers). * * Since it's a generic mechanism, there is no way to conclusively * identify the trailing bytes as a signature. We simply slice those - * out and recover signer. + * and recover signer. * * As a result, we impose a minimum calldata length equal to a function - * selector plus a signature (i.e., 4 + 65 bytes). Any calldata shorter - * than that is guaranteed to not contain a signature. + * selector plus a signature (i.e., 4 + 65 bytes), any shorter and + * calldata it guaranteed to not contain a signature. */ if (data.length < 4 + 65) { return address(0); @@ -50,20 +50,20 @@ abstract contract SignatureChecker { uint256 start ) = _splitSignature(data); - bytes32 txHash = moduleTxHash(data[:start], nonce); + bytes32 hash = moduleTxHash(data[:start], nonce); if (isContractSignature) { address signer = address(uint160(uint256(r))); return _isValidContractSignature( signer, - txHash, + hash, data[start:data.length - 65] ) ? signer : address(0); } else { - return ecrecover(txHash, v, r, s); + return ecrecover(hash, v, r, s); } } @@ -119,13 +119,10 @@ abstract contract SignatureChecker { * s - contains the offset within calldata where the signer specific * signature is located * - * We detect contract signatures by the following two conditions: + * We detect contract signatures by checking: * 1- `v` is zero - * 2- `s` points within the buffer and is after selector and before - * signature - * - * The data pointed by s should be non zero, as EIP-1271 describes a - * a non-zero length signer specific signature + * 2- `s` points within the buffer, is after selector, is before + * signature and delimits a non-zero length buffer */ uint256 length = data.length; v = uint8(bytes1(data[length - 1:])); @@ -141,13 +138,13 @@ abstract contract SignatureChecker { /** * @dev Calls the signer contract, and validates the contract signature. * @param signer The address of the signer contract. - * @param txHash The hash of the message that was signed. - * @param signature The signature to validate. - * @return result indicates whether the signature is valid. + * @param hash Hash of the data signed + * @param signature The contract signature. + * @return result Indicates whether the signature is valid. */ function _isValidContractSignature( address signer, - bytes32 txHash, + bytes32 hash, bytes calldata signature ) internal view returns (bool result) { uint256 size; @@ -161,7 +158,7 @@ abstract contract SignatureChecker { (, bytes memory returnData) = signer.staticcall( abi.encodeWithSelector( IERC1271.isValidSignature.selector, - txHash, + hash, signature ) ); @@ -181,6 +178,8 @@ abstract contract SignatureChecker { bytes32 private constant MODULE_TX_TYPEHASH = 0xd6c6b5df57eef4e79cab990a377d29dc4c5bbb016a6293120d53f49c54144227; - // bytes4(keccak256("isValidSignature(bytes32,bytes)") + // bytes4(keccak256( + // "isValidSignature(bytes32,bytes)" + // )); bytes4 private constant EIP1271_MAGIC_VALUE = 0x1626ba7e; } From fa34352fb6aa0aa7441362202d4de42df5f392d0 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Wed, 4 Oct 2023 07:39:45 +0200 Subject: [PATCH 26/82] Introduce GuardableModule and GuardableModifier - this makes Module and Modifier leaner by default --- contracts/core/GuardableModifier.sol | 87 +++++++++++++++++++++++++++ contracts/core/GuardableModule.sol | 88 ++++++++++++++++++++++++++++ contracts/core/Modifier.sol | 9 +-- contracts/core/Module.sol | 62 +++++--------------- contracts/test/TestGuard.sol | 10 +--- contracts/test/TestModule.sol | 4 +- test/01_IAvatar.spec.ts | 7 ++- test/03_Modifier.spec.ts | 21 ++++--- 8 files changed, 216 insertions(+), 72 deletions(-) create mode 100644 contracts/core/GuardableModifier.sol create mode 100644 contracts/core/GuardableModule.sol diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol new file mode 100644 index 00000000..705a5d2f --- /dev/null +++ b/contracts/core/GuardableModifier.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.7.0 <0.9.0; + +import "../guard/Guardable.sol"; +import "./Modifier.sol"; + +abstract contract GuardableModifier is Module, Guardable, Modifier { + /// @dev Passes a transaction to be executed by the avatar. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function exec( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal override returns (bool success) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + msg.sender + ); + } + success = IAvatar(target).execTransactionFromModule( + to, + value, + data, + operation + ); + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution("", success); + } + } + + /// @dev Passes a transaction to be executed by the target and returns data. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execAndReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal override returns (bool success, bytes memory returnData) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + msg.sender + ); + } + + (success, returnData) = IAvatar(target) + .execTransactionFromModuleReturnData(to, value, data, operation); + + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution("", success); + } + } +} diff --git a/contracts/core/GuardableModule.sol b/contracts/core/GuardableModule.sol new file mode 100644 index 00000000..35c36cf2 --- /dev/null +++ b/contracts/core/GuardableModule.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.7.0 <0.9.0; + +import "../guard/Guardable.sol"; +import "./Module.sol"; + +/// @title GuardableModule - A contract that can pass messages to a Module Manager contract if enabled by that contract. +abstract contract GuardableModule is Module, Guardable { + /// @dev Passes a transaction to be executed by the avatar. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function exec( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal override returns (bool success) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + msg.sender + ); + } + success = IAvatar(target).execTransactionFromModule( + to, + value, + data, + operation + ); + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution("", success); + } + } + + /// @dev Passes a transaction to be executed by the target and returns data. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execAndReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal override returns (bool success, bytes memory returnData) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + msg.sender + ); + } + + (success, returnData) = IAvatar(target) + .execTransactionFromModuleReturnData(to, value, data, operation); + + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution("", success); + } + } +} diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 160898c1..a539d6cc 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: LGPL-3.0-only - -/// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. pragma solidity >=0.7.0 <0.9.0; -import "./Module.sol"; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + import "../interfaces/IAvatar.sol"; import "../signature/SignatureChecker.sol"; +import "./Module.sol"; -abstract contract Modifier is Module, IAvatar, SignatureChecker { +/// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. +abstract contract Modifier is Module, SignatureChecker, IAvatar { address internal constant SENTINEL_MODULES = address(0x1); /// Mapping of modules. mapping(address => address) internal modules; diff --git a/contracts/core/Module.sol b/contracts/core/Module.sol index 04b292a8..dbf37f95 100644 --- a/contracts/core/Module.sol +++ b/contracts/core/Module.sol @@ -1,13 +1,11 @@ // SPDX-License-Identifier: LGPL-3.0-only - -/// @title Module Interface - A contract that can pass messages to a Module Manager contract if enabled by that contract. pragma solidity >=0.7.0 <0.9.0; -import "../interfaces/IAvatar.sol"; import "../factory/FactoryFriendly.sol"; -import "../guard/Guardable.sol"; +import "../interfaces/IAvatar.sol"; -abstract contract Module is FactoryFriendly, Guardable { +/// @title Module Interface - A contract that can pass messages to a Module Manager contract if enabled by that contract. +abstract contract Module is FactoryFriendly { /// @dev Address that will ultimately execute function calls. address public avatar; /// @dev Address that this module will pass transactions to. @@ -45,8 +43,14 @@ abstract contract Module is FactoryFriendly, Guardable { uint256 value, bytes memory data, Enum.Operation operation - ) internal returns (bool success) { - (success, ) = _exec(to, value, data, operation); + ) internal virtual returns (bool success) { + return + IAvatar(target).execTransactionFromModule( + to, + value, + data, + operation + ); } /// @dev Passes a transaction to be executed by the target and returns data. @@ -60,49 +64,13 @@ abstract contract Module is FactoryFriendly, Guardable { uint256 value, bytes memory data, Enum.Operation operation - ) internal returns (bool success, bytes memory returnData) { - (success, returnData) = _exec(to, value, data, operation); - } - - function _exec( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) private returns (bool success, bytes memory returnData) { - address currentGuard = guard; - if (currentGuard != address(0)) { - IGuard(currentGuard).checkTransaction( - /// Transaction info used by module transactions. + ) internal virtual returns (bool success, bytes memory returnData) { + return + IAvatar(target).execTransactionFromModuleReturnData( to, value, data, - operation, - /// Zero out the redundant transaction information only used for Safe multisig transctions. - 0, - 0, - 0, - address(0), - payable(0), - "", - msg.sender + operation ); - (success, returnData) = IAvatar(target) - .execTransactionFromModuleReturnData( - to, - value, - data, - operation - ); - IGuard(currentGuard).checkAfterExecution("", success); - } else { - (success, returnData) = IAvatar(target) - .execTransactionFromModuleReturnData( - to, - value, - data, - operation - ); - } } } diff --git a/contracts/test/TestGuard.sol b/contracts/test/TestGuard.sol index de63f73b..8dc75d70 100644 --- a/contracts/test/TestGuard.sol +++ b/contracts/test/TestGuard.sol @@ -1,13 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only - -/// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. pragma solidity >=0.7.0 <0.9.0; -import "../guard/BaseGuard.sol"; -import "../factory/FactoryFriendly.sol"; -import "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "../core/Module.sol"; +import "../core/GuardableModule.sol"; contract TestGuard is FactoryFriendly, BaseGuard { event PreChecked(bool checked); @@ -46,7 +40,7 @@ contract TestGuard is FactoryFriendly, BaseGuard { function checkAfterExecution(bytes32, bool) public override { require( - Module(module).guard() == address(this), + GuardableModule(module).guard() == address(this), "Module cannot remove its own guard." ); emit PostChecked(true); diff --git a/contracts/test/TestModule.sol b/contracts/test/TestModule.sol index 0e8e7e2c..6df4e5ea 100644 --- a/contracts/test/TestModule.sol +++ b/contracts/test/TestModule.sol @@ -3,9 +3,9 @@ /// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. pragma solidity >=0.7.0 <0.9.0; -import "../core/Module.sol"; +import "../core/GuardableModule.sol"; -contract TestModule is Module { +contract TestModule is GuardableModule { constructor(address _avatar, address _target) { bytes memory initParams = abi.encode(_avatar, _target); setUp(initParams); diff --git a/test/01_IAvatar.spec.ts b/test/01_IAvatar.spec.ts index 60efd22c..8fae82e6 100644 --- a/test/01_IAvatar.spec.ts +++ b/test/01_IAvatar.spec.ts @@ -3,15 +3,16 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import hre from "hardhat"; +import { TestAvatar__factory } from "../typechain-types"; describe("IAvatar", async () => { async function setupTests() { + const [signer] = await hre.ethers.getSigners(); const Avatar = await hre.ethers.getContractFactory("TestAvatar"); - const avatar = await Avatar.deploy(); - const iAvatar = await hre.ethers.getContractAt("IAvatar", avatar.address); + const avatar = await Avatar.connect(signer).deploy(); + const iAvatar = TestAvatar__factory.connect(avatar.address, signer); const tx = { to: avatar.address, - value: 0, data: "0x", operation: 0, diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 7bcb91df..e040338c 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -6,17 +6,22 @@ import { PopulatedTransaction } from "ethers"; import hre from "hardhat"; import typedDataForTransaction from "./typesDataForTransaction"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { TestModifier__factory } from "../typechain-types"; +import { TestAvatar__factory, TestModifier__factory } from "../typechain-types"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; async function setupTests() { + const [signer] = await hre.ethers.getSigners(); const Avatar = await hre.ethers.getContractFactory("TestAvatar"); - const avatar = await Avatar.deploy(); - const iAvatar = await hre.ethers.getContractAt("IAvatar", avatar.address); + const avatar = await Avatar.connect(signer).deploy(); + const iAvatar = TestAvatar__factory.connect(avatar.address, signer); const Modifier = await hre.ethers.getContractFactory("TestModifier"); - const modifier = await Modifier.deploy(iAvatar.address, iAvatar.address); + const modifier = await Modifier.connect(signer).deploy( + iAvatar.address, + iAvatar.address + ); + await iAvatar.enableModule(modifier.address); const tx = { to: avatar.address, @@ -32,7 +37,7 @@ describe("Modifier", async () => { }; return { iAvatar, - modifier, + modifier: TestModifier__factory.connect(modifier.address, signer), tx, }; } @@ -244,9 +249,9 @@ describe("Modifier", async () => { const { modifier } = await loadFixture(setupTests); const [user1, user2, user3] = await hre.ethers.getSigners(); - await expect(modifier.enableModule(user1.address)); - await expect(modifier.enableModule(user2.address)); - await expect(modifier.enableModule(user3.address)); + await modifier.enableModule(user1.address); + await modifier.enableModule(user2.address); + await modifier.enableModule(user3.address); await expect(await modifier.isModuleEnabled(user1.address)).to.be.true; await expect(await modifier.isModuleEnabled(user2.address)).to.be.true; From f150e32373abd2d0d91b7bb0c2152b3f6a3a106e Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sat, 7 Oct 2023 16:29:11 +0200 Subject: [PATCH 27/82] GuardableModifier tests --- contracts/test/TestGuardableModifier.sol | 87 +++++++++++ test/07_GuardableModifier.spec.ts | 180 +++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 contracts/test/TestGuardableModifier.sol create mode 100644 test/07_GuardableModifier.spec.ts diff --git a/contracts/test/TestGuardableModifier.sol b/contracts/test/TestGuardableModifier.sol new file mode 100644 index 00000000..98333afd --- /dev/null +++ b/contracts/test/TestGuardableModifier.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.7.0 <0.9.0; + +import "../core/GuardableModifier.sol"; + +contract TestGuardableModifier is GuardableModifier { + event executed( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bool success + ); + + event executedAndReturnedData( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bytes returnData, + bool success + ); + + constructor(address _avatar, address _target) { + bytes memory initParams = abi.encode(_avatar, _target); + setUp(initParams); + } + + /// @dev Passes a transaction to the modifier. + /// @param to Destination address of module transaction + /// @param value Ether value of module transaction + /// @param data Data payload of module transaction + /// @param operation Operation type of module transaction + /// @notice Can only be called by enabled modules + function execTransactionFromModule( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public override moduleOnly returns (bool success) { + success = exec(to, value, data, operation); + emit executed(to, value, data, operation, success); + } + + /// @dev Passes a transaction to the modifier, expects return data. + /// @param to Destination address of module transaction + /// @param value Ether value of module transaction + /// @param data Data payload of module transaction + /// @param operation Operation type of module transaction + /// @notice Can only be called by enabled modules + function execTransactionFromModuleReturnData( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) + public + override + moduleOnly + returns (bool success, bytes memory returnData) + { + (success, returnData) = execAndReturnData(to, value, data, operation); + emit executedAndReturnedData( + to, + value, + data, + operation, + returnData, + success + ); + } + + function setUp(bytes memory initializeParams) public override initializer { + setupModules(); + __Ownable_init(); + (address _avatar, address _target) = abi.decode( + initializeParams, + (address, address) + ); + avatar = _avatar; + target = _target; + } + + function attemptToSetupModules() public { + setupModules(); + } +} diff --git a/test/07_GuardableModifier.spec.ts b/test/07_GuardableModifier.spec.ts new file mode 100644 index 00000000..723b64d3 --- /dev/null +++ b/test/07_GuardableModifier.spec.ts @@ -0,0 +1,180 @@ +import hre from "hardhat"; +import { expect } from "chai"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; + +import { + TestAvatar__factory, + TestGuard__factory, + TestGuardableModifier__factory, +} from "../typechain-types"; + +describe("GuardableModifier", async () => { + async function setupTests() { + const [signer, someone, executor] = await hre.ethers.getSigners(); + + const Avatar = await hre.ethers.getContractFactory("TestAvatar"); + const avatar = TestAvatar__factory.connect( + (await Avatar.deploy()).address, + signer + ); + + const Modifier = await hre.ethers.getContractFactory( + "TestGuardableModifier" + ); + const modifier = TestGuardableModifier__factory.connect( + (await Modifier.connect(signer).deploy(avatar.address, avatar.address)) + .address, + signer + ); + const Guard = await hre.ethers.getContractFactory("TestGuard"); + const guard = TestGuard__factory.connect( + (await Guard.deploy(modifier.address)).address, + hre.ethers.provider + ); + + await avatar.enableModule(modifier.address); + await modifier.enableModule(executor.address); + + return { + avatar, + someone, + executor, + guard, + modifier, + }; + } + + describe("exec", async () => { + it("skips guard pre-check if no guard is set", async () => { + const { avatar, modifier, executor } = await loadFixture(setupTests); + + await expect( + modifier + .connect(executor) + .execTransactionFromModule(avatar.address, 0, "0x", 0) + ).to.not.be.reverted; + }); + + it("pre-checks transaction if guard is set", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + await modifier.setGuard(guard.address); + + await expect( + modifier + .connect(executor) + .execTransactionFromModule(avatar.address, 0, "0x", 0) + ) + .to.emit(guard, "PreChecked") + .withArgs(true); + }); + + it("pre-checks and reverts transaction if guard is set", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + await modifier.setGuard(guard.address); + + await expect( + modifier + .connect(executor) + .execTransactionFromModule(avatar.address, 1337, "0x", 0) + ).to.be.revertedWith("Cannot send 1337"); + }); + + it("skips post-check if no guard is enabled", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + + await expect( + modifier + .connect(executor) + .execTransactionFromModule(avatar.address, 0, "0x", 0) + ).not.to.emit(guard, "PostChecked"); + }); + + it("post-checks transaction if guard is set", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + await modifier.setGuard(guard.address); + + await expect( + modifier + .connect(executor) + .execTransactionFromModule(avatar.address, 0, "0x", 0) + ) + .to.emit(guard, "PostChecked") + .withArgs(true); + }); + }); + + describe("execAndReturnData", async () => { + it("skips guard pre-check if no guard is set", async () => { + const { avatar, modifier, executor } = await loadFixture(setupTests); + + await expect( + modifier + .connect(executor) + .execTransactionFromModuleReturnData(avatar.address, 0, "0x", 0) + ).to.not.be.reverted; + }); + + it("pre-checks transaction if guard is set", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + await modifier.setGuard(guard.address); + + await expect( + modifier + .connect(executor) + .execTransactionFromModuleReturnData(avatar.address, 0, "0x", 0) + ) + .to.emit(guard, "PreChecked") + .withArgs(true); + }); + + it("pre-checks and reverts transaction if guard is set", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + await modifier.setGuard(guard.address); + + await expect( + modifier + .connect(executor) + .execTransactionFromModuleReturnData(avatar.address, 1337, "0x", 0) + ).to.be.revertedWith("Cannot send 1337"); + }); + + it("skips post-check if no guard is enabled", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + + await expect( + modifier + .connect(executor) + .execTransactionFromModuleReturnData(avatar.address, 0, "0x", 0) + ).not.to.emit(guard, "PostChecked"); + }); + + it("post-checks transaction if guard is set", async () => { + const { avatar, executor, modifier, guard } = await loadFixture( + setupTests + ); + await modifier.setGuard(guard.address); + + await expect( + modifier + .connect(executor) + .execTransactionFromModuleReturnData(avatar.address, 0, "0x", 0) + ) + .to.emit(guard, "PostChecked") + .withArgs(true); + }); + }); +}); From 0edfe89970623335319e153bbdfa76ac16b42982 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sat, 7 Oct 2023 16:41:56 +0200 Subject: [PATCH 28/82] Bumping OpenZeppeling for bytecode optimized base classes --- contracts/test/TestGuardableModifier.sol | 2 +- contracts/test/TestModifier.sol | 2 +- contracts/test/TestModule.sol | 2 +- hardhat.config.ts | 2 +- package.json | 4 ++-- test/02_Module.spec.ts | 16 ++++++++-------- test/03_Modifier.spec.ts | 10 ++++++---- test/04_Guard.spec.ts | 6 +++--- yarn.lock | 18 +++++++++--------- 9 files changed, 32 insertions(+), 30 deletions(-) diff --git a/contracts/test/TestGuardableModifier.sol b/contracts/test/TestGuardableModifier.sol index 98333afd..6e38457c 100644 --- a/contracts/test/TestGuardableModifier.sol +++ b/contracts/test/TestGuardableModifier.sol @@ -72,7 +72,7 @@ contract TestGuardableModifier is GuardableModifier { function setUp(bytes memory initializeParams) public override initializer { setupModules(); - __Ownable_init(); + __Ownable_init(msg.sender); (address _avatar, address _target) = abi.decode( initializeParams, (address, address) diff --git a/contracts/test/TestModifier.sol b/contracts/test/TestModifier.sol index dac3c745..8629d8a5 100644 --- a/contracts/test/TestModifier.sol +++ b/contracts/test/TestModifier.sol @@ -74,7 +74,7 @@ contract TestModifier is Modifier { function setUp(bytes memory initializeParams) public override initializer { setupModules(); - __Ownable_init(); + __Ownable_init(msg.sender); (address _avatar, address _target) = abi.decode( initializeParams, (address, address) diff --git a/contracts/test/TestModule.sol b/contracts/test/TestModule.sol index 6df4e5ea..5e6d2ce4 100644 --- a/contracts/test/TestModule.sol +++ b/contracts/test/TestModule.sol @@ -55,7 +55,7 @@ contract TestModule is GuardableModule { } function setUp(bytes memory initializeParams) public override initializer { - __Ownable_init(); + __Ownable_init(msg.sender); (address _avatar, address _target) = abi.decode( initializeParams, (address, address) diff --git a/hardhat.config.ts b/hardhat.config.ts index 02b6634d..53497ee1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -53,7 +53,7 @@ export default { solidity: { compilers: [ { - version: "0.8.6", + version: "0.8.20", settings: { optimizer: { enabled: true, diff --git a/package.json b/package.json index facb29b8..85feb289 100644 --- a/package.json +++ b/package.json @@ -89,8 +89,8 @@ "dependencies": { "@gnosis.pm/mock-contract": "^4.0.0", "@gnosis.pm/safe-contracts": "1.3.0", - "@openzeppelin/contracts": "^4.8.1", - "@openzeppelin/contracts-upgradeable": "^4.8.1", + "@openzeppelin/contracts": "^5.0.0", + "@openzeppelin/contracts-upgradeable": "^5.0.0", "ethers": "^5.7.1" } } \ No newline at end of file diff --git a/test/02_Module.spec.ts b/test/02_Module.spec.ts index 0e7fe537..61578c48 100644 --- a/test/02_Module.spec.ts +++ b/test/02_Module.spec.ts @@ -37,12 +37,12 @@ describe("Module", async () => { it("reverts if caller is not the owner", async () => { const { iAvatar, module } = await loadFixture(setupTests); - const [, wallet1] = await hre.ethers.getSigners(); + const [owner, wallet1] = await hre.ethers.getSigners(); await module.transferOwnership(wallet1.address); - await expect(module.setAvatar(iAvatar.address)).to.be.revertedWith( - "Ownable: caller is not the owner" - ); + await expect(module.setAvatar(iAvatar.address)) + .to.be.revertedWithCustomError(module, "OwnableUnauthorizedAccount") + .withArgs(owner.address); }); it("allows owner to set avatar", async () => { @@ -64,11 +64,11 @@ describe("Module", async () => { describe("setTarget", async () => { it("reverts if caller is not the owner", async () => { const { iAvatar, module } = await loadFixture(setupTests); - const [, wallet1] = await hre.ethers.getSigners(); + const [owner, wallet1] = await hre.ethers.getSigners(); await module.transferOwnership(wallet1.address); - await expect(module.setTarget(iAvatar.address)).to.be.revertedWith( - "Ownable: caller is not the owner" - ); + await expect(module.setTarget(iAvatar.address)) + .to.be.revertedWithCustomError(module, "OwnableUnauthorizedAccount") + .withArgs(owner.address); }); it("allows owner to set avatar", async () => { diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index e040338c..6eb0021e 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -56,9 +56,9 @@ describe("Modifier", async () => { const [, user2] = await hre.ethers.getSigners(); - await expect( - modifier.connect(user2).enableModule(user2.address) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(modifier.connect(user2).enableModule(user2.address)) + .to.be.revertedWithCustomError(modifier, "OwnableUnauthorizedAccount") + .withArgs(user2.address); }); it("reverts if module is zero address", async () => { @@ -103,7 +103,9 @@ describe("Modifier", async () => { const [, user2] = await hre.ethers.getSigners(); await expect( modifier.connect(user2).disableModule(SENTINEL_MODULES, user2.address) - ).to.be.revertedWith("Ownable: caller is not the owner"); + ) + .to.be.revertedWithCustomError(modifier, "OwnableUnauthorizedAccount") + .withArgs(user2.address); }); it("reverts if module is zero address", async () => { diff --git a/test/04_Guard.spec.ts b/test/04_Guard.spec.ts index 0faced25..68a78a40 100644 --- a/test/04_Guard.spec.ts +++ b/test/04_Guard.spec.ts @@ -24,9 +24,9 @@ describe("Guardable", async () => { it("reverts if reverts if caller is not the owner", async () => { const { module } = await loadFixture(setupTests); const [, user1] = await hre.ethers.getSigners(); - await expect( - module.connect(user1).setGuard(user1.address) - ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(module.connect(user1).setGuard(user1.address)) + .to.be.revertedWithCustomError(module, "OwnableUnauthorizedAccount") + .withArgs(user1.address); }); it("reverts if guard does not implement ERC165", async () => { diff --git a/yarn.lock b/yarn.lock index f25a8c38..9dd61e90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -793,15 +793,15 @@ table "^6.8.0" undici "^5.14.0" -"@openzeppelin/contracts-upgradeable@^4.8.1": - version "4.8.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.3.tgz#6b076a7b751811b90fe3a172a7faeaa603e13a3f" - integrity sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg== +"@openzeppelin/contracts-upgradeable@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.0.tgz#859c00c55f04b6dda85b3c88bce507d65019888f" + integrity sha512-D54RHzkOKHQ8xUssPgQe2d/U92mwaiBDY7qCCVGq6VqwQjsT3KekEQ3bonev+BLP30oZ0R1U6YC8/oLpizgC5Q== -"@openzeppelin/contracts@^4.8.1": - version "4.8.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" - integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== +"@openzeppelin/contracts@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c" + integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw== "@pkgjs/parseargs@^0.11.0": version "0.11.0" @@ -5978,4 +5978,4 @@ yocto-queue@^0.1.0: zksync-web3@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.3.tgz#64ac2a16d597464c3fc4ae07447a8007631c57c9" - integrity sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ== \ No newline at end of file + integrity sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ== From 043a62a58cbdf5add56b5357da5928c834acec32 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Sat, 7 Oct 2023 16:47:47 +0200 Subject: [PATCH 29/82] remove import --- contracts/core/Modifier.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index a539d6cc..a1ff0e9f 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - import "../interfaces/IAvatar.sol"; import "../signature/SignatureChecker.sol"; import "./Module.sol"; From 2d33510e594ee2fcc6765c23e094ab37f1b83364 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Mon, 9 Oct 2023 01:39:56 +0200 Subject: [PATCH 30/82] Mark exec functions as virtual for Guardable* --- contracts/core/GuardableModifier.sol | 13 +++++++++---- contracts/core/GuardableModule.sol | 11 ++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 705a5d2f..60df8762 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -16,7 +16,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { uint256 value, bytes memory data, Enum.Operation operation - ) internal override returns (bool success) { + ) internal virtual override returns (bool success) { address currentGuard = guard; if (currentGuard != address(0)) { IGuard(currentGuard).checkTransaction( @@ -42,7 +42,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { operation ); if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution("", success); + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } } @@ -57,7 +57,12 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { uint256 value, bytes memory data, Enum.Operation operation - ) internal override returns (bool success, bytes memory returnData) { + ) + internal + virtual + override + returns (bool success, bytes memory returnData) + { address currentGuard = guard; if (currentGuard != address(0)) { IGuard(currentGuard).checkTransaction( @@ -81,7 +86,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { .execTransactionFromModuleReturnData(to, value, data, operation); if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution("", success); + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } } } diff --git a/contracts/core/GuardableModule.sol b/contracts/core/GuardableModule.sol index 35c36cf2..94fb3fb2 100644 --- a/contracts/core/GuardableModule.sol +++ b/contracts/core/GuardableModule.sol @@ -43,7 +43,7 @@ abstract contract GuardableModule is Module, Guardable { operation ); if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution("", success); + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } } @@ -58,7 +58,12 @@ abstract contract GuardableModule is Module, Guardable { uint256 value, bytes memory data, Enum.Operation operation - ) internal override returns (bool success, bytes memory returnData) { + ) + internal + virtual + override + returns (bool success, bytes memory returnData) + { address currentGuard = guard; if (currentGuard != address(0)) { IGuard(currentGuard).checkTransaction( @@ -82,7 +87,7 @@ abstract contract GuardableModule is Module, Guardable { .execTransactionFromModuleReturnData(to, value, data, operation); if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution("", success); + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } } } From 47fe8b5c2c2d43c2ea9d1ff2d63f50bd02f1aff3 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Mon, 9 Oct 2023 01:40:49 +0200 Subject: [PATCH 31/82] Prettier --- contracts/factory/ModuleProxyFactory.sol | 8 ++++---- contracts/guard/BaseGuard.sol | 9 +++------ contracts/interfaces/IAvatar.sol | 8 ++++---- contracts/test/TestAvatar.sol | 9 ++++----- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/contracts/factory/ModuleProxyFactory.sol b/contracts/factory/ModuleProxyFactory.sol index b2e2921b..ff2e26dc 100644 --- a/contracts/factory/ModuleProxyFactory.sol +++ b/contracts/factory/ModuleProxyFactory.sol @@ -19,10 +19,10 @@ contract ModuleProxyFactory { /// @notice Initialization failed. error FailedInitialization(); - function createProxy(address target, bytes32 salt) - internal - returns (address result) - { + function createProxy( + address target, + bytes32 salt + ) internal returns (address result) { if (address(target) == address(0)) revert ZeroAddress(target); if (address(target).code.length == 0) revert TargetHasNoCode(target); bytes memory deployment = abi.encodePacked( diff --git a/contracts/guard/BaseGuard.sol b/contracts/guard/BaseGuard.sol index 96d3d8c7..6e892bbc 100644 --- a/contracts/guard/BaseGuard.sol +++ b/contracts/guard/BaseGuard.sol @@ -6,12 +6,9 @@ import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../interfaces/IGuard.sol"; abstract contract BaseGuard is IERC165 { - function supportsInterface(bytes4 interfaceId) - external - pure - override - returns (bool) - { + function supportsInterface( + bytes4 interfaceId + ) external pure override returns (bool) { return interfaceId == type(IGuard).interfaceId || // 0xe6d7a83a interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7 diff --git a/contracts/interfaces/IAvatar.sol b/contracts/interfaces/IAvatar.sol index c757611d..7c4ebfdc 100644 --- a/contracts/interfaces/IAvatar.sol +++ b/contracts/interfaces/IAvatar.sol @@ -64,8 +64,8 @@ interface IAvatar { /// @param pageSize Maximum number of modules that should be returned. /// @return array Array of modules. /// @return next Start of the next page. - function getModulesPaginated(address start, uint256 pageSize) - external - view - returns (address[] memory array, address next); + function getModulesPaginated( + address start, + uint256 pageSize + ) external view returns (address[] memory array, address next); } diff --git a/contracts/test/TestAvatar.sol b/contracts/test/TestAvatar.sol index e0309848..a3399efd 100644 --- a/contracts/test/TestAvatar.sol +++ b/contracts/test/TestAvatar.sol @@ -51,11 +51,10 @@ contract TestAvatar { else (success, returnData) = to.call{value: value}(data); } - function getModulesPaginated(address, uint256 pageSize) - external - view - returns (address[] memory array, address next) - { + function getModulesPaginated( + address, + uint256 pageSize + ) external view returns (address[] memory array, address next) { // Init array with max page size array = new address[](pageSize); From 9b63f0ca61e915c68221e6f092fe7ffc07c28db2 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Mon, 9 Oct 2023 10:43:39 +0200 Subject: [PATCH 32/82] Make execTransactionFromModule virtual --- contracts/core/Modifier.sol | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index a1ff0e9f..7452f024 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -30,12 +30,6 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { /// @dev `setModules()` was already called. error SetupModulesAlreadyCalled(); - /* - -------------------------------------------------- - You must override at least one of following two virtual functions, - execTransactionFromModule() and execTransactionFromModuleReturnData(). - */ - /// @dev Passes a transaction to the modifier. /// @notice Can only be called by enabled modules. /// @param to Destination address of module transaction. @@ -47,7 +41,7 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { uint256 value, bytes calldata data, Enum.Operation operation - ) public virtual override moduleOnly returns (bool success) {} + ) public virtual returns (bool success); /// @dev Passes a transaction to the modifier, expects return data. /// @notice Can only be called by enabled modules. @@ -60,17 +54,7 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { uint256 value, bytes calldata data, Enum.Operation operation - ) - public - virtual - override - moduleOnly - returns (bool success, bytes memory returnData) - {} - - /* - -------------------------------------------------- - */ + ) public virtual returns (bool success, bytes memory returnData); modifier moduleOnly() { if (modules[msg.sender] == address(0)) { From 0c4de8562dd43e249e2d71b07a8825e7e61c33ca Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Mon, 9 Oct 2023 10:48:25 +0200 Subject: [PATCH 33/82] Add comment to Modifier.sol --- contracts/core/Modifier.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 7452f024..b050b36c 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -30,6 +30,14 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { /// @dev `setModules()` was already called. error SetupModulesAlreadyCalled(); + /* + -------------------------------------------------- + You must override both of the following virtual functions, + execTransactionFromModule() and execTransactionFromModuleReturnData(). + It is recommended that implementations of both functions make use the + onlyModule modifier. + */ + /// @dev Passes a transaction to the modifier. /// @notice Can only be called by enabled modules. /// @param to Destination address of module transaction. @@ -56,6 +64,10 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { Enum.Operation operation ) public virtual returns (bool success, bytes memory returnData); + /* + -------------------------------------------------- + */ + modifier moduleOnly() { if (modules[msg.sender] == address(0)) { if (modules[moduleTxSignedBy()] == address(0)) { From 54cf05a1b38d071af98538b474b5ff2e1d680fbe Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 11:11:59 +0200 Subject: [PATCH 34/82] Break down Modifier authorization logic in reusable parts --- contracts/core/Modifier.sol | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index b050b36c..2b5ce002 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -69,16 +69,31 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { */ modifier moduleOnly() { - if (modules[msg.sender] == address(0)) { - if (modules[moduleTxSignedBy()] == address(0)) { - revert NotAuthorized(msg.sender); - } + (bool isAuthorized, address module) = isModuleTxAuthorized(); + if (!isAuthorized) { + revert NotAuthorized(msg.sender); + } + + if (module != msg.sender) { moduleTxNonceBump(); } _; } + function isModuleTxAuthorized() internal returns (bool, address) { + if (modules[msg.sender] != address(0)) { + return (true, msg.sender); + } + + address signer = moduleTxSignedBy(); + if (modules[signer] != address(0)) { + return (true, signer); + } + + return (false, address(0)); + } + /// @dev Disables a module on the modifier. /// @notice This can only be called by the owner. /// @param prevModule Module that pointed to the module to be removed in the linked list. From 860f93ae6d130bfeccdb220bad6a00187d194c67 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 12:05:40 +0200 Subject: [PATCH 35/82] Add failing tests --- contracts/test/TestGuard.sol | 6 +- test/02_Module.spec.ts | 8 +-- test/04_Guard.spec.ts | 4 +- test/07_GuardableModifier.spec.ts | 100 +++++++++++++++++++++++++++--- 4 files changed, 98 insertions(+), 20 deletions(-) diff --git a/contracts/test/TestGuard.sol b/contracts/test/TestGuard.sol index 8dc75d70..c1323045 100644 --- a/contracts/test/TestGuard.sol +++ b/contracts/test/TestGuard.sol @@ -4,7 +4,7 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/GuardableModule.sol"; contract TestGuard is FactoryFriendly, BaseGuard { - event PreChecked(bool checked); + event PreChecked(address sender); event PostChecked(bool checked); address public module; @@ -29,13 +29,13 @@ contract TestGuard is FactoryFriendly, BaseGuard { address, address payable, bytes memory, - address + address sender ) public override { require(to != address(0), "Cannot send to zero address"); require(value != 1337, "Cannot send 1337"); require(bytes3(data) != bytes3(0xbaddad), "Cannot call 0xbaddad"); require(operation != Enum.Operation(1), "No delegate calls"); - emit PreChecked(true); + emit PreChecked(sender); } function checkAfterExecution(bytes32, bool) public override { diff --git a/test/02_Module.spec.ts b/test/02_Module.spec.ts index 61578c48..f2d03b33 100644 --- a/test/02_Module.spec.ts +++ b/test/02_Module.spec.ts @@ -98,9 +98,7 @@ describe("Module", async () => { await module.setGuard(guard.address); await expect( module.executeTransaction(tx.to, tx.value, tx.data, tx.operation) - ) - .to.emit(guard, "PreChecked") - .withArgs(true); + ).to.emit(guard, "PreChecked"); }); it("executes a transaction", async () => { @@ -151,9 +149,7 @@ describe("Module", async () => { tx.data, tx.operation ) - ) - .to.emit(guard, "PreChecked") - .withArgs(true); + ).to.emit(guard, "PreChecked"); }); it("executes a transaction", async () => { diff --git a/test/04_Guard.spec.ts b/test/04_Guard.spec.ts index 68a78a40..af802bff 100644 --- a/test/04_Guard.spec.ts +++ b/test/04_Guard.spec.ts @@ -120,9 +120,7 @@ describe("BaseGuard", async () => { tx.signatures, user1.address ) - ) - .to.emit(guard, "PreChecked") - .withArgs(true); + ).to.emit(guard, "PreChecked"); }); }); diff --git a/test/07_GuardableModifier.spec.ts b/test/07_GuardableModifier.spec.ts index 723b64d3..e3f71cfc 100644 --- a/test/07_GuardableModifier.spec.ts +++ b/test/07_GuardableModifier.spec.ts @@ -7,24 +7,28 @@ import { TestGuard__factory, TestGuardableModifier__factory, } from "../typechain-types"; +import typedDataForTransaction from "./typesDataForTransaction"; +import { PopulatedTransaction } from "ethers"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; describe("GuardableModifier", async () => { async function setupTests() { - const [signer, someone, executor] = await hre.ethers.getSigners(); + const [deployer, executor, signer, someone, relayer] = + await hre.ethers.getSigners(); const Avatar = await hre.ethers.getContractFactory("TestAvatar"); const avatar = TestAvatar__factory.connect( (await Avatar.deploy()).address, - signer + deployer ); const Modifier = await hre.ethers.getContractFactory( "TestGuardableModifier" ); const modifier = TestGuardableModifier__factory.connect( - (await Modifier.connect(signer).deploy(avatar.address, avatar.address)) + (await Modifier.connect(deployer).deploy(avatar.address, avatar.address)) .address, - signer + deployer ); const Guard = await hre.ethers.getContractFactory("TestGuard"); const guard = TestGuard__factory.connect( @@ -36,9 +40,11 @@ describe("GuardableModifier", async () => { await modifier.enableModule(executor.address); return { - avatar, - someone, executor, + signer, + someone, + relayer, + avatar, guard, modifier, }; @@ -67,7 +73,40 @@ describe("GuardableModifier", async () => { .execTransactionFromModule(avatar.address, 0, "0x", 0) ) .to.emit(guard, "PreChecked") - .withArgs(true); + .withArgs(executor.address); + }); + + it("pre-check gets called with signer when transaction is relayed", async () => { + const { signer, modifier, relayer, avatar, guard } = await loadFixture( + setupTests + ); + + await modifier.enableModule(signer.address); + await modifier.setGuard(guard.address); + + const inner = await avatar.populateTransaction.enableModule( + "0xff00000000000000000000000000000000ff3456" + ); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModule( + avatar.address, + 0, + inner.data as string, + 0 + ); + + const signature = await sign(modifier.address, transaction, signer); + const transactionWithSig = { + ...transaction, + to: modifier.address, + data: `${transaction.data}${signature.slice(2)}`, + value: 0, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(guard, "PreChecked") + .withArgs(signer.address); }); it("pre-checks and reverts transaction if guard is set", async () => { @@ -134,7 +173,40 @@ describe("GuardableModifier", async () => { .execTransactionFromModuleReturnData(avatar.address, 0, "0x", 0) ) .to.emit(guard, "PreChecked") - .withArgs(true); + .withArgs(executor.address); + }); + + it("pre-check gets called with signer when transaction is relayed", async () => { + const { signer, modifier, relayer, avatar, guard } = await loadFixture( + setupTests + ); + + await modifier.enableModule(signer.address); + await modifier.setGuard(guard.address); + + const inner = await avatar.populateTransaction.enableModule( + "0xff00000000000000000000000000000000ff3456" + ); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModuleReturnData( + avatar.address, + 0, + inner.data as string, + 0 + ); + + const signature = await sign(modifier.address, transaction, signer); + const transactionWithSig = { + ...transaction, + to: modifier.address, + data: `${transaction.data}${signature.slice(2)}`, + value: 0, + }; + + await expect(await relayer.sendTransaction(transactionWithSig)) + .to.emit(guard, "PreChecked") + .withArgs(signer.address); }); it("pre-checks and reverts transaction if guard is set", async () => { @@ -178,3 +250,15 @@ describe("GuardableModifier", async () => { }); }); }); + +async function sign( + contract: string, + transaction: PopulatedTransaction, + signer: SignerWithAddress +) { + const { domain, types, message } = typedDataForTransaction( + { contract, chainId: 31337, nonce: 0 }, + transaction.data || "0x" + ); + return await signer._signTypedData(domain, types, message); +} From 4ef408c665ae7c020788635489317bc620dee3ef Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 13:18:51 +0200 Subject: [PATCH 36/82] Changing the base SignatureChecker to work with user proposed salt, instead of self managed nonce --- contracts/core/GuardableModifier.sol | 4 +- contracts/core/Modifier.sol | 19 ++-- contracts/signature/SignatureChecker.sol | 49 ++++------ contracts/test/TestSignature.sol | 6 +- test/03_Modifier.spec.ts | 2 +- test/06_SignatureChecker.spec.ts | 97 ++++++++++++------- test/07_GuardableModifier.spec.ts | 2 +- ...nsaction.ts => typedDataForTransaction.ts} | 8 +- 8 files changed, 100 insertions(+), 87 deletions(-) rename test/{typesDataForTransaction.ts => typedDataForTransaction.ts} (82%) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 60df8762..95ae2959 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -32,7 +32,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - msg.sender + authorizer() ); } success = IAvatar(target).execTransactionFromModule( @@ -78,7 +78,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - msg.sender + authorizer() ); } diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 2b5ce002..a0b070cd 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -69,29 +69,26 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { */ modifier moduleOnly() { - (bool isAuthorized, address module) = isModuleTxAuthorized(); - if (!isAuthorized) { - revert NotAuthorized(msg.sender); - } + address module = authorizer(); - if (module != msg.sender) { - moduleTxNonceBump(); + if (module == address(0)) { + revert NotAuthorized(msg.sender); } _; } - function isModuleTxAuthorized() internal returns (bool, address) { + function authorizer() internal returns (address) { if (modules[msg.sender] != address(0)) { - return (true, msg.sender); + return msg.sender; } - address signer = moduleTxSignedBy(); + (, address signer) = moduleTxSignedBy(); if (modules[signer] != address(0)) { - return (true, signer); + return signer; } - return (false, address(0)); + return address(0); } /// @dev Disables a module on the modifier. diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 292c244e..5d9c2b5d 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -6,24 +6,12 @@ import "./IERC1271.sol"; /// @title SignatureChecker - A contract that retrieves and validates signatures appended to transaction calldata. /// @dev currently supports eip-712 and eip-1271 signatures abstract contract SignatureChecker { - uint256 private nonce; - - /// @notice Returns the current nonce. - function moduleTxNonce() public view returns (uint256) { - return nonce; - } - - /// @notice Increments nonce. - function moduleTxNonceBump() internal { - nonce = nonce + 1; - } - /** * @notice Searches for a signature, validates it, and returns the signer's address. * @dev When signature not found or invalid, zero address is returned * @return The address of the signer. */ - function moduleTxSignedBy() internal view returns (address) { + function moduleTxSignedBy() internal view returns (bytes32, address) { bytes calldata data = msg.data; /* @@ -35,11 +23,11 @@ abstract contract SignatureChecker { * and recover signer. * * As a result, we impose a minimum calldata length equal to a function - * selector plus a signature (i.e., 4 + 65 bytes), any shorter and - * calldata it guaranteed to not contain a signature. + * selector plus salt, plus a signature (i.e., 4 + 32 + 65 bytes), any + * shorter and calldata it guaranteed to not contain a signature. */ - if (data.length < 4 + 65) { - return address(0); + if (data.length < 4 + 32 + 65) { + return (bytes32(0), address(0)); } ( @@ -50,7 +38,10 @@ abstract contract SignatureChecker { uint256 start ) = _splitSignature(data); - bytes32 hash = moduleTxHash(data[:start], nonce); + bytes32 hash = moduleTxHash( + data[:start], // slice the appended signature out + bytes32(data[data.length - 65 - 32:]) // get the salt + ); if (isContractSignature) { address signer = address(uint160(uint256(r))); @@ -60,10 +51,10 @@ abstract contract SignatureChecker { hash, data[start:data.length - 65] ) - ? signer - : address(0); + ? (hash, signer) + : (bytes32(0), address(0)); } else { - return ecrecover(hash, v, r, s); + return (hash, ecrecover(hash, v, r, s)); } } @@ -71,12 +62,12 @@ abstract contract SignatureChecker { * @notice Hashes the transaction EIP-712 data structure. * @dev The produced hash is intended to be signed. * @param data The current transaction's calldata. - * @param _nonce The nonce value. + * @param salt The salt value. * @return The 32-byte hash that is to be signed. */ function moduleTxHash( bytes calldata data, - uint256 _nonce + bytes32 salt ) public view returns (bytes32) { bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) @@ -85,7 +76,7 @@ abstract contract SignatureChecker { bytes1(0x19), bytes1(0x01), domainSeparator, - keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), _nonce)) + keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), salt)) ); return keccak256(moduleTxData); } @@ -122,7 +113,7 @@ abstract contract SignatureChecker { * We detect contract signatures by checking: * 1- `v` is zero * 2- `s` points within the buffer, is after selector, is before - * signature and delimits a non-zero length buffer + * salt and delimits a non-zero length buffer */ uint256 length = data.length; v = uint8(bytes1(data[length - 1:])); @@ -131,8 +122,8 @@ abstract contract SignatureChecker { isEIP1271Signature = v == 0 && uint256(s) > 3 && - uint256(s) < (length - 65); - start = isEIP1271Signature ? uint256(s) : length - 65; + uint256(s) < (length - 65 - 32); + start = isEIP1271Signature ? uint256(s) : length - 65 - 32; } /** @@ -173,10 +164,10 @@ abstract contract SignatureChecker { 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; // keccak256( - // "ModuleTx(bytes data,uint256 nonce)" + // "ModuleTx(bytes data,bytes32 salt)" // ); bytes32 private constant MODULE_TX_TYPEHASH = - 0xd6c6b5df57eef4e79cab990a377d29dc4c5bbb016a6293120d53f49c54144227; + 0x2939aeeda3ca260200c9f7b436b19e13207547ccc65cfedc857751c5ea6d91d4; // bytes4(keccak256( // "isValidSignature(bytes32,bytes)" diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index 5a76edd9..7242e6d4 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -38,10 +38,12 @@ contract TestSignature is SignatureChecker { event Goodbye(address signer); function hello() public { - emit Hello(moduleTxSignedBy()); + (, address signer) = moduleTxSignedBy(); + emit Hello(signer); } function goodbye(uint256, bytes memory) public { - emit Goodbye(moduleTxSignedBy()); + (, address signer) = moduleTxSignedBy(); + emit Goodbye(signer); } } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 6eb0021e..ce1bf614 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -4,7 +4,7 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { PopulatedTransaction } from "ethers"; import hre from "hardhat"; -import typedDataForTransaction from "./typesDataForTransaction"; +import typedDataForTransaction from "./typedDataForTransaction"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { TestAvatar__factory, TestModifier__factory } from "../typechain-types"; diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 5d7c0de3..3acc4869 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -5,10 +5,15 @@ import { PopulatedTransaction } from "ethers"; import { expect } from "chai"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import typedDataForTransaction from "./typesDataForTransaction"; -import { defaultAbiCoder, solidityPack } from "ethers/lib/utils"; - -describe("SignatureChecker", async () => { +import typedDataForTransaction from "./typedDataForTransaction"; +import { + defaultAbiCoder, + keccak256, + solidityPack, + toUtf8Bytes, +} from "ethers/lib/utils"; + +describe.only("SignatureChecker", async () => { async function setup() { const [signer, relayer] = await hre.ethers.getSigners(); const TestSignature = await hre.ethers.getContractFactory("TestSignature"); @@ -30,7 +35,12 @@ describe("SignatureChecker", async () => { const { testSignature, signer, relayer } = await loadFixture(setup); const transaction = await testSignature.populateTransaction.hello(); - const signature = await sign(testSignature.address, transaction, signer); + const signature = await sign( + testSignature.address, + transaction, + keccak256(toUtf8Bytes("Hello this is a salt")), + signer + ); const transactionWithSig = { ...transaction, data: `${transaction.data}${signature.slice(2)}`, @@ -52,7 +62,12 @@ describe("SignatureChecker", async () => { 0, "0xbadfed" ); - const signature = await sign(testSignature.address, transaction, signer); + const signature = await sign( + testSignature.address, + transaction, + keccak256(toUtf8Bytes("salt")), + signer + ); const transactionWithSig = { ...transaction, data: `${transaction.data}${signature.slice(2)}`, @@ -67,11 +82,6 @@ describe("SignatureChecker", async () => { .withArgs(signer.address); }); - it("it publicly exposes the eip712 nonce", async () => { - const { testSignature } = await loadFixture(setup); - expect(await testSignature.moduleTxNonce()).to.equal(0); - }); - describe("contract signature", () => { it("s pointing out of bounds fails", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -86,9 +96,10 @@ describe("SignatureChecker", async () => { // 4 bytes of selector plus 3 bytes of custom signature // an s of 4, 5 or 6 should be okay. 7 and higher should fail let signature = makeContractSignature( - signer, transaction, "0xdddddd", + keccak256(toUtf8Bytes("salt")), + signer, defaultAbiCoder.encode(["uint256"], [1000]) ); @@ -102,9 +113,10 @@ describe("SignatureChecker", async () => { .withArgs(AddressZero); signature = makeContractSignature( - signer, transaction, "0xdddddd", + keccak256(toUtf8Bytes("salt")), + signer, defaultAbiCoder.encode(["uint256"], [6]) ); @@ -128,9 +140,10 @@ describe("SignatureChecker", async () => { const transaction = await testSignature.populateTransaction.hello(); let signature = makeContractSignature( - signer, transaction, "0xdddddd", + keccak256(toUtf8Bytes("salt")), + signer, defaultAbiCoder.encode(["uint256"], [3]) ); @@ -144,9 +157,10 @@ describe("SignatureChecker", async () => { .withArgs(AddressZero); signature = makeContractSignature( - signer, transaction, "0xdddddd", + keccak256(toUtf8Bytes("salt")), + signer, defaultAbiCoder.encode(["uint256"], [4]) ); @@ -170,9 +184,10 @@ describe("SignatureChecker", async () => { const transaction = await testSignature.populateTransaction.hello(); let signature = makeContractSignature( - signer, transaction, "0xdddddd", + keccak256(toUtf8Bytes("salt")), + signer, defaultAbiCoder.encode(["uint256"], [60]) ); @@ -186,9 +201,10 @@ describe("SignatureChecker", async () => { .withArgs(AddressZero); signature = makeContractSignature( - signer, transaction, "0xdddddd", + keccak256(toUtf8Bytes("salt")), + signer, defaultAbiCoder.encode(["uint256"], [6]) ); @@ -201,7 +217,6 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Hello") .withArgs(signer); }); - it("signer returns isValid yes", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -216,9 +231,10 @@ describe("SignatureChecker", async () => { ); const signature = makeContractSignature( - contractSigner.address, transaction, - "0xaabbccddeeff" + "0xaabbccddeeff", + keccak256(toUtf8Bytes("salt")), + contractSigner.address ); const transactionWithSig = { @@ -234,7 +250,6 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Goodbye") .withArgs(contractSigner.address); }); - it("signer returns isValid no", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -244,9 +259,10 @@ describe("SignatureChecker", async () => { const transaction = await testSignature.populateTransaction.hello(); const signature = makeContractSignature( - signer.address, transaction, - "0xaabbccddeeff" + "0xaabbccddeeff", + keccak256(toUtf8Bytes("salt")), + signer.address ); const transactionWithSig = { @@ -258,7 +274,6 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Hello") .withArgs(AddressZero); }); - it("signer bad return size", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -270,9 +285,10 @@ describe("SignatureChecker", async () => { const transaction = await testSignature.populateTransaction.hello(); const signature = makeContractSignature( - signer.address, transaction, - "0xaabbccddeeff" + "0xaabbccddeeff", + keccak256(toUtf8Bytes("salt")), + signer.address ); const transactionWithSig = { @@ -284,7 +300,6 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Hello") .withArgs(AddressZero); }); - it("signer with faulty entrypoint", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -296,9 +311,10 @@ describe("SignatureChecker", async () => { const transaction = await testSignature.populateTransaction.hello(); const signature = makeContractSignature( - signer.address, transaction, - "0xaabbccddeeff" + "0xaabbccddeeff", + keccak256(toUtf8Bytes("salt")), + signer.address ); const transactionWithSig = { @@ -310,7 +326,6 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Hello") .withArgs(AddressZero); }); - it("signer with no code deployed", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -323,9 +338,10 @@ describe("SignatureChecker", async () => { const transaction = await testSignature.populateTransaction.hello(); const signature = makeContractSignature( - signerAddress, transaction, - "0xaabbccddeeff" + "0xaabbccddeeff", + keccak256(toUtf8Bytes("salt")), + signerAddress ); const transactionWithSig = { @@ -343,26 +359,33 @@ describe("SignatureChecker", async () => { async function sign( contract: string, transaction: PopulatedTransaction, + salt: string, signer: SignerWithAddress ) { const { domain, types, message } = typedDataForTransaction( - { contract, chainId: 31337, nonce: 0 }, + { contract, chainId: 31337, salt }, transaction.data || "0x" ); - return await signer._signTypedData(domain, types, message); + + const signature = await signer._signTypedData(domain, types, message); + + return `${salt}${signature.slice(2)}`; } function makeContractSignature( - signer: string, transaction: PopulatedTransaction, signerSpecificSignature: string, + salt: string, + r: string, s?: string ) { const dataBytesLength = (transaction.data?.length as number) / 2 - 1; - const r = defaultAbiCoder.encode(["address"], [signer]); + r = defaultAbiCoder.encode(["address"], [r]); s = s || defaultAbiCoder.encode(["uint256"], [dataBytesLength]); const v = solidityPack(["uint8"], [0]); - return `${signerSpecificSignature}${r.slice(2)}${s.slice(2)}${v.slice(2)}`; + return `${signerSpecificSignature}${salt.slice(2)}${r.slice(2)}${s.slice( + 2 + )}${v.slice(2)}`; } diff --git a/test/07_GuardableModifier.spec.ts b/test/07_GuardableModifier.spec.ts index e3f71cfc..6dbe3aeb 100644 --- a/test/07_GuardableModifier.spec.ts +++ b/test/07_GuardableModifier.spec.ts @@ -7,7 +7,7 @@ import { TestGuard__factory, TestGuardableModifier__factory, } from "../typechain-types"; -import typedDataForTransaction from "./typesDataForTransaction"; +import typedDataForTransaction from "./typedDataForTransaction"; import { PopulatedTransaction } from "ethers"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; diff --git a/test/typesDataForTransaction.ts b/test/typedDataForTransaction.ts similarity index 82% rename from test/typesDataForTransaction.ts rename to test/typedDataForTransaction.ts index 351bd952..81f4d175 100644 --- a/test/typesDataForTransaction.ts +++ b/test/typedDataForTransaction.ts @@ -4,11 +4,11 @@ export default function typedDataForTransaction( { contract, chainId, - nonce, + salt, }: { contract: string; chainId: BigNumberish; - nonce: BigNumberish; + salt: string; }, data: string ) { @@ -16,12 +16,12 @@ export default function typedDataForTransaction( const types = { ModuleTx: [ { type: "bytes", name: "data" }, - { type: "uint256", name: "nonce" }, + { type: "bytes32", name: "salt" }, ], }; const message = { data, - nonce, + salt, }; return { domain, types, message }; From 1b86f9f75b5d1816e9e7d7c13538daca1eb3778f Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 14:09:22 +0200 Subject: [PATCH 37/82] Introduce execution tracking into Modifier.sol based on executed and invalidated hashes --- contracts/core/GuardableModifier.sol | 13 +- contracts/core/Modifier.sol | 41 ++-- contracts/signature/ExecutionTracker.sol | 12 ++ contracts/test/TestGuardableModifier.sol | 8 +- contracts/test/TestModifier.sol | 8 +- test/03_Modifier.spec.ts | 252 ++++++++++++++++++----- test/06_SignatureChecker.spec.ts | 2 +- test/07_GuardableModifier.spec.ts | 23 ++- 8 files changed, 283 insertions(+), 76 deletions(-) create mode 100644 contracts/signature/ExecutionTracker.sol diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 95ae2959..1203ac75 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -32,7 +32,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - authorizer() + _authorizer() ); } success = IAvatar(target).execTransactionFromModule( @@ -78,7 +78,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - authorizer() + _authorizer() ); } @@ -89,4 +89,13 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } } + + function _authorizer() private returns (address) { + if (modules[msg.sender] != address(0)) { + return msg.sender; + } + + (, address signer) = moduleTxSignedBy(); + return signer; + } } diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index a0b070cd..af96b549 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -2,11 +2,17 @@ pragma solidity >=0.7.0 <0.9.0; import "../interfaces/IAvatar.sol"; +import "../signature/ExecutionTracker.sol"; import "../signature/SignatureChecker.sol"; import "./Module.sol"; /// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. -abstract contract Modifier is Module, SignatureChecker, IAvatar { +abstract contract Modifier is + Module, + ExecutionTracker, + SignatureChecker, + IAvatar +{ address internal constant SENTINEL_MODULES = address(0x1); /// Mapping of modules. mapping(address => address) internal modules; @@ -15,6 +21,12 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { /// @param sender The address of the sender. error NotAuthorized(address sender); + /// @param hash already executed. + error HashAlreadyExecuted(bytes32 hash); + + /// @param hash already executed. + error HashInvalidated(bytes32 hash); + /// `module` is invalid. error InvalidModule(address module); @@ -69,26 +81,25 @@ abstract contract Modifier is Module, SignatureChecker, IAvatar { */ modifier moduleOnly() { - address module = authorizer(); + if (modules[msg.sender] == address(0)) { + (bytes32 hash, address signer) = moduleTxSignedBy(); - if (module == address(0)) { - revert NotAuthorized(msg.sender); - } + if (modules[signer] == address(0)) { + revert NotAuthorized(msg.sender); + } - _; - } + if (executed[signer][hash]) { + revert HashAlreadyExecuted(hash); + } - function authorizer() internal returns (address) { - if (modules[msg.sender] != address(0)) { - return msg.sender; - } + if (invalidated[signer][hash]) { + revert HashInvalidated(hash); + } - (, address signer) = moduleTxSignedBy(); - if (modules[signer] != address(0)) { - return signer; + executed[signer][hash] = true; } - return address(0); + _; } /// @dev Disables a module on the modifier. diff --git a/contracts/signature/ExecutionTracker.sol b/contracts/signature/ExecutionTracker.sol new file mode 100644 index 00000000..b9f21a0c --- /dev/null +++ b/contracts/signature/ExecutionTracker.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +/// @title ExecutionTracker - A contract that keeps track of executed and invalidated hashes +contract ExecutionTracker { + mapping(address => mapping(bytes32 => bool)) public executed; + mapping(address => mapping(bytes32 => bool)) public invalidated; + + function invalidate(bytes32 hash) external { + invalidated[msg.sender][hash] = true; + } +} diff --git a/contracts/test/TestGuardableModifier.sol b/contracts/test/TestGuardableModifier.sol index 6e38457c..4b2e02c2 100644 --- a/contracts/test/TestGuardableModifier.sol +++ b/contracts/test/TestGuardableModifier.sol @@ -4,7 +4,7 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/GuardableModifier.sol"; contract TestGuardableModifier is GuardableModifier { - event executed( + event Executed( address to, uint256 value, bytes data, @@ -12,7 +12,7 @@ contract TestGuardableModifier is GuardableModifier { bool success ); - event executedAndReturnedData( + event ExecutedAndReturnedData( address to, uint256 value, bytes data, @@ -39,7 +39,7 @@ contract TestGuardableModifier is GuardableModifier { Enum.Operation operation ) public override moduleOnly returns (bool success) { success = exec(to, value, data, operation); - emit executed(to, value, data, operation, success); + emit Executed(to, value, data, operation, success); } /// @dev Passes a transaction to the modifier, expects return data. @@ -60,7 +60,7 @@ contract TestGuardableModifier is GuardableModifier { returns (bool success, bytes memory returnData) { (success, returnData) = execAndReturnData(to, value, data, operation); - emit executedAndReturnedData( + emit ExecutedAndReturnedData( to, value, data, diff --git a/contracts/test/TestModifier.sol b/contracts/test/TestModifier.sol index 8629d8a5..8746e78e 100644 --- a/contracts/test/TestModifier.sol +++ b/contracts/test/TestModifier.sol @@ -6,7 +6,7 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/Modifier.sol"; contract TestModifier is Modifier { - event executed( + event Executed( address to, uint256 value, bytes data, @@ -14,7 +14,7 @@ contract TestModifier is Modifier { bool success ); - event executedAndReturnedData( + event ExecutedAndReturnedData( address to, uint256 value, bytes data, @@ -41,7 +41,7 @@ contract TestModifier is Modifier { Enum.Operation operation ) public override moduleOnly returns (bool success) { success = exec(to, value, data, operation); - emit executed(to, value, data, operation, success); + emit Executed(to, value, data, operation, success); } /// @dev Passes a transaction to the modifier, expects return data. @@ -62,7 +62,7 @@ contract TestModifier is Modifier { returns (bool success, bytes memory returnData) { (success, returnData) = execAndReturnData(to, value, data, operation); - emit executedAndReturnedData( + emit ExecutedAndReturnedData( to, value, data, diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index ce1bf614..c5e31e4f 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -1,12 +1,15 @@ +import hre from "hardhat"; +import { expect } from "chai"; +import { PopulatedTransaction } from "ethers"; + import { AddressZero } from "@ethersproject/constants"; import { AddressOne } from "@gnosis.pm/safe-contracts"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; -import { expect } from "chai"; -import { PopulatedTransaction } from "ethers"; -import hre from "hardhat"; -import typedDataForTransaction from "./typedDataForTransaction"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; + +import typedDataForTransaction from "./typedDataForTransaction"; import { TestAvatar__factory, TestModifier__factory } from "../typechain-types"; +import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; @@ -316,7 +319,7 @@ describe("Modifier", async () => { tx.data, tx.operation ) - ).to.emit(modifier, "executed"); + ).to.emit(modifier, "Executed"); }); it("execute a transaction with signature.", async () => { const { modifier, tx } = await loadFixture(setupTests); @@ -333,7 +336,12 @@ describe("Modifier", async () => { tx.operation ); - const signature = await sign(modifier.address, transaction, user1); + const signature = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user1 + ); const transactionWithSig = { ...transaction, @@ -346,7 +354,7 @@ describe("Modifier", async () => { await expect(relayer.sendTransaction(transactionWithSig)).to.emit( modifier, - "executed" + "Executed" ); }); it("reverts if signature not valid.", async () => { @@ -364,8 +372,18 @@ describe("Modifier", async () => { tx.operation ); - const signatureOk = await sign(modifier.address, transaction, user1); - const signatureBad = await sign(modifier.address, transaction, user2); + const signatureOk = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user1 + ); + const signatureBad = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user2 + ); const transactionWithBadSig = { ...transaction, @@ -383,38 +401,65 @@ describe("Modifier", async () => { await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( modifier, - "executed" + "Executed" ); }); - it("execute a transaction via sender nonce stays same.", async () => { + it("reverts if signature previously used for execution.", async () => { const { modifier, tx } = await loadFixture(setupTests); - const [user1] = await hre.ethers.getSigners(); + const [user1, user2, relayer] = await hre.ethers.getSigners(); await expect(await modifier.enableModule(user1.address)) .to.emit(modifier, "EnabledModule") .withArgs(user1.address); - await expect( - modifier.execTransactionFromModule( + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModule( tx.to, tx.value, tx.data, tx.operation - ) - ).to.emit(modifier, "executed"); + ); - expect( - await TestModifier__factory.connect( - modifier.address, - hre.ethers.provider - ).moduleTxNonce() - ).to.equal(0); + const signatureOk = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user1 + ); + const signatureBad = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user2 + ); + + const transactionWithBadSig = { + ...transaction, + data: `${transaction.data}${signatureBad.slice(2)}`, + }; + + const transactionWithOkSig = { + ...transaction, + data: `${transaction.data}${signatureOk.slice(2)}`, + }; + + await expect( + relayer.sendTransaction(transactionWithBadSig) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); + + await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( + modifier, + "Executed" + ); + + await expect( + relayer.sendTransaction(transactionWithOkSig) + ).to.be.revertedWithCustomError(modifier, "HashAlreadyExecuted"); }); - it("execute a transaction with signature nonce is incremented.", async () => { + it("reverts if signature invalidated.", async () => { const { modifier, tx } = await loadFixture(setupTests); - const [user1, user2, relayer] = await hre.ethers.getSigners(); - await expect(await modifier.enableModule(user1.address)) - .to.emit(modifier, "EnabledModule") - .withArgs(user1.address); + const [user1, relayer] = await hre.ethers.getSigners(); + + await modifier.enableModule(user1.address); const { from, ...transaction } = await modifier.populateTransaction.execTransactionFromModule( @@ -424,24 +469,30 @@ describe("Modifier", async () => { tx.operation ); - const signature = await sign(modifier.address, transaction, user1); + const salt = keccak256(toUtf8Bytes("salt")); + + const signatureOk = await sign( + modifier.address, + transaction, + salt, + user1 + ); const transactionWithSig = { ...transaction, - data: `${transaction.data}${signature.slice(2)}`, + data: `${transaction.data}${signatureOk.slice(2)}`, }; - await expect(relayer.sendTransaction(transactionWithSig)).to.emit( - modifier, - "executed" + const hash = await modifier.moduleTxHash( + transaction.data as string, + salt ); - expect( - await TestModifier__factory.connect( - modifier.address, - hre.ethers.provider - ).moduleTxNonce() - ).to.equal(1); + await modifier.invalidate(hash); + + await expect( + relayer.sendTransaction(transactionWithSig) + ).to.be.revertedWithCustomError(modifier, "HashInvalidated"); }); }); @@ -473,7 +524,7 @@ describe("Modifier", async () => { tx.data, tx.operation ) - ).to.emit(modifier, "executedAndReturnedData"); + ).to.emit(modifier, "ExecutedAndReturnedData"); }); it("execute a transaction with signature.", async () => { const { modifier, tx } = await loadFixture(setupTests); @@ -490,7 +541,12 @@ describe("Modifier", async () => { tx.operation ); - const signature = await sign(modifier.address, transaction, user1); + const signature = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user1 + ); const transactionWithSig = { ...transaction, @@ -503,7 +559,7 @@ describe("Modifier", async () => { await expect(relayer.sendTransaction(transactionWithSig)).to.emit( modifier, - "executedAndReturnedData" + "ExecutedAndReturnedData" ); }); it("reverts if signature not valid.", async () => { @@ -521,8 +577,65 @@ describe("Modifier", async () => { tx.operation ); - const signatureBad = await sign(modifier.address, transaction, user2); - const signatureOk = await sign(modifier.address, transaction, user1); + const signatureBad = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user2 + ); + const signatureOk = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user1 + ); + + const transactionWithBadSig = { + ...transaction, + data: `${transaction.data}${signatureBad.slice(2)}`, + }; + + const transactionWithOkSig = { + ...transaction, + data: `${transaction.data}${signatureOk.slice(2)}`, + }; + + await expect( + relayer.sendTransaction(transactionWithBadSig) + ).to.be.revertedWithCustomError(modifier, "NotAuthorized"); + + await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( + modifier, + "ExecutedAndReturnedData" + ); + }); + it("reverts if signature previously used for execution.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, user2, relayer] = await hre.ethers.getSigners(); + await expect(await modifier.enableModule(user1.address)) + .to.emit(modifier, "EnabledModule") + .withArgs(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModuleReturnData( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const signatureOk = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user1 + ); + const signatureBad = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + user2 + ); const transactionWithBadSig = { ...transaction, @@ -540,8 +653,51 @@ describe("Modifier", async () => { await expect(relayer.sendTransaction(transactionWithOkSig)).to.emit( modifier, - "executedAndReturnedData" + "ExecutedAndReturnedData" + ); + + await expect( + relayer.sendTransaction(transactionWithOkSig) + ).to.be.revertedWithCustomError(modifier, "HashAlreadyExecuted"); + }); + it("reverts if signature invalidated.", async () => { + const { modifier, tx } = await loadFixture(setupTests); + const [user1, relayer] = await hre.ethers.getSigners(); + + await modifier.enableModule(user1.address); + + const { from, ...transaction } = + await modifier.populateTransaction.execTransactionFromModuleReturnData( + tx.to, + tx.value, + tx.data, + tx.operation + ); + + const salt = keccak256(toUtf8Bytes("salt")); + + const signatureOk = await sign( + modifier.address, + transaction, + salt, + user1 + ); + + const transactionWithSig = { + ...transaction, + data: `${transaction.data}${signatureOk.slice(2)}`, + }; + + const hash = await modifier.moduleTxHash( + transaction.data as string, + salt ); + + await modifier.invalidate(hash); + + await expect( + relayer.sendTransaction(transactionWithSig) + ).to.be.revertedWithCustomError(modifier, "HashInvalidated"); }); }); }); @@ -549,11 +705,15 @@ describe("Modifier", async () => { async function sign( contract: string, transaction: PopulatedTransaction, + salt: string, signer: SignerWithAddress ) { const { domain, types, message } = typedDataForTransaction( - { contract, chainId: 31337, nonce: 0 }, + { contract, chainId: 31337, salt }, transaction.data || "0x" ); - return signer._signTypedData(domain, types, message); + + const signature = await signer._signTypedData(domain, types, message); + + return `${salt}${signature.slice(2)}`; } diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 3acc4869..3343e199 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -13,7 +13,7 @@ import { toUtf8Bytes, } from "ethers/lib/utils"; -describe.only("SignatureChecker", async () => { +describe("SignatureChecker", async () => { async function setup() { const [signer, relayer] = await hre.ethers.getSigners(); const TestSignature = await hre.ethers.getContractFactory("TestSignature"); diff --git a/test/07_GuardableModifier.spec.ts b/test/07_GuardableModifier.spec.ts index 6dbe3aeb..40ff355a 100644 --- a/test/07_GuardableModifier.spec.ts +++ b/test/07_GuardableModifier.spec.ts @@ -10,6 +10,7 @@ import { import typedDataForTransaction from "./typedDataForTransaction"; import { PopulatedTransaction } from "ethers"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; describe("GuardableModifier", async () => { async function setupTests() { @@ -96,7 +97,12 @@ describe("GuardableModifier", async () => { 0 ); - const signature = await sign(modifier.address, transaction, signer); + const signature = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + signer + ); const transactionWithSig = { ...transaction, to: modifier.address, @@ -196,7 +202,12 @@ describe("GuardableModifier", async () => { 0 ); - const signature = await sign(modifier.address, transaction, signer); + const signature = await sign( + modifier.address, + transaction, + keccak256(toUtf8Bytes("salt")), + signer + ); const transactionWithSig = { ...transaction, to: modifier.address, @@ -254,11 +265,15 @@ describe("GuardableModifier", async () => { async function sign( contract: string, transaction: PopulatedTransaction, + salt: string, signer: SignerWithAddress ) { const { domain, types, message } = typedDataForTransaction( - { contract, chainId: 31337, nonce: 0 }, + { contract, chainId: 31337, salt }, transaction.data || "0x" ); - return await signer._signTypedData(domain, types, message); + + const signature = await signer._signTypedData(domain, types, message); + + return `${salt}${signature.slice(2)}`; } From 8e283ae77040e78d7db7bc8104c6704dbecbac53 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 15:42:24 +0200 Subject: [PATCH 38/82] Rename auxiliary function --- contracts/core/GuardableModifier.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 1203ac75..3ba9dec5 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -32,7 +32,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - _authorizer() + sentOrSignedBy() ); } success = IAvatar(target).execTransactionFromModule( @@ -78,7 +78,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - _authorizer() + sentOrSignedBy() ); } @@ -90,7 +90,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { } } - function _authorizer() private returns (address) { + function sentOrSignedBy() private returns (address) { if (modules[msg.sender] != address(0)) { return msg.sender; } From c5335310f1c05ede10d3c69b639e6d4d92e26c16 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 15:46:35 +0200 Subject: [PATCH 39/82] Moving the newly introducedd errors into ExecutionTracker --- contracts/core/GuardableModifier.sol | 2 +- contracts/core/Modifier.sol | 6 ------ contracts/signature/ExecutionTracker.sol | 3 +++ 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 3ba9dec5..6d8c0298 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -90,7 +90,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { } } - function sentOrSignedBy() private returns (address) { + function sentOrSignedBy() private view returns (address) { if (modules[msg.sender] != address(0)) { return msg.sender; } diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index af96b549..3c8c5ae6 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -21,12 +21,6 @@ abstract contract Modifier is /// @param sender The address of the sender. error NotAuthorized(address sender); - /// @param hash already executed. - error HashAlreadyExecuted(bytes32 hash); - - /// @param hash already executed. - error HashInvalidated(bytes32 hash); - /// `module` is invalid. error InvalidModule(address module); diff --git a/contracts/signature/ExecutionTracker.sol b/contracts/signature/ExecutionTracker.sol index b9f21a0c..a8e6e07f 100644 --- a/contracts/signature/ExecutionTracker.sol +++ b/contracts/signature/ExecutionTracker.sol @@ -3,6 +3,9 @@ pragma solidity >=0.8.0 <0.9.0; /// @title ExecutionTracker - A contract that keeps track of executed and invalidated hashes contract ExecutionTracker { + error HashAlreadyExecuted(bytes32); + error HashInvalidated(bytes32); + mapping(address => mapping(bytes32 => bool)) public executed; mapping(address => mapping(bytes32 => bool)) public invalidated; From e694b442370c65281ebcfb1d9ce7f6bf97920a76 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Thu, 12 Oct 2023 16:34:29 +0200 Subject: [PATCH 40/82] Fully cover guard with tests --- contracts/core/Modifier.sol | 3 + contracts/test/TestGuard.sol | 22 ++++++ contracts/test/TestModifier.sol | 4 +- test/04_Guard.spec.ts | 135 +++++++++++++++++++------------- 4 files changed, 108 insertions(+), 56 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 3c8c5ae6..ebf659fb 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -78,14 +78,17 @@ abstract contract Modifier is if (modules[msg.sender] == address(0)) { (bytes32 hash, address signer) = moduleTxSignedBy(); + // is the signer a module? if (modules[signer] == address(0)) { revert NotAuthorized(msg.sender); } + // is the provided signature fresh? if (executed[signer][hash]) { revert HashAlreadyExecuted(hash); } + // was the presented signature invalidated? if (invalidated[signer][hash]) { revert HashInvalidated(hash); } diff --git a/contracts/test/TestGuard.sol b/contracts/test/TestGuard.sol index c1323045..72bb06b1 100644 --- a/contracts/test/TestGuard.sol +++ b/contracts/test/TestGuard.sol @@ -51,3 +51,25 @@ contract TestGuard is FactoryFriendly, BaseGuard { module = _module; } } + +contract TestNonCompliantGuard is IERC165 { + function supportsInterface(bytes4) external pure returns (bool) { + return false; + } + + function checkTransaction( + address, + uint256, + bytes memory, + Enum.Operation, + uint256, + uint256, + uint256, + address, + address, + bytes memory, + address + ) public {} + + function checkAfterExecution(bytes32, bool) public {} +} diff --git a/contracts/test/TestModifier.sol b/contracts/test/TestModifier.sol index 8746e78e..e2bcc468 100644 --- a/contracts/test/TestModifier.sol +++ b/contracts/test/TestModifier.sol @@ -73,12 +73,12 @@ contract TestModifier is Modifier { } function setUp(bytes memory initializeParams) public override initializer { - setupModules(); - __Ownable_init(msg.sender); (address _avatar, address _target) = abi.decode( initializeParams, (address, address) ); + setupModules(); + _transferOwnership(msg.sender); avatar = _avatar; target = _target; } diff --git a/test/04_Guard.spec.ts b/test/04_Guard.spec.ts index af802bff..2914ddb2 100644 --- a/test/04_Guard.spec.ts +++ b/test/04_Guard.spec.ts @@ -1,32 +1,66 @@ -import { AddressZero } from "@ethersproject/constants"; -import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import hre from "hardhat"; -describe("Guardable", async () => { - async function setupTests() { - const Avatar = await hre.ethers.getContractFactory("TestAvatar"); - const avatar = await Avatar.deploy(); - const iAvatar = await hre.ethers.getContractAt("IAvatar", avatar.address); - const Module = await hre.ethers.getContractFactory("TestModule"); - const module = await Module.deploy(iAvatar.address, iAvatar.address); - await avatar.enableModule(module.address); - const Guard = await hre.ethers.getContractFactory("TestGuard"); - const guard = await Guard.deploy(module.address); - return { - iAvatar, - guard, - module, - }; - } +import { AddressZero } from "@ethersproject/constants"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import { TestGuard__factory, TestModule__factory } from "../typechain-types"; + +async function setupTests() { + const [owner, other, relayer] = await hre.ethers.getSigners(); + const Avatar = await hre.ethers.getContractFactory("TestAvatar"); + const avatar = await Avatar.deploy(); + const Module = await hre.ethers.getContractFactory("TestModule"); + const module = TestModule__factory.connect( + (await Module.connect(owner).deploy(avatar.address, avatar.address)) + .address, + owner + ); + await avatar.enableModule(module.address); + const Guard = await hre.ethers.getContractFactory("TestGuard"); + const guard = TestGuard__factory.connect( + (await Guard.deploy(module.address)).address, + relayer + ); + + const GuardNonCompliant = await hre.ethers.getContractFactory( + "TestNonCompliantGuard" + ); + const guardNonCompliant = TestGuard__factory.connect( + (await GuardNonCompliant.deploy()).address, + hre.ethers.provider + ); + + const tx = { + to: avatar.address, + value: 0, + data: "0x", + operation: 0, + avatarTxGas: 0, + baseGas: 0, + gasPrice: 0, + gasToken: AddressZero, + refundReceiver: AddressZero, + signatures: "0x", + }; + + return { + owner, + other, + module, + guard, + guardNonCompliant, + tx, + }; +} + +describe("Guardable", async () => { describe("setGuard", async () => { it("reverts if reverts if caller is not the owner", async () => { - const { module } = await loadFixture(setupTests); - const [, user1] = await hre.ethers.getSigners(); - await expect(module.connect(user1).setGuard(user1.address)) + const { other, guard, module } = await loadFixture(setupTests); + await expect(module.connect(other).setGuard(guard.address)) .to.be.revertedWithCustomError(module, "OwnableUnauthorizedAccount") - .withArgs(user1.address); + .withArgs(other.address); }); it("reverts if guard does not implement ERC165", async () => { @@ -34,12 +68,30 @@ describe("Guardable", async () => { await expect(module.setGuard(module.address)).to.be.reverted; }); + it("reverts if guard implements ERC165 and returns false", async () => { + const { module, guardNonCompliant } = await loadFixture(setupTests); + await expect(module.setGuard(guardNonCompliant.address)) + .to.be.revertedWithCustomError(module, "NotIERC165Compliant") + .withArgs(guardNonCompliant.address); + }); + it("sets module and emits event", async () => { const { module, guard } = await loadFixture(setupTests); await expect(module.setGuard(guard.address)) .to.emit(module, "ChangedGuard") .withArgs(guard.address); }); + + it("sets guard back to zero", async () => { + const { module, guard } = await loadFixture(setupTests); + await expect(module.setGuard(guard.address)) + .to.emit(module, "ChangedGuard") + .withArgs(guard.address); + + await expect(module.setGuard(AddressZero)) + .to.emit(module, "ChangedGuard") + .withArgs(AddressZero); + }); }); describe("getGuard", async () => { @@ -54,39 +106,15 @@ describe("BaseGuard", async () => { const txHash = "0x0000000000000000000000000000000000000000000000000000000000000001"; - async function setupTests() { - const Avatar = await hre.ethers.getContractFactory("TestAvatar"); - const avatar = await Avatar.deploy(); - const iAvatar = await hre.ethers.getContractAt("IAvatar", avatar.address); - const Module = await hre.ethers.getContractFactory("TestModule"); - const module = await Module.deploy(iAvatar.address, iAvatar.address); - await avatar.enableModule(module.address); - const Guard = await hre.ethers.getContractFactory("TestGuard"); - const guard = await Guard.deploy(module.address); - const tx = { - to: avatar.address, - value: 0, - data: "0x", - operation: 0, - avatarTxGas: 0, - baseGas: 0, - gasPrice: 0, - gasToken: AddressZero, - refundReceiver: AddressZero, - signatures: "0x", - }; - return { - iAvatar, - guard, - module, - tx, - }; - } + it("supports interface", async () => { + const { guard } = await loadFixture(setupTests); + expect(await guard.supportsInterface("0xe6d7a83a")).to.be.true; + expect(await guard.supportsInterface("0x01ffc9a7")).to.be.true; + }); describe("checkTransaction", async () => { it("reverts if test fails", async () => { const { guard, tx } = await loadFixture(setupTests); - const [user1] = await hre.ethers.getSigners(); await expect( guard.checkTransaction( tx.to, @@ -99,13 +127,12 @@ describe("BaseGuard", async () => { tx.gasToken, tx.refundReceiver, tx.signatures, - user1.address + AddressZero ) ).to.be.revertedWith("Cannot send 1337"); }); it("checks transaction", async () => { const { guard, tx } = await loadFixture(setupTests); - const [user1] = await hre.ethers.getSigners(); await expect( guard.checkTransaction( tx.to, @@ -118,7 +145,7 @@ describe("BaseGuard", async () => { tx.gasToken, tx.refundReceiver, tx.signatures, - user1.address + AddressZero ) ).to.emit(guard, "PreChecked"); }); From b69af8005c5a06c70dbb4046da11ed612d231682 Mon Sep 17 00:00:00 2001 From: cristovaoth Date: Fri, 13 Oct 2023 18:49:18 +0200 Subject: [PATCH 41/82] Make sentOrSigned by an internal helper function for Modifiers --- contracts/core/GuardableModifier.sol | 9 --------- contracts/core/Modifier.sol | 13 +++++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 6d8c0298..90c29b1a 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -89,13 +89,4 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } } - - function sentOrSignedBy() private view returns (address) { - if (modules[msg.sender] != address(0)) { - return msg.sender; - } - - (, address signer) = moduleTxSignedBy(); - return signer; - } } diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index ebf659fb..3a39a3dc 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -99,6 +99,19 @@ abstract contract Modifier is _; } + function sentOrSignedBy() internal view returns (address) { + if (modules[msg.sender] != address(0)) { + return msg.sender; + } + + (, address signer) = moduleTxSignedBy(); + if (modules[signer] != address(0)) { + return signer; + } + + return address(0); + } + /// @dev Disables a module on the modifier. /// @notice This can only be called by the owner. /// @param prevModule Module that pointed to the module to be removed in the linked list. From f740b174d2b5d9f2e86c440dca20f103c6141ad9 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Wed, 18 Oct 2023 09:35:10 +0200 Subject: [PATCH 42/82] Make moduleTxSignedBy return always the hash, even when no signer found recovered --- contracts/signature/SignatureChecker.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 5d9c2b5d..416dddcc 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -52,7 +52,7 @@ abstract contract SignatureChecker { data[start:data.length - 65] ) ? (hash, signer) - : (bytes32(0), address(0)); + : (hash, address(0)); } else { return (hash, ecrecover(hash, v, r, s)); } From 91d5eaa45d1d00437e766aeef55df75adfd5ffe7 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Wed, 18 Oct 2023 09:46:09 +0200 Subject: [PATCH 43/82] Consolidate hash tracking into one mapping --- contracts/core/Modifier.sol | 12 ++++-------- contracts/signature/ExecutionTracker.sol | 12 +++++++----- test/03_Modifier.spec.ts | 8 ++++---- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 3a39a3dc..f2ce79c3 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -84,16 +84,12 @@ abstract contract Modifier is } // is the provided signature fresh? - if (executed[signer][hash]) { - revert HashAlreadyExecuted(hash); + if (consumed[signer][hash]) { + revert HashAlreadyConsumed(hash); } - // was the presented signature invalidated? - if (invalidated[signer][hash]) { - revert HashInvalidated(hash); - } - - executed[signer][hash] = true; + consumed[signer][hash] = true; + emit HashExecuted(hash); } _; diff --git a/contracts/signature/ExecutionTracker.sol b/contracts/signature/ExecutionTracker.sol index a8e6e07f..ad88b1d4 100644 --- a/contracts/signature/ExecutionTracker.sol +++ b/contracts/signature/ExecutionTracker.sol @@ -3,13 +3,15 @@ pragma solidity >=0.8.0 <0.9.0; /// @title ExecutionTracker - A contract that keeps track of executed and invalidated hashes contract ExecutionTracker { - error HashAlreadyExecuted(bytes32); - error HashInvalidated(bytes32); + error HashAlreadyConsumed(bytes32); - mapping(address => mapping(bytes32 => bool)) public executed; - mapping(address => mapping(bytes32 => bool)) public invalidated; + event HashExecuted(bytes32); + event HashInvalidated(bytes32); + + mapping(address => mapping(bytes32 => bool)) public consumed; function invalidate(bytes32 hash) external { - invalidated[msg.sender][hash] = true; + consumed[msg.sender][hash] = true; + emit HashInvalidated(hash); } } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index c5e31e4f..30563533 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -453,7 +453,7 @@ describe("Modifier", async () => { await expect( relayer.sendTransaction(transactionWithOkSig) - ).to.be.revertedWithCustomError(modifier, "HashAlreadyExecuted"); + ).to.be.revertedWithCustomError(modifier, "HashAlreadyConsumed"); }); it("reverts if signature invalidated.", async () => { const { modifier, tx } = await loadFixture(setupTests); @@ -492,7 +492,7 @@ describe("Modifier", async () => { await expect( relayer.sendTransaction(transactionWithSig) - ).to.be.revertedWithCustomError(modifier, "HashInvalidated"); + ).to.be.revertedWithCustomError(modifier, "HashAlreadyConsumed"); }); }); @@ -658,7 +658,7 @@ describe("Modifier", async () => { await expect( relayer.sendTransaction(transactionWithOkSig) - ).to.be.revertedWithCustomError(modifier, "HashAlreadyExecuted"); + ).to.be.revertedWithCustomError(modifier, "HashAlreadyConsumed"); }); it("reverts if signature invalidated.", async () => { const { modifier, tx } = await loadFixture(setupTests); @@ -697,7 +697,7 @@ describe("Modifier", async () => { await expect( relayer.sendTransaction(transactionWithSig) - ).to.be.revertedWithCustomError(modifier, "HashInvalidated"); + ).to.be.revertedWithCustomError(modifier, "HashAlreadyConsumed"); }); }); }); From 5bef621d97ca108e09117fc112e368f0a27ff2c8 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Thu, 19 Oct 2023 11:15:57 +0200 Subject: [PATCH 44/82] Ensure contract specific signature is sliced correctly --- contracts/signature/SignatureChecker.sol | 8 ++-- contracts/test/TestSignature.sol | 12 ++++++ test/06_SignatureChecker.spec.ts | 48 ++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 416dddcc..fd8c1af2 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -40,7 +40,7 @@ abstract contract SignatureChecker { bytes32 hash = moduleTxHash( data[:start], // slice the appended signature out - bytes32(data[data.length - 65 - 32:]) // get the salt + bytes32(data[data.length - (32 + 65):]) // get the salt ); if (isContractSignature) { @@ -49,7 +49,7 @@ abstract contract SignatureChecker { _isValidContractSignature( signer, hash, - data[start:data.length - 65] + data[start:data.length - (32 + 65)] ) ? (hash, signer) : (hash, address(0)); @@ -122,8 +122,8 @@ abstract contract SignatureChecker { isEIP1271Signature = v == 0 && uint256(s) > 3 && - uint256(s) < (length - 65 - 32); - start = isEIP1271Signature ? uint256(s) : length - 65 - 32; + uint256(s) < (length - (32 + 65)); + start = isEIP1271Signature ? uint256(s) : length - (32 + 65); } /** diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index 7242e6d4..70113528 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -21,6 +21,18 @@ contract ContractSignerNo is IERC1271 { } } +contract ContractSignerMaybe is IERC1271 { + function isValidSignature( + bytes32, + bytes memory contractSpecificSignature + ) external pure override returns (bytes4) { + bool isValid = contractSpecificSignature.length == 6 && + bytes6(contractSpecificSignature) == 0x001122334455; + + return isValid ? bytes4(0x1626ba7e) : bytes4(0x33333333); + } +} + contract ContractSignerFaulty {} contract ContractSignerReturnSize { diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 3343e199..91724a22 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -217,6 +217,54 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Hello") .withArgs(signer); }); + it("signer returns isValid maybe", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerMaybe" + ); + const contractSigner = await ContractSigner.deploy(); + + const transaction = await testSignature.populateTransaction.goodbye( + 0, + "0xbadfed" + ); + + const signatureGood = makeContractSignature( + transaction, + "0x001122334455", + keccak256(toUtf8Bytes("some irrelevant salt")), + contractSigner.address + ); + + const signatureBad = makeContractSignature( + transaction, + "0x00112233445566", + keccak256(toUtf8Bytes("some irrelevant salt")), + contractSigner.address + ); + + const transactionWithGoodSig = { + ...transaction, + data: `${transaction.data}${signatureGood.slice(2)}`, + }; + const transactionWithBadSig = { + ...transaction, + data: `${transaction.data}${signatureBad.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithGoodSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(contractSigner.address); + + await expect(await relayer.sendTransaction(transactionWithBadSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + }); it("signer returns isValid yes", async () => { const { testSignature, relayer } = await loadFixture(setup); From d398b4d79415c74a418312927fb012646269c18d Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Wed, 25 Oct 2023 19:42:39 +0200 Subject: [PATCH 45/82] Simplify splitSignature, and pull up logic that assembles the isValidContractSignature call --- contracts/signature/SignatureChecker.sol | 72 ++++++++---------------- 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index fd8c1af2..69eadcbd 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -30,30 +30,37 @@ abstract contract SignatureChecker { return (bytes32(0), address(0)); } - ( - uint8 v, - bytes32 r, - bytes32 s, - bool isContractSignature, - uint256 start - ) = _splitSignature(data); + (uint8 v, bytes32 r, bytes32 s) = _splitSignature(data); - bytes32 hash = moduleTxHash( - data[:start], // slice the appended signature out - bytes32(data[data.length - (32 + 65):]) // get the salt - ); + uint256 end = data.length - (32 + 65); + bytes32 salt = bytes32(data[end:]); - if (isContractSignature) { + /* + * When handling contract signatures: + * v - is zero + * r - contains the signer + * s - contains the offset within calldata where the signer specific + * signature is located + * + * We detect contract signatures by checking: + * 1- `v` is zero + * 2- `s` points within the buffer, is after selector, is before + * salt and delimits a non-zero length buffer + */ + if (v == 0) { + uint256 start = uint256(s); + if (start < 4 || start > end) { + return (bytes32(0), address(0)); + } address signer = address(uint160(uint256(r))); + + bytes32 hash = moduleTxHash(data[:start], salt); return - _isValidContractSignature( - signer, - hash, - data[start:data.length - (32 + 65)] - ) + _isValidContractSignature(signer, hash, data[start:end]) ? (hash, signer) : (hash, address(0)); } else { + bytes32 hash = moduleTxHash(data[:end], salt); return (hash, ecrecover(hash, v, r, s)); } } @@ -87,43 +94,14 @@ abstract contract SignatureChecker { * @return v The ECDSA v value * @return r The ECDSA r value * @return s The ECDSA s value - * @return isEIP1271Signature Indicates whether the split signature is a contract signature - * @return start offset in calldata where signature starts */ function _splitSignature( bytes calldata data - ) - private - pure - returns ( - uint8 v, - bytes32 r, - bytes32 s, - bool isEIP1271Signature, - uint256 start - ) - { - /* - * When handling contract signatures: - * v - is zero - * r - contains the signer - * s - contains the offset within calldata where the signer specific - * signature is located - * - * We detect contract signatures by checking: - * 1- `v` is zero - * 2- `s` points within the buffer, is after selector, is before - * salt and delimits a non-zero length buffer - */ + ) private pure returns (uint8 v, bytes32 r, bytes32 s) { uint256 length = data.length; v = uint8(bytes1(data[length - 1:])); r = bytes32(data[length - 65:]); s = bytes32(data[length - 33:]); - isEIP1271Signature = - v == 0 && - uint256(s) > 3 && - uint256(s) < (length - (32 + 65)); - start = isEIP1271Signature ? uint256(s) : length - (32 + 65); } /** From 6af30a6be285f8b542523d6686dc6d367e79d9b2 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Wed, 25 Oct 2023 19:57:13 +0200 Subject: [PATCH 46/82] Add test for contract specific signature empty --- contracts/test/TestSignature.sol | 10 +++++++ test/06_SignatureChecker.spec.ts | 51 +++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index 70113528..1614cc26 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -33,6 +33,16 @@ contract ContractSignerMaybe is IERC1271 { } } +contract ContractSignerOnlyEmpty is IERC1271 { + function isValidSignature( + bytes32, + bytes memory contractSpecificSignature + ) external pure override returns (bytes4) { + bool isValid = contractSpecificSignature.length == 0; + return isValid ? bytes4(0x1626ba7e) : bytes4(0x33333333); + } +} + contract ContractSignerFaulty {} contract ContractSignerReturnSize { diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 91724a22..6886b27a 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -322,6 +322,55 @@ describe("SignatureChecker", async () => { .to.emit(testSignature, "Hello") .withArgs(AddressZero); }); + + it("signer returns isValid for empty specific signature only", async () => { + const { testSignature, relayer } = await loadFixture(setup); + + const ContractSigner = await hre.ethers.getContractFactory( + "ContractSignerOnlyEmpty" + ); + const contractSigner = await ContractSigner.deploy(); + + const transaction = await testSignature.populateTransaction.goodbye( + 0, + "0xbadfed" + ); + + const signatureGood = makeContractSignature( + transaction, + "0x", + keccak256(toUtf8Bytes("some irrelevant salt")), + contractSigner.address + ); + + const signatureBad = makeContractSignature( + transaction, + "0xffff", + keccak256(toUtf8Bytes("some irrelevant salt")), + contractSigner.address + ); + + const transactionWithGoodSig = { + ...transaction, + data: `${transaction.data}${signatureGood.slice(2)}`, + }; + const transactionWithBadSig = { + ...transaction, + data: `${transaction.data}${signatureBad.slice(2)}`, + }; + + await expect(await relayer.sendTransaction(transaction)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + + await expect(await relayer.sendTransaction(transactionWithGoodSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(contractSigner.address); + + await expect(await relayer.sendTransaction(transactionWithBadSig)) + .to.emit(testSignature, "Goodbye") + .withArgs(AddressZero); + }); it("signer bad return size", async () => { const { testSignature, relayer } = await loadFixture(setup); @@ -427,7 +476,7 @@ function makeContractSignature( r: string, s?: string ) { - const dataBytesLength = (transaction.data?.length as number) / 2 - 1; + const dataBytesLength = ((transaction.data?.length as number) - 2) / 2; r = defaultAbiCoder.encode(["address"], [r]); s = s || defaultAbiCoder.encode(["uint256"], [dataBytesLength]); From f3211aceda2f08a26ac94d0e0950aa210223e0dc Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Wed, 25 Oct 2023 23:06:42 +0200 Subject: [PATCH 47/82] Remove aux variable --- contracts/signature/SignatureChecker.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 69eadcbd..6d55a4f3 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -98,10 +98,9 @@ abstract contract SignatureChecker { function _splitSignature( bytes calldata data ) private pure returns (uint8 v, bytes32 r, bytes32 s) { - uint256 length = data.length; - v = uint8(bytes1(data[length - 1:])); - r = bytes32(data[length - 65:]); - s = bytes32(data[length - 33:]); + v = uint8(bytes1(data[data.length - 1:])); + r = bytes32(data[data.length - 65:]); + s = bytes32(data[data.length - 33:]); } /** From 94dc31a05663b86847d0d87c5c076027b264aada Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Thu, 26 Oct 2023 10:23:44 +0200 Subject: [PATCH 48/82] Consistently return hash from moduleTxSignedBy() --- contracts/signature/SignatureChecker.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 6d55a4f3..21d1d145 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -58,7 +58,7 @@ abstract contract SignatureChecker { return _isValidContractSignature(signer, hash, data[start:end]) ? (hash, signer) - : (hash, address(0)); + : (bytes32(0), address(0)); } else { bytes32 hash = moduleTxHash(data[:end], salt); return (hash, ecrecover(hash, v, r, s)); From 63fc0b37558078756452d05449bddc060e82591e Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Mon, 30 Oct 2023 11:07:06 +0100 Subject: [PATCH 49/82] bump package.json version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 85feb289..b45508aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.3.10", + "version": "3.4.0", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", @@ -93,4 +93,4 @@ "@openzeppelin/contracts-upgradeable": "^5.0.0", "ethers": "^5.7.1" } -} \ No newline at end of file +} From 84528e5fa2271284b68e9ec7a9b5290fccbc09be Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 14:43:15 +0100 Subject: [PATCH 50/82] Bump dependencies --- package.json | 15 +- yarn.lock | 2472 +++++++++++++++++++++++--------------------------- 2 files changed, 1124 insertions(+), 1363 deletions(-) diff --git a/package.json b/package.json index b45508aa..b53d1791 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,9 @@ "lint": "yarn lint:sol && yarn lint:ts", "lint:sol": "solhint ./contracts/**/*.sol", "lint:ts": "eslint --max-warnings 0 .", - "fmt:sol": "prettier ./contracts/**/*.sol -w", "format": "yarn format:sol && yarn format:ts", - "format:sol": "prettier ./contracts/**/*.sol -w", - "format:ts": "prettier ./sdk/**/*.ts ./test/**/*.ts ./*.ts -w", + "format:sol": "prettier --write --plugin=prettier-plugin-solidity ./contracts/**/*.sol", + "format:ts": "prettier --write ./sdk/**/*.ts ./test/**/*.ts ./*.ts", "generate:types": "rm -rf src/types && typechain --target ethers-v5 --out-dir sdk/types './sdk/abi/*.json'", "prepare": "yarn generate:types && yarn build", "prerelease": "yarn clean && yarn build && yarn build:sdk", @@ -66,24 +65,24 @@ "chai": "^4.3.7", "dotenv": "^16.0.3", "eslint": "^8.25.0", - "eslint-config-prettier": "^8.5.0", + "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-no-only-tests": "^3.0.0", - "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-prettier": "^5.0.1", "hardhat": "^2.14.0", "hardhat-change-network": "^0.0.7", "hardhat-deploy": "^0.11.28", "hardhat-gas-reporter": "^1.0.9", "husky": "^8.0.1", - "prettier": "^2.8.8", + "prettier": "^3.0.3", "prettier-plugin-solidity": "^1.1.3", "rimraf": "^5.0.1", "solhint": "^3.3.7", - "solhint-plugin-prettier": "^0.0.5", + "solhint-plugin-prettier": "^0.1.0", "solidity-coverage": "^0.8.4", "ts-node": "^10.9.1", "typechain": "^8.3.0", - "typescript": "^5.1.6", + "typescript": "^5.2.2", "yargs": "^17.6.0" }, "dependencies": { diff --git a/yarn.lock b/yarn.lock index 9dd61e90..55206cb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,25 +2,31 @@ # yarn lockfile v1 +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + "@babel/code-frame@^7.0.0": - version "7.21.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" - integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" -"@babel/helper-validator-identifier@^7.18.6": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" "@chainsafe/as-sha256@^0.3.1": @@ -73,19 +79,19 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" - integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== -"@eslint/eslintrc@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" - integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.5.2" + espree "^9.6.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -93,12 +99,26 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.40.0": - version "8.40.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.40.0.tgz#3ba73359e11f5a7bd3e407f70b3528abfae69cec" - integrity sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA== +"@eslint/js@8.52.0": + version "8.52.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" + integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -440,6 +460,11 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@fastify/busboy@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" + integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== + "@gnosis.pm/mock-contract@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/mock-contract/-/mock-contract-4.0.0.tgz#eaf500fddcab81b5f6c22280a7b22ff891dd6f87" @@ -450,12 +475,12 @@ resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.3.0.tgz#316741a7690d8751a1f701538cfc9ec80866eedc" integrity sha512-1p+1HwGvxGUVzVkFjNzglwHrLNA67U/axP0Ct85FzzH8yhGJb4t9jDjPYocVMzLorDoWAfKicGy1akPY9jXRVw== -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== +"@humanwhocodes/config-array@^0.11.13": + version "0.11.13" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== dependencies: - "@humanwhocodes/object-schema" "^1.2.1" + "@humanwhocodes/object-schema" "^2.0.1" debug "^4.1.1" minimatch "^3.0.5" @@ -464,10 +489,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/object-schema@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -510,19 +535,28 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@morgan-stanley/ts-mocking-bird@^0.6.2": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@morgan-stanley/ts-mocking-bird/-/ts-mocking-bird-0.6.4.tgz#2e4b60d42957bab3b50b67dbf14c3da2f62a39f7" - integrity sha512-57VJIflP8eR2xXa9cD1LUawh+Gh+BVQfVu0n6GALyg/AqV/Nz25kDRvws3i9kIe1PTrbsZZOYpsYp6bXPd6nVA== +"@noble/curves@1.1.0", "@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== dependencies: - lodash "^4.17.16" - uuid "^7.0.3" + "@noble/hashes" "1.3.1" "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== +"@noble/hashes@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" @@ -549,31 +583,31 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" - integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" +"@nomicfoundation/ethereumjs-block@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz#13a7968f5964f1697da941281b7f7943b0465d04" + integrity sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" ethereum-cryptography "0.1.3" ethers "^5.7.1" -"@nomicfoundation/ethereumjs-blockchain@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" - integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-ethash" "3.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" +"@nomicfoundation/ethereumjs-blockchain@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz#45323b673b3d2fab6b5008535340d1b8fea7d446" + integrity sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-ethash" "3.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" abstract-level "^1.0.3" debug "^4.3.3" ethereum-cryptography "0.1.3" @@ -581,103 +615,103 @@ lru-cache "^5.1.1" memory-level "^1.0.0" -"@nomicfoundation/ethereumjs-common@4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" - integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== +"@nomicfoundation/ethereumjs-common@4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz#a15d1651ca36757588fdaf2a7d381a150662a3c3" + integrity sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg== dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.2" crc-32 "^1.2.0" -"@nomicfoundation/ethereumjs-ethash@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" - integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== +"@nomicfoundation/ethereumjs-ethash@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz#da77147f806401ee996bfddfa6487500118addca" + integrity sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg== dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" abstract-level "^1.0.3" bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-evm@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" - integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== +"@nomicfoundation/ethereumjs-evm@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz#4c2f4b84c056047102a4fa41c127454e3f0cfcf6" + integrity sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ== dependencies: "@ethersproject/providers" "^5.7.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" mcl-wasm "^0.7.1" rustbn.js "~0.2.0" -"@nomicfoundation/ethereumjs-rlp@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" - integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== +"@nomicfoundation/ethereumjs-rlp@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz#4fee8dc58a53ac6ae87fb1fca7c15dc06c6b5dea" + integrity sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA== -"@nomicfoundation/ethereumjs-statemanager@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" - integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== +"@nomicfoundation/ethereumjs-statemanager@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz#3ba4253b29b1211cafe4f9265fee5a0d780976e0" + integrity sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA== dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" ethers "^5.7.1" js-sdsl "^4.1.4" -"@nomicfoundation/ethereumjs-trie@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" - integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== +"@nomicfoundation/ethereumjs-trie@6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz#9a6dbd28482dca1bc162d12b3733acab8cd12835" + integrity sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ== dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" "@types/readable-stream" "^2.3.13" ethereum-cryptography "0.1.3" readable-stream "^3.6.0" -"@nomicfoundation/ethereumjs-tx@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" - integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== +"@nomicfoundation/ethereumjs-tx@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz#117813b69c0fdc14dd0446698a64be6df71d7e56" + integrity sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g== dependencies: "@chainsafe/ssz" "^0.9.2" "@ethersproject/providers" "^5.7.2" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-util@9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" - integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== +"@nomicfoundation/ethereumjs-util@9.0.2": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz#16bdc1bb36f333b8a3559bbb4b17dac805ce904d" + integrity sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ== dependencies: "@chainsafe/ssz" "^0.10.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-vm@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" - integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" +"@nomicfoundation/ethereumjs-vm@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz#3b0852cb3584df0e18c182d0672a3596c9ca95e6" + integrity sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" mcl-wasm "^0.7.1" @@ -695,9 +729,9 @@ ordinal "^1.0.3" "@nomicfoundation/hardhat-network-helpers@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz#e4fe1be93e8a65508c46d73c41fa26c7e9f84931" - integrity sha512-MNqQbzUJZnCMIYvlniC3U+kcavz/PhhQSsY90tbEtUyMj/IQqsLwIRZa4ctjABh3Bz0KCh9OXUZ7Yk/d9hr45Q== + version "1.0.9" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.9.tgz#767449e8a2acda79306ac84626117583d95d25aa" + integrity sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q== dependencies: ethereumjs-util "^7.1.4" @@ -808,10 +842,27 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@pkgr/utils@^2.3.1": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" + integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw== + dependencies: + cross-spawn "^7.0.3" + fast-glob "^3.3.0" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.6.0" + +"@prettier/sync@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@prettier/sync/-/sync-0.3.0.tgz#91f2cfc23490a21586d1cf89c6f72157c000ca1e" + integrity sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw== + "@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + version "1.1.3" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" + integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== "@scure/bip32@1.1.5": version "1.1.5" @@ -822,6 +873,15 @@ "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== + dependencies: + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" + "@scure/base" "~1.1.0" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -830,6 +890,14 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -906,9 +974,9 @@ antlr4ts "^0.5.0-alpha.4" "@solidity-parser/parser@^0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.0.tgz#1fb418c816ca1fc3a1e94b08bcfe623ec4e1add4" - integrity sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q== + version "0.16.1" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c" + integrity sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw== dependencies: antlr4ts "^0.5.0-alpha.4" @@ -928,14 +996,14 @@ integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@typechain/ethers-v5@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-11.1.0.tgz#98cac1788ef8b22c0482bb6797edcd22d69b8f0f" - integrity sha512-7P+fLol3faUi/WPFwUo9tfo+IHSsvMBvSM/ECNU9mFHcF8eFI84ygauCdwPgP41k8bhsPb29XhwZiYDTUDXU8Q== + version "11.1.2" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-11.1.2.tgz#82510c1744f37a2f906b9e0532ac18c0b74ffe69" + integrity sha512-ID6pqWkao54EuUQa0P5RgjvfA3MYqxUQKpbGKERbsjBW5Ra7EIXvbMlPp2pcP5IAdUkyMCFYsP2SN5q7mPdLDQ== dependencies: lodash "^4.17.15" ts-essentials "^7.0.1" @@ -955,23 +1023,23 @@ "@types/node" "*" "@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + version "5.1.4" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.4.tgz#0853d5f92dfdbc8fe1ae60700411a60845fa7d27" + integrity sha512-ZtBd9L8hVtoBpPMSWfbwjC4dhQtJdlPS+e1A0Rydb7vg7bDcUwiRklPx24sMYtXcmAMST/k0Wze7JLbNU/5SkA== dependencies: "@types/node" "*" "@types/chai-as-promised@^7.1.3": - version "7.1.5" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + version "7.1.7" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.7.tgz#fd16a981ba9542c83d4e1d2f40c7899aae82aa38" + integrity sha512-APucaP5rlmTRYKtRA6FE5QPP87x76ejw5t5guRJ4y5OgMnwtsvigw7HHhKZlx2MGXLeZd6R/GNZR/IqDHcbtQw== dependencies: "@types/chai" "*" "@types/chai@*", "@types/chai@^4.3.3": - version "4.3.5" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" - integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== + version "4.3.9" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.9.tgz#144d762491967db8c6dea38e03d2206c2623feec" + integrity sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg== "@types/concat-stream@^1.6.0": version "1.6.1" @@ -996,9 +1064,9 @@ "@types/node" "*" "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.14" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" + integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== "@types/json5@^0.0.29": version "0.0.29" @@ -1016,14 +1084,16 @@ integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/mocha@^10.0.0": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" - integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== + version "10.0.3" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.3.tgz#4804fe9cd39da26eb62fa65c15ea77615a187812" + integrity sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ== "@types/node@*": - version "20.1.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.1.1.tgz#afc492e8dbe7f672dd3a13674823522b467a45ad" - integrity sha512-uKBEevTNb+l6/aCQaKVnUModfEMjAl98lw2Si9P5y4hLu9tm6AlX2ZIoXZX6Wh9lJueYPrGPKk5WMCNHg/u6/A== + version "20.8.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.10.tgz#a5448b895c753ae929c26ce85cab557c6d4a365e" + integrity sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w== + dependencies: + undici-types "~5.26.4" "@types/node@^10.0.3": version "10.17.60" @@ -1031,9 +1101,11 @@ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== "@types/node@^18.8.5": - version "18.16.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.6.tgz#d0ffffe201b253989b17ea157ddabec677a4f4fe" - integrity sha512-N7KINmeB8IN3vRR8dhgHEp+YpWvGFcpDoh5XZ8jB5a00AdFKCKEyyGTOPTddUf4JqU1ZKTVxkOxakDvchNVI2Q== + version "18.18.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.18.8.tgz#2b285361f2357c8c8578ec86b5d097c7f464cfd6" + integrity sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ== + dependencies: + undici-types "~5.26.4" "@types/node@^8.0.0": version "8.10.66" @@ -1041,21 +1113,21 @@ integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== "@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.1.tgz#c290c1f0d3dc364af94c2c5ee92046a13b7f89fd" + integrity sha512-4HCoGwR3221nOc7G0Z/6KgTNGgaaFGkbGrtUJsB+zlKX2LBVjFHHIUkieMBgHHXgBH5Gq6dZHJKdBYdtlhBQvw== dependencies: "@types/node" "*" "@types/prettier@^2.1.1": - version "2.7.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" - integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/qs@^6.2.31", "@types/qs@^6.9.7": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.9" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.9.tgz#66f7b26288f6799d279edf13da7ccd40d2fa9197" + integrity sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg== "@types/readable-stream@^2.3.13": version "2.3.15" @@ -1066,113 +1138,118 @@ safe-buffer "~5.1.1" "@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.5.tgz#14b1766b4fbc198b0af5599d9fd21c89056633ce" + integrity sha512-aIonTBMErtE3T9MxDvTZRzcrT/mCqpEZBw3CCY/i+oG9n57N/+7obBkhFgavUAIrX21bU0LHg1XRgtaLdelBhA== dependencies: "@types/node" "*" "@types/semver@^7.3.12": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" - integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + version "7.5.4" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff" + integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ== "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + version "21.0.2" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.2.tgz#7bd04c5da378496ef1695a1008bf8f71847a8b8b" + integrity sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw== "@types/yargs@^17.0.13": - version "17.0.24" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" - integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== + version "17.0.29" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.29.tgz#06aabc72497b798c643c812a8b561537fea760cf" + integrity sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA== dependencies: "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.40.0": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz#f156827610a3f8cefc56baeaa93cd4a5f32966b4" - integrity sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== dependencies: "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.59.5" - "@typescript-eslint/type-utils" "5.59.5" - "@typescript-eslint/utils" "5.59.5" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" natural-compare-lite "^1.4.0" semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/parser@^5.40.0": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.5.tgz#63064f5eafbdbfb5f9dfbf5c4503cdf949852981" - integrity sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== dependencies: - "@typescript-eslint/scope-manager" "5.59.5" - "@typescript-eslint/types" "5.59.5" - "@typescript-eslint/typescript-estree" "5.59.5" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.59.5": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz#33ffc7e8663f42cfaac873de65ebf65d2bce674d" - integrity sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A== +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: - "@typescript-eslint/types" "5.59.5" - "@typescript-eslint/visitor-keys" "5.59.5" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/type-utils@5.59.5": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz#485b0e2c5b923460bc2ea6b338c595343f06fc9b" - integrity sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg== +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== dependencies: - "@typescript-eslint/typescript-estree" "5.59.5" - "@typescript-eslint/utils" "5.59.5" + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.59.5": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.5.tgz#e63c5952532306d97c6ea432cee0981f6d2258c7" - integrity sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w== +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/typescript-estree@5.59.5": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz#9b252ce55dd765e972a7a2f99233c439c5101e42" - integrity sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg== +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: - "@typescript-eslint/types" "5.59.5" - "@typescript-eslint/visitor-keys" "5.59.5" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.59.5": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.5.tgz#15b3eb619bb223302e60413adb0accd29c32bcae" - integrity sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA== +"@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.59.5" - "@typescript-eslint/types" "5.59.5" - "@typescript-eslint/typescript-estree" "5.59.5" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.59.5": - version "5.59.5" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz#ba5b8d6791a13cf9fea6716af1e7626434b29b9b" - integrity sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA== +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: - "@typescript-eslint/types" "5.59.5" + "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1183,13 +1260,6 @@ abbrev@1.0.x: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" @@ -1209,14 +1279,14 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + version "8.3.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.0.tgz#2097665af50fd0cf7a2dfccd2b9368964e66540f" + integrity sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA== -acorn@^8.4.1, acorn@^8.8.0: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +acorn@^8.4.1, acorn@^8.9.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== address@^1.0.1: version "1.2.2" @@ -1248,7 +1318,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.6: +ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1273,11 +1343,6 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -1300,11 +1365,6 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1315,7 +1375,7 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -1335,16 +1395,16 @@ ansi-styles@^6.1.0: integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== antlr4@^4.11.0: - version "4.12.0" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.12.0.tgz#e2323fbb057c77068a174914b0533398aeaba56a" - integrity sha512-23iB5IzXJZRZeK9TigzUyrNc9pSmNqAerJRBcNq1ETrmttMWRgaYZzC561IgEO3ygKsDJTYDTozABXa4b/fTQQ== + version "4.13.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1.tgz#1e0a1830a08faeb86217cb2e6c34716004e4253d" + integrity sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA== antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== -anymatch@~3.1.1, anymatch@~3.1.2: +anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -1387,15 +1447,15 @@ array-buffer-byte-length@^1.0.0: call-bind "^1.0.2" is-array-buffer "^3.0.1" -array-includes@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" - integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== +array-includes@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" is-string "^1.0.7" array-union@^2.1.0: @@ -1408,54 +1468,55 @@ array-uniq@1.0.3: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== -array.prototype.flat@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" - integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== +array.prototype.findlastindex@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" -array.prototype.flatmap@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" - integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.reduce@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" - integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" @@ -1491,16 +1552,6 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== - -aws4@^1.8.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" - integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== - axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -1508,6 +1559,15 @@ axios@^0.21.1: dependencies: follow-redirects "^1.14.0" +axios@^1.5.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102" + integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -1525,22 +1585,20 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== - dependencies: - tweetnacl "^0.14.3" - bech32@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +big-integer@^1.6.44: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + bigint-crypto-utils@^3.0.23: - version "3.2.2" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.2.2.tgz#e30a49ec38357c6981cd3da5aaa6480b1f752ee4" - integrity sha512-U1RbE3aX9ayCUVcIPHuPDPKcK3SFOXf93J1UK/iHlJuQB7bhagPIX06/CLpLEsDThJ7KA4Dhrnzynl+d2weTiw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" + integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== binary-extensions@^2.0.0: version "2.2.0" @@ -1567,6 +1625,13 @@ bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1655,36 +1720,32 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -busboy@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== dependencies: - streamsearch "^1.1.0" + run-applescript "^5.0.0" bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - camelcase@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" @@ -1720,19 +1781,19 @@ chai-as-promised@^7.1.1: check-error "^1.0.2" chai@^4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + version "4.3.10" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" + integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== dependencies: assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" pathval "^1.1.1" - type-detect "^4.0.5" + type-detect "^4.0.8" -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1754,25 +1815,12 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== - -chokidar@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== +check-error@^1.0.2, check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.2.0" - optionalDependencies: - fsevents "~2.1.1" + get-func-name "^2.0.2" chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2: version "3.5.3" @@ -1828,15 +1876,6 @@ cli-table3@^0.5.0: optionalDependencies: colors "^1.1.2" -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -1884,7 +1923,7 @@ colors@1.4.0, colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -1946,24 +1985,19 @@ cookie@^0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== cosmiconfig@^8.0.0: - version "8.1.3" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.1.3.tgz#0e614a118fcc2d9e5afc2f87d53cd09931015689" - integrity sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw== + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== dependencies: - import-fresh "^3.2.1" + import-fresh "^3.3.0" js-yaml "^4.1.0" - parse-json "^5.0.0" + parse-json "^5.2.0" path-type "^4.0.0" crc-32@^1.2.0: @@ -1999,7 +2033,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2013,25 +2047,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== - dependencies: - assert-plus "^1.0.0" - death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -2046,17 +2066,12 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -deep-eql@^4.0.1, deep-eql@^4.1.2: +deep-eql@^4.0.1, deep-eql@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== @@ -2073,11 +2088,44 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + +define-data-property@^1.0.1, define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -2099,11 +2147,6 @@ detect-port@^1.3.0: address "^1.0.1" debug "4" -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -2143,23 +2186,15 @@ doctrine@^3.0.0: esutils "^2.0.2" dotenv@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -2173,11 +2208,6 @@ elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2194,11 +2224,12 @@ encode-utf8@^1.0.2: integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== enquirer@^2.3.0, enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: ansi-colors "^4.1.1" + strip-ansi "^6.0.1" env-paths@^2.2.0: version "2.2.1" @@ -2212,25 +2243,26 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== +es-abstract@^1.22.1: + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== dependencies: array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + call-bind "^1.0.5" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.2" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" - has "^1.0.3" has-property-descriptors "^1.0.0" has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" internal-slot "^1.0.5" is-array-buffer "^3.0.2" is-callable "^1.2.7" @@ -2238,40 +2270,39 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" is-string "^1.0.7" - is-typed-array "^1.1.10" + is-typed-array "^1.1.12" is-weakref "^1.0.2" - object-inspect "^1.12.3" + object-inspect "^1.13.1" object-keys "^1.1.1" object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + which-typed-array "^1.1.13" es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" + integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" + get-intrinsic "^1.2.2" has-tostringtag "^1.0.0" + hasown "^2.0.0" es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== dependencies: - has "^1.0.3" + hasown "^2.0.0" es-to-primitive@^1.2.1: version "1.2.1" @@ -2287,16 +2318,16 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" @@ -2309,21 +2340,21 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -eslint-config-prettier@^8.5.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" - integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== +eslint-config-prettier@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f" + integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw== -eslint-import-resolver-node@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" - integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" - is-core-module "^2.11.0" - resolve "^1.22.1" + is-core-module "^2.13.0" + resolve "^1.22.4" -eslint-module-utils@^2.7.4: +eslint-module-utils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== @@ -2331,37 +2362,40 @@ eslint-module-utils@^2.7.4: debug "^3.2.7" eslint-plugin-import@^2.26.0: - version "2.27.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" - integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - array.prototype.flatmap "^1.3.1" + version "2.29.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155" + integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.7" - eslint-module-utils "^2.7.4" - has "^1.0.3" - is-core-module "^2.11.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" is-glob "^4.0.3" minimatch "^3.1.2" - object.values "^1.1.6" - resolve "^1.22.1" - semver "^6.3.0" - tsconfig-paths "^3.14.1" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.14.2" eslint-plugin-no-only-tests@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz#f38e4935c6c6c4842bf158b64aaa20c366fe171b" integrity sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw== -eslint-plugin-prettier@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== +eslint-plugin-prettier@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz#a3b399f04378f79f066379f544e42d6b73f11515" + integrity sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg== dependencies: prettier-linter-helpers "^1.0.0" + synckit "^0.8.5" eslint-scope@^5.1.1: version "5.1.1" @@ -2371,40 +2405,41 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" - integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.25.0: - version "8.40.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.40.0.tgz#a564cd0099f38542c4e9a2f630fa45bf33bc42a4" - integrity sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ== + version "8.52.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.52.0.tgz#d0cd4a1fac06427a61ef9242b9353f36ea7062fc" + integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.4.0" - "@eslint/eslintrc" "^2.0.3" - "@eslint/js" "8.40.0" - "@humanwhocodes/config-array" "^0.11.8" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.52.0" + "@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.0" - eslint-visitor-keys "^3.4.1" - espree "^9.5.2" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -2412,30 +2447,27 @@ eslint@^8.25.0: find-up "^5.0.0" glob-parent "^6.0.2" globals "^13.19.0" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" - js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" + optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.5.2: - version "9.5.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" - integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^8.8.0" + acorn "^8.9.0" acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" @@ -2484,23 +2516,21 @@ esutils@^2.0.2: integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== eth-gas-reporter@^0.2.25: - version "0.2.25" - resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz#546dfa946c1acee93cb1a94c2a1162292d6ff566" - integrity sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ== + version "0.2.27" + resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz#928de8548a674ed64c7ba0bf5795e63079150d4e" + integrity sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw== dependencies: - "@ethersproject/abi" "^5.0.0-beta.146" "@solidity-parser/parser" "^0.14.0" + axios "^1.5.1" cli-table3 "^0.5.0" colors "1.4.0" ethereum-cryptography "^1.0.3" - ethers "^4.0.40" + ethers "^5.7.2" fs-readdir-recursive "^1.1.0" lodash "^4.17.14" markdown-table "^1.1.3" - mocha "^7.1.1" + mocha "^10.2.0" req-cwd "^2.0.0" - request "^2.88.0" - request-promise-native "^1.0.5" sha1 "^1.1.1" sync-request "^6.0.0" @@ -2542,6 +2572,16 @@ ethereum-cryptography@^1.0.3: "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" + integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== + dependencies: + "@noble/curves" "1.1.0" + "@noble/hashes" "1.3.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" + ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" @@ -2563,7 +2603,7 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.4: +ethereumjs-util@^7.1.4: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -2574,22 +2614,7 @@ ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.4: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@^4.0.40: - version "4.0.49" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" - integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== - dependencies: - aes-js "3.0.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.4" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - -ethers@^5.5.3, ethers@^5.7.1: +ethers@^5.7.0, ethers@^5.7.1, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -2641,11 +2666,6 @@ ethjs-util@0.1.6, ethjs-util@^0.1.6: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -2654,20 +2674,35 @@ evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" @@ -2675,14 +2710,14 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2, fast-diff@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@^3.0.3, fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.0.3, fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -2728,13 +2763,6 @@ find-replace@^3.0.0: dependencies: array-back "^3.0.1" -find-up@3.0.0, find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -2751,29 +2779,23 @@ find-up@^2.1.0: locate-path "^2.0.0" flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.1.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" + integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== dependencies: - flatted "^3.1.0" + flatted "^3.2.9" + keyv "^4.5.3" rimraf "^3.0.2" -flat@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" - integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== - dependencies: - is-buffer "~2.0.3" - flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== fmix@^0.1.0: version "0.1.0" @@ -2782,10 +2804,10 @@ fmix@^0.1.0: dependencies: imul "^1.0.0" -follow-redirects@^1.12.1, follow-redirects@^1.14.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.15.0: + version "1.15.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" + integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== for-each@^0.3.3: version "0.3.3" @@ -2802,11 +2824,6 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== - form-data@^2.2.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -2825,15 +2842,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - fp-ts@1.19.3: version "1.19.3" resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" @@ -2902,65 +2910,66 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -get-caller-file@^2.0.1, get-caller-file@^2.0.5: +get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" - integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + function-bind "^1.1.2" + has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-port@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== +get-stream@^6.0.0, get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -2969,13 +2978,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== - dependencies: - assert-plus "^1.0.0" - ghost-testrpc@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" @@ -2984,7 +2986,7 @@ ghost-testrpc@^0.0.2: chalk "^2.4.2" node-emoji "^1.10.0" -glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -2998,18 +3000,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.1.7: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" @@ -3034,13 +3024,13 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^10.2.5: - version "10.3.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.3.tgz#8360a4ffdd6ed90df84aa8d52f21f452e86a123b" - integrity sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw== +glob@^10.3.7: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== dependencies: foreground-child "^3.1.0" - jackspeak "^2.0.3" + jackspeak "^2.3.5" minimatch "^9.0.1" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" @@ -3096,9 +3086,9 @@ global-prefix@^3.0.0: which "^1.3.1" globals@^13.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.23.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== dependencies: type-fest "^0.20.2" @@ -3147,50 +3137,32 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== handlebars@^4.0.1: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: uglify-js "^3.1.4" -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - hardhat-change-network@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/hardhat-change-network/-/hardhat-change-network-0.0.7.tgz#9f9b7943ff966515658b70bf5e44bc2f073af402" integrity sha512-Usp9fJan9SOJnOlVcv/jMJDchseE7bIDA5ZsBnracgVk4MiBwkvMqpmLWn5G1aDBvnUCthvS2gO3odfahgkV0Q== hardhat-deploy@^0.11.28: - version "0.11.34" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.34.tgz#61252ebf5dfdda7b0b31298dd5580b0735c05910" - integrity sha512-N6xcwD8LSMV/IyfEr8TfR2YRbOh9Q4QvitR9MKZRTXQmgQiiMGjX+2efMjKgNMxwCVlmpfnE1tyDxOJOOUseLQ== + version "0.11.43" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.43.tgz#b22ff15b3ea201b72ba0f17f4b2e182cc950e73e" + integrity sha512-D760CjDtinwjOCpKOvdyRtIJYLQIYXmhfgkFe+AkxlYM9bPZ/T4tZ/xIB2tR89ZT+z0hF1YuZFBXIL3/G/9T5g== dependencies: "@ethersproject/abi" "^5.7.0" "@ethersproject/abstract-signer" "^5.7.0" @@ -3209,7 +3181,7 @@ hardhat-deploy@^0.11.28: chokidar "^3.5.2" debug "^4.3.2" enquirer "^2.3.6" - ethers "^5.5.3" + ethers "^5.7.0" form-data "^4.0.0" fs-extra "^10.0.0" match-all "^1.2.6" @@ -3227,27 +3199,26 @@ hardhat-gas-reporter@^1.0.9: sha1 "^1.1.1" hardhat@^2.14.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.17.0.tgz#574478790fa4f4a45c5ccf162e82e54f36671749" - integrity sha512-CaEGa13tkJNe2/rdaBiive4pmdNShwxvdWVhr1zfb6aVpRhQt9VNO0l/UIBt/zzajz38ZFjvhfM2bj8LDXo9gw== + version "2.18.3" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.18.3.tgz#8fd01348795c77086fff417a4d13c521dce28fcf" + integrity sha512-JuYaTG+4ZHVjEHCW5Hn6jCHH3LpO75dtgznZpM/dLv12RcSlw/xHbeQh3FAsGahQr1epKryZcZEMHvztVZHe0g== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@nomicfoundation/ethereumjs-vm" "7.0.1" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + "@nomicfoundation/ethereumjs-vm" "7.0.2" "@nomicfoundation/solidity-analyzer" "^0.1.0" "@sentry/node" "^5.18.1" "@types/bn.js" "^5.1.0" "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" adm-zip "^0.4.16" aggregate-error "^3.0.0" ansi-escapes "^4.3.0" @@ -3302,18 +3273,18 @@ has-flag@^4.0.0: integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== dependencies: - get-intrinsic "^1.1.1" + get-intrinsic "^1.2.2" has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== -has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -3325,13 +3296,6 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - hash-base@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" @@ -3341,14 +3305,6 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -3357,6 +3313,13 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -3404,15 +3367,6 @@ http-response-object@^3.0.1: dependencies: "@types/node" "^10.0.3" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -3421,6 +3375,16 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + husky@^8.0.1: version "8.0.3" resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" @@ -3444,11 +3408,11 @@ ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== immutable@^4.0.0-rc.12: - version "4.3.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be" - integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== + version "4.3.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" + integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== -import-fresh@^3.0.0, import-fresh@^3.2.1: +import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -3490,12 +3454,12 @@ ini@^1.3.5: integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== internal-slot@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" + integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" + get-intrinsic "^1.2.2" + hasown "^2.0.0" side-channel "^1.0.4" interpret@^1.0.0: @@ -3546,7 +3510,7 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^2.0.5, is-buffer@~2.0.3: +is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -3556,12 +3520,12 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.11.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" - integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: - has "^1.0.3" + hasown "^2.0.0" is-date-object@^1.0.1: version "1.0.5" @@ -3570,6 +3534,16 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -3597,6 +3571,13 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -3639,6 +3620,16 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -3653,21 +3644,12 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + which-typed-array "^1.1.11" is-unicode-supported@^0.1.0: version "0.1.0" @@ -3681,6 +3663,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -3696,29 +3685,19 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== - -jackspeak@^2.0.3: - version "2.2.1" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.2.1.tgz#655e8cf025d872c9c03d3eb63e8f0c024fef16a6" - integrity sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw== +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: "@pkgjs/parseargs" "^0.11.0" js-sdsl@^4.1.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" - integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== - -js-sha3@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== + version "4.4.2" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" + integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" @@ -3730,14 +3709,6 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@3.x: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -3753,10 +3724,10 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-parse-even-better-errors@^2.3.0: version "2.3.1" @@ -3773,21 +3744,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -3823,25 +3784,22 @@ jsonschema@^1.2.4: resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - keccak@^3.0.0, keccak@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" - integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== dependencies: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" readable-stream "^3.6.0" +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -3904,14 +3862,6 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -3934,18 +3884,11 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - log-symbols@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -3954,12 +3897,12 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -loupe@^2.3.1: - version "2.3.6" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" - integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== dependencies: - get-func-name "^2.0.0" + get-func-name "^2.0.1" lru-cache@^5.1.1: version "5.1.1" @@ -3976,9 +3919,9 @@ lru-cache@^6.0.0: yallist "^4.0.0" "lru-cache@^9.1.1 || ^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" - integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== + version "10.0.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" + integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== lru_map@^0.3.3: version "0.3.3" @@ -4028,11 +3971,21 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -4046,13 +3999,23 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@~2.1.19: +mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -4070,13 +4033,6 @@ minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - minimatch@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" @@ -4104,16 +4060,9 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.2.tgz#58a82b7d81c7010da5bd4b2c0c85ac4b4ec5131e" - integrity sha512-eL79dXrE1q9dBbDCLg7xfn/vl7MS4F1gvJAgjJrQli/jbQWdUttuVawphqpffoIYfRdq78LHx6GP4bU/EQ2ATA== - -mkdirp@0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== mkdirp@0.5.x: version "0.5.6" @@ -4134,37 +4083,7 @@ mnemonist@^0.38.0: dependencies: obliterator "^2.0.0" -mocha@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6" - integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - chokidar "3.3.0" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" - minimatch "3.0.4" - mkdirp "0.5.5" - ms "2.1.1" - node-environment-flags "1.0.6" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.0" - -mocha@^10.0.0: +mocha@10.2.0, mocha@^10.0.0, mocha@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== @@ -4191,46 +4110,11 @@ mocha@^10.0.0: yargs-parser "20.2.4" yargs-unparser "2.0.0" -mocha@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" - integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - chokidar "3.3.0" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" - minimatch "3.0.4" - mkdirp "0.5.5" - ms "2.1.1" - node-environment-flags "1.0.6" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.0" - module-error@^1.0.1, module-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -4270,7 +4154,7 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -4287,18 +4171,10 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-environment-flags@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" - integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + version "4.6.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" + integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== nofilter@^3.1.0: version "3.1.0" @@ -4317,6 +4193,20 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" @@ -4325,36 +4215,21 @@ number-to-bn@1.7.0: bn.js "4.11.6" strip-hex-prefix "1.0.0" -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.3, object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.13.1, object-inspect@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== -object-keys@^1.0.11, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -4365,25 +4240,33 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.getownpropertydescriptors@^2.0.3: - version "2.1.6" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" - integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== +object.fromentries@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== dependencies: - array.prototype.reduce "^1.0.5" call-bind "^1.0.2" define-properties "^1.2.0" - es-abstract "^1.21.2" - safe-array-concat "^1.0.0" + es-abstract "^1.22.1" -object.values@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== +object.groupby@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + +object.values@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" obliterator@^2.0.0: version "2.0.4" @@ -4397,6 +4280,30 @@ once@1.x, once@^1.3.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -4409,17 +4316,17 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" ordinal@^1.0.3: version "1.0.3" @@ -4438,13 +4345,6 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -4459,13 +4359,6 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -4485,11 +4378,6 @@ p-try@^1.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -4502,7 +4390,7 @@ parse-cache-control@^1.0.1: resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== -parse-json@^5.0.0: +parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -4527,11 +4415,16 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -4566,10 +4459,10 @@ pbkdf2@^3.0.17: safe-buffer "^5.0.1" sha.js "^2.4.8" -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" @@ -4612,11 +4505,16 @@ prettier-plugin-solidity@^1.1.3: semver "^7.3.8" solidity-comments-extractor "^0.0.7" -prettier@^2.3.1, prettier@^2.8.3, prettier@^2.8.8: +prettier@^2.3.1, prettier@^2.8.3: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" + integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -4629,28 +4527,23 @@ promise@^8.0.0: dependencies: asap "~2.0.6" -psl@^1.1.28: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -punycode@^2.1.0, punycode@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== qs@^6.4.0, qs@^6.9.4: - version "6.11.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" - integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== + version "6.11.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" + integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== dependencies: side-channel "^1.0.4" -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - queue-microtask@^1.2.2, queue-microtask@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -4695,13 +4588,6 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== - dependencies: - picomatch "^2.0.4" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -4728,14 +4614,14 @@ reduce-flatten@^2.0.0: resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== -regexp.prototype.flags@^1.4.3: - version "1.5.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" - integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== +regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== dependencies: call-bind "^1.0.2" define-properties "^1.2.0" - functions-have-names "^1.2.3" + set-function-name "^2.0.0" req-cwd@^2.0.0: version "2.0.0" @@ -4751,48 +4637,6 @@ req-from@^2.0.0: dependencies: resolve-from "^3.0.0" -request-promise-core@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" - integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== - dependencies: - lodash "^4.17.19" - -request-promise-native@^1.0.5: - version "1.0.9" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" - integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== - dependencies: - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -4803,11 +4647,6 @@ require-from-string@^2.0.0, require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -4830,12 +4669,12 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.22.1: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== +resolve@^1.1.6, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: - is-core-module "^2.11.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -4859,11 +4698,11 @@ rimraf@^3.0.2: glob "^7.1.3" rimraf@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.1.tgz#0881323ab94ad45fec7c0221f27ea1a142f3f0d0" - integrity sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg== + version "5.0.5" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" + integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== dependencies: - glob "^10.2.5" + glob "^10.3.7" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" @@ -4880,6 +4719,13 @@ rlp@^2.2.3, rlp@^2.2.4: dependencies: bn.js "^5.2.0" +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -4899,13 +4745,13 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -safe-array-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" - integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.2.0" + get-intrinsic "^1.2.1" has-symbols "^1.0.3" isarray "^2.0.5" @@ -4928,7 +4774,7 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -4953,11 +4799,6 @@ sc-istanbul@^0.4.5: which "^1.1.1" wordwrap "^1.0.0" -scrypt-js@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" - integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== - scrypt-js@3.0.1, scrypt-js@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" @@ -4972,20 +4813,20 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -semver@^5.5.0, semver@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.7, semver@^7.3.8: - version "7.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" - integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== +semver@^7.3.4, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" @@ -4996,15 +4837,24 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog== +set-function-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" setimmediate@^1.0.5: version "1.0.5" @@ -5062,10 +4912,15 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" - integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== slash@^3.0.0: version "3.0.0" @@ -5096,17 +4951,18 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" -solhint-plugin-prettier@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.0.5.tgz#e3b22800ba435cd640a9eca805a7f8bc3e3e6a6b" - integrity sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA== +solhint-plugin-prettier@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.1.0.tgz#2f46999e26d6c6bc80281c22a7a21e381175bef7" + integrity sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw== dependencies: + "@prettier/sync" "^0.3.0" prettier-linter-helpers "^1.0.0" solhint@^3.3.7: - version "3.4.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.4.1.tgz#8ea15b21c13d1be0b53fd46d605a24d0b36a0c46" - integrity sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg== + version "3.6.2" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.6.2.tgz#2b2acbec8fdc37b2c68206a71ba89c7f519943fe" + integrity sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ== dependencies: "@solidity-parser/parser" "^0.16.0" ajv "^6.12.6" @@ -5121,7 +4977,7 @@ solhint@^3.3.7: js-yaml "^4.1.0" lodash "^4.17.21" pluralize "^8.0.0" - semver "^6.3.0" + semver "^7.5.2" strip-ansi "^6.0.1" table "^6.8.1" text-table "^0.2.0" @@ -5134,9 +4990,9 @@ solidity-comments-extractor@^0.0.7: integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== solidity-coverage@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.4.tgz#c57a21979f5e86859c5198de9fbae2d3bc6324a5" - integrity sha512-xeHOfBOjdMF6hWTbt42iH4x+7j1Atmrf5OldDPMxI+i/COdExUxszOswD9qqvcBTaLGiOrrpnh9UZjSpt4rBsg== + version "0.8.5" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.5.tgz#64071c3a0c06a0cecf9a7776c35f49edc961e875" + integrity sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ== dependencies: "@ethersproject/abi" "^5.0.9" "@solidity-parser/parser" "^0.16.0" @@ -5150,7 +5006,7 @@ solidity-coverage@^0.8.4: globby "^10.0.1" jsonschema "^1.2.4" lodash "^4.17.15" - mocha "7.1.2" + mocha "10.2.0" node-emoji "^1.10.0" pify "^4.0.1" recursive-readdir "^2.2.2" @@ -5184,21 +5040,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - stacktrace-parser@^0.1.10: version "0.1.10" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" @@ -5211,16 +5052,6 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - string-format@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" @@ -5235,7 +5066,7 @@ string-format@^2.0.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -"string-width@^1.0.2 || 2", string-width@^2.1.1: +string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5243,15 +5074,6 @@ string-format@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -5261,32 +5083,32 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.trim@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string_decoder@^1.1.1: version "1.3.0" @@ -5316,13 +5138,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -5335,6 +5150,16 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" @@ -5342,23 +5167,11 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" -strip-json-comments@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - supports-color@8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -5408,6 +5221,14 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" +synckit@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" + integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q== + dependencies: + "@pkgr/utils" "^2.3.1" + tslib "^2.5.0" + table-layout@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" @@ -5451,6 +5272,11 @@ then-request@^6.0.0: promise "^8.0.0" qs "^6.4.0" +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -5470,20 +5296,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tough-cookie@^2.3.3, tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - ts-command-line-args@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.0.tgz#7eeed3a6937b2612ea08a0794cf9d43fbbea89c4" - integrity sha512-Ff7Xt04WWCjj/cmPO9eWTJX3qpBZWuPWyQYG1vnxJao+alWWYjwJBc5aYz3h5p5dE08A6AnpkgiCtP/0KXXBYw== + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== dependencies: - "@morgan-stanley/ts-mocking-bird" "^0.6.2" chalk "^4.1.0" command-line-args "^5.1.1" command-line-usage "^6.1.0" @@ -5513,7 +5330,7 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.14.1: +tsconfig-paths@^3.14.2: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== @@ -5528,6 +5345,11 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.5.0, tslib@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsort@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" @@ -5540,23 +5362,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== - tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" @@ -5576,7 +5386,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -5597,9 +5407,9 @@ type-fest@^0.7.1: integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== typechain@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.0.tgz#d95566de822332651152bd682ed1ec7b0e1b8610" - integrity sha512-AxtAYyOA7f2p28/JkcqrF+gnzam94VNTIbXcaUKodkrKzMX6P/XqBaP6d/OPuBZOi0WgOOmkg1zOSojX8uGkOg== + version "8.3.2" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.2.tgz#1090dd8d9c57b6ef2aed3640a516bdbf01b00d73" + integrity sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q== dependencies: "@types/prettier" "^2.1.1" debug "^4.3.1" @@ -5612,6 +5422,36 @@ typechain@^8.3.0: ts-command-line-args "^2.2.0" ts-essentials "^7.0.1" +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + typed-array-length@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" @@ -5626,10 +5466,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" - integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== +typescript@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== typical@^4.0.0: version "4.0.0" @@ -5656,12 +5496,17 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + undici@^5.14.0: - version "5.22.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.0.tgz#5e205d82a5aecc003fc4388ccd3d2c6e8674a0ad" - integrity sha512-fR9RXCc+6Dxav4P9VV/sp5w3eFiSdOjJYsbtWfd4s5L5C4ogyuVpdKIVHeW0vV1MloM65/f7W45nR9ZxwVdyiA== + version "5.27.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.27.0.tgz#789f2e40ce982b5507899abc2c2ddeb2712b4554" + integrity sha512-l3ydWhlhOJzMVOYkymLykcRRXqbUaQriERtR70B9LzNkZ4bX52Fc8wbTDneMiwo8T+AemZXvXaTx+9o5ROxrXg== dependencies: - busboy "^1.6.0" + "@fastify/busboy" "^2.0.0" universalify@^0.1.0: version "0.1.2" @@ -5678,6 +5523,11 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -5695,21 +5545,6 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg== - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" - integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== - uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -5720,23 +5555,15 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - web3-utils@^1.3.6: - version "1.9.0" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.9.0.tgz#7c5775a47586cefb4ad488831be8f6627be9283d" - integrity sha512-p++69rCNNfu2jM9n5+VD/g26l+qkEOQ1m6cfRQCbH8ZRrtquTmrirJMgTmyOoax5a5XRYOuws14aypCOs51pdQ== + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.3.tgz#f1db99c82549c7d9f8348f04ffe4e0188b449714" + integrity sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ== dependencies: + "@ethereumjs/util" "^8.1.0" bn.js "^5.2.1" ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" + ethereum-cryptography "^2.1.2" ethjs-unit "0.1.6" number-to-bn "1.7.0" randombytes "^2.1.0" @@ -5753,24 +5580,18 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== +which-typed-array@^1.1.11, which-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== dependencies: available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + call-bind "^1.0.4" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" -which@1.3.1, which@^1.1.1, which@^1.3.1: +which@^1.1.1, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -5784,17 +5605,10 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wide-align@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wordwrap@^1.0.0: version "1.0.0" @@ -5823,15 +5637,6 @@ workerpool@6.2.1: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -5856,16 +5661,6 @@ ws@^7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -5881,14 +5676,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@13.1.2, yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" @@ -5904,15 +5691,6 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== - dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" - yargs-unparser@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" @@ -5923,22 +5701,6 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@13.3.2, yargs@^13.3.0: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - yargs@16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" From eb990511a653b55a8144c88b0c063ef3826a29e6 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 14:44:05 +0100 Subject: [PATCH 51/82] Bump dependencies --- sdk/factory/mastercopyDeployer.ts | 4 ++- test/05_ModuleProxyFactory.spec.ts | 5 ++- test/06_SignatureChecker.spec.ts | 20 +++++------- test/07_GuardableModifier.spec.ts | 50 ++++++++++++------------------ 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/sdk/factory/mastercopyDeployer.ts b/sdk/factory/mastercopyDeployer.ts index 1522c447..7f5dacae 100644 --- a/sdk/factory/mastercopyDeployer.ts +++ b/sdk/factory/mastercopyDeployer.ts @@ -105,7 +105,9 @@ export const deployMastercopyWithInitData = async ( ); if (targetAddress === AddressZero) { - console.log(` ✔ Mastercopy already deployed to: ${computedTargetAddress}`); + console.log( + ` ✔ Mastercopy already deployed to: ${computedTargetAddress}` + ); return AddressZero; } diff --git a/test/05_ModuleProxyFactory.spec.ts b/test/05_ModuleProxyFactory.spec.ts index c6b8dd43..7f0951c0 100644 --- a/test/05_ModuleProxyFactory.spec.ts +++ b/test/05_ModuleProxyFactory.spec.ts @@ -16,9 +16,8 @@ describe("ModuleProxyFactory", async () => { beforeEach(async () => { const Avatar = await ethers.getContractFactory("TestAvatar"); const avatar = await Avatar.deploy(); - const ModuleProxyFactory = await ethers.getContractFactory( - "ModuleProxyFactory" - ); + const ModuleProxyFactory = + await ethers.getContractFactory("ModuleProxyFactory"); moduleFactory = await ModuleProxyFactory.deploy(); const MasterCopyModule = await ethers.getContractFactory("TestModule"); diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 6886b27a..3c0f26cf 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -86,9 +86,8 @@ describe("SignatureChecker", async () => { it("s pointing out of bounds fails", async () => { const { testSignature, relayer } = await loadFixture(setup); - const ContractSigner = await hre.ethers.getContractFactory( - "ContractSignerYes" - ); + const ContractSigner = + await hre.ethers.getContractFactory("ContractSignerYes"); const signer = (await ContractSigner.deploy()).address; const transaction = await testSignature.populateTransaction.hello(); @@ -132,9 +131,8 @@ describe("SignatureChecker", async () => { it("s pointing to selector fails", async () => { const { testSignature, relayer } = await loadFixture(setup); - const ContractSigner = await hre.ethers.getContractFactory( - "ContractSignerYes" - ); + const ContractSigner = + await hre.ethers.getContractFactory("ContractSignerYes"); const signer = (await ContractSigner.deploy()).address; const transaction = await testSignature.populateTransaction.hello(); @@ -176,9 +174,8 @@ describe("SignatureChecker", async () => { it("s pointing to signature fails", async () => { const { testSignature, relayer } = await loadFixture(setup); - const ContractSigner = await hre.ethers.getContractFactory( - "ContractSignerYes" - ); + const ContractSigner = + await hre.ethers.getContractFactory("ContractSignerYes"); const signer = (await ContractSigner.deploy()).address; const transaction = await testSignature.populateTransaction.hello(); @@ -268,9 +265,8 @@ describe("SignatureChecker", async () => { it("signer returns isValid yes", async () => { const { testSignature, relayer } = await loadFixture(setup); - const ContractSigner = await hre.ethers.getContractFactory( - "ContractSignerYes" - ); + const ContractSigner = + await hre.ethers.getContractFactory("ContractSignerYes"); const contractSigner = await ContractSigner.deploy(); const transaction = await testSignature.populateTransaction.goodbye( diff --git a/test/07_GuardableModifier.spec.ts b/test/07_GuardableModifier.spec.ts index 40ff355a..801ed16e 100644 --- a/test/07_GuardableModifier.spec.ts +++ b/test/07_GuardableModifier.spec.ts @@ -63,9 +63,8 @@ describe("GuardableModifier", async () => { }); it("pre-checks transaction if guard is set", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await modifier.setGuard(guard.address); await expect( @@ -78,9 +77,8 @@ describe("GuardableModifier", async () => { }); it("pre-check gets called with signer when transaction is relayed", async () => { - const { signer, modifier, relayer, avatar, guard } = await loadFixture( - setupTests - ); + const { signer, modifier, relayer, avatar, guard } = + await loadFixture(setupTests); await modifier.enableModule(signer.address); await modifier.setGuard(guard.address); @@ -116,9 +114,8 @@ describe("GuardableModifier", async () => { }); it("pre-checks and reverts transaction if guard is set", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await modifier.setGuard(guard.address); await expect( @@ -129,9 +126,8 @@ describe("GuardableModifier", async () => { }); it("skips post-check if no guard is enabled", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await expect( modifier @@ -141,9 +137,8 @@ describe("GuardableModifier", async () => { }); it("post-checks transaction if guard is set", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await modifier.setGuard(guard.address); await expect( @@ -168,9 +163,8 @@ describe("GuardableModifier", async () => { }); it("pre-checks transaction if guard is set", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await modifier.setGuard(guard.address); await expect( @@ -183,9 +177,8 @@ describe("GuardableModifier", async () => { }); it("pre-check gets called with signer when transaction is relayed", async () => { - const { signer, modifier, relayer, avatar, guard } = await loadFixture( - setupTests - ); + const { signer, modifier, relayer, avatar, guard } = + await loadFixture(setupTests); await modifier.enableModule(signer.address); await modifier.setGuard(guard.address); @@ -221,9 +214,8 @@ describe("GuardableModifier", async () => { }); it("pre-checks and reverts transaction if guard is set", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await modifier.setGuard(guard.address); await expect( @@ -234,9 +226,8 @@ describe("GuardableModifier", async () => { }); it("skips post-check if no guard is enabled", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await expect( modifier @@ -246,9 +237,8 @@ describe("GuardableModifier", async () => { }); it("post-checks transaction if guard is set", async () => { - const { avatar, executor, modifier, guard } = await loadFixture( - setupTests - ); + const { avatar, executor, modifier, guard } = + await loadFixture(setupTests); await modifier.setGuard(guard.address); await expect( From ef701358b08950e0235150d5208c7c45bfa2cffd Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 14:44:54 +0100 Subject: [PATCH 52/82] Yarn format:sol --- contracts/core/GuardableModifier.sol | 157 ++++++----- contracts/core/GuardableModule.sol | 157 ++++++----- contracts/core/Modifier.sol | 318 +++++++++++------------ contracts/core/Module.sol | 119 ++++----- contracts/factory/FactoryFriendly.sol | 2 +- contracts/factory/ModuleProxyFactory.sol | 89 +++---- contracts/guard/BaseGuard.sol | 48 ++-- contracts/guard/Guardable.sol | 32 +-- contracts/interfaces/IAvatar.sol | 112 ++++---- contracts/interfaces/IGuard.sol | 28 +- contracts/signature/ExecutionTracker.sol | 16 +- contracts/signature/IERC1271.sol | 26 +- contracts/signature/SignatureChecker.sol | 260 +++++++++--------- contracts/test/TestAvatar.sol | 94 +++---- contracts/test/TestGuard.sol | 114 ++++---- contracts/test/TestGuardableModifier.sol | 143 +++++----- contracts/test/TestModifier.sol | 143 +++++----- contracts/test/TestModule.sol | 106 ++++---- contracts/test/TestSignature.sol | 86 +++--- 19 files changed, 1014 insertions(+), 1036 deletions(-) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 90c29b1a..e630a241 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -5,88 +5,87 @@ import "../guard/Guardable.sol"; import "./Modifier.sol"; abstract contract GuardableModifier is Module, Guardable, Modifier { - /// @dev Passes a transaction to be executed by the avatar. - /// @notice Can only be called by this contract. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function exec( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) internal virtual override returns (bool success) { - address currentGuard = guard; - if (currentGuard != address(0)) { - IGuard(currentGuard).checkTransaction( - /// Transaction info used by module transactions. - to, - value, - data, - operation, - /// Zero out the redundant transaction information only used for Safe multisig transctions. - 0, - 0, - 0, - address(0), - payable(0), - "", - sentOrSignedBy() - ); - } - success = IAvatar(target).execTransactionFromModule( - to, - value, - data, - operation - ); - if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution(bytes32(0), success); - } + /// @dev Passes a transaction to be executed by the avatar. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function exec( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal virtual override returns (bool success) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + sentOrSignedBy() + ); } + success = IAvatar(target).execTransactionFromModule( + to, + value, + data, + operation + ); + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); + } + } - /// @dev Passes a transaction to be executed by the target and returns data. - /// @notice Can only be called by this contract. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function execAndReturnData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) - internal - virtual - override - returns (bool success, bytes memory returnData) - { - address currentGuard = guard; - if (currentGuard != address(0)) { - IGuard(currentGuard).checkTransaction( - /// Transaction info used by module transactions. - to, - value, - data, - operation, - /// Zero out the redundant transaction information only used for Safe multisig transctions. - 0, - 0, - 0, - address(0), - payable(0), - "", - sentOrSignedBy() - ); - } + /// @dev Passes a transaction to be executed by the target and returns data. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execAndReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal virtual override returns (bool success, bytes memory returnData) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + sentOrSignedBy() + ); + } - (success, returnData) = IAvatar(target) - .execTransactionFromModuleReturnData(to, value, data, operation); + (success, returnData) = IAvatar(target).execTransactionFromModuleReturnData( + to, + value, + data, + operation + ); - if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution(bytes32(0), success); - } + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } + } } diff --git a/contracts/core/GuardableModule.sol b/contracts/core/GuardableModule.sol index 94fb3fb2..b0691548 100644 --- a/contracts/core/GuardableModule.sol +++ b/contracts/core/GuardableModule.sol @@ -6,88 +6,87 @@ import "./Module.sol"; /// @title GuardableModule - A contract that can pass messages to a Module Manager contract if enabled by that contract. abstract contract GuardableModule is Module, Guardable { - /// @dev Passes a transaction to be executed by the avatar. - /// @notice Can only be called by this contract. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function exec( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) internal override returns (bool success) { - address currentGuard = guard; - if (currentGuard != address(0)) { - IGuard(currentGuard).checkTransaction( - /// Transaction info used by module transactions. - to, - value, - data, - operation, - /// Zero out the redundant transaction information only used for Safe multisig transctions. - 0, - 0, - 0, - address(0), - payable(0), - "", - msg.sender - ); - } - success = IAvatar(target).execTransactionFromModule( - to, - value, - data, - operation - ); - if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution(bytes32(0), success); - } + /// @dev Passes a transaction to be executed by the avatar. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function exec( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal override returns (bool success) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + msg.sender + ); } + success = IAvatar(target).execTransactionFromModule( + to, + value, + data, + operation + ); + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); + } + } - /// @dev Passes a transaction to be executed by the target and returns data. - /// @notice Can only be called by this contract. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function execAndReturnData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) - internal - virtual - override - returns (bool success, bytes memory returnData) - { - address currentGuard = guard; - if (currentGuard != address(0)) { - IGuard(currentGuard).checkTransaction( - /// Transaction info used by module transactions. - to, - value, - data, - operation, - /// Zero out the redundant transaction information only used for Safe multisig transctions. - 0, - 0, - 0, - address(0), - payable(0), - "", - msg.sender - ); - } + /// @dev Passes a transaction to be executed by the target and returns data. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execAndReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal virtual override returns (bool success, bytes memory returnData) { + address currentGuard = guard; + if (currentGuard != address(0)) { + IGuard(currentGuard).checkTransaction( + /// Transaction info used by module transactions. + to, + value, + data, + operation, + /// Zero out the redundant transaction information only used for Safe multisig transctions. + 0, + 0, + 0, + address(0), + payable(0), + "", + msg.sender + ); + } - (success, returnData) = IAvatar(target) - .execTransactionFromModuleReturnData(to, value, data, operation); + (success, returnData) = IAvatar(target).execTransactionFromModuleReturnData( + to, + value, + data, + operation + ); - if (currentGuard != address(0)) { - IGuard(currentGuard).checkAfterExecution(bytes32(0), success); - } + if (currentGuard != address(0)) { + IGuard(currentGuard).checkAfterExecution(bytes32(0), success); } + } } diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index f2ce79c3..7e56aa3d 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -8,35 +8,35 @@ import "./Module.sol"; /// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. abstract contract Modifier is - Module, - ExecutionTracker, - SignatureChecker, - IAvatar + Module, + ExecutionTracker, + SignatureChecker, + IAvatar { - address internal constant SENTINEL_MODULES = address(0x1); - /// Mapping of modules. - mapping(address => address) internal modules; + address internal constant SENTINEL_MODULES = address(0x1); + /// Mapping of modules. + mapping(address => address) internal modules; - /// `sender` is not an authorized module. - /// @param sender The address of the sender. - error NotAuthorized(address sender); + /// `sender` is not an authorized module. + /// @param sender The address of the sender. + error NotAuthorized(address sender); - /// `module` is invalid. - error InvalidModule(address module); + /// `module` is invalid. + error InvalidModule(address module); - /// `pageSize` is invalid. - error InvalidPageSize(); + /// `pageSize` is invalid. + error InvalidPageSize(); - /// `module` is already disabled. - error AlreadyDisabledModule(address module); + /// `module` is already disabled. + error AlreadyDisabledModule(address module); - /// `module` is already enabled. - error AlreadyEnabledModule(address module); + /// `module` is already enabled. + error AlreadyEnabledModule(address module); - /// @dev `setModules()` was already called. - error SetupModulesAlreadyCalled(); + /// @dev `setModules()` was already called. + error SetupModulesAlreadyCalled(); - /* + /* -------------------------------------------------- You must override both of the following virtual functions, execTransactionFromModule() and execTransactionFromModuleReturnData(). @@ -44,162 +44,160 @@ abstract contract Modifier is onlyModule modifier. */ - /// @dev Passes a transaction to the modifier. - /// @notice Can only be called by enabled modules. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction. - function execTransactionFromModule( - address to, - uint256 value, - bytes calldata data, - Enum.Operation operation - ) public virtual returns (bool success); - - /// @dev Passes a transaction to the modifier, expects return data. - /// @notice Can only be called by enabled modules. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction. - function execTransactionFromModuleReturnData( - address to, - uint256 value, - bytes calldata data, - Enum.Operation operation - ) public virtual returns (bool success, bytes memory returnData); - - /* + /// @dev Passes a transaction to the modifier. + /// @notice Can only be called by enabled modules. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction. + function execTransactionFromModule( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public virtual returns (bool success); + + /// @dev Passes a transaction to the modifier, expects return data. + /// @notice Can only be called by enabled modules. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction. + function execTransactionFromModuleReturnData( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public virtual returns (bool success, bytes memory returnData); + + /* -------------------------------------------------- */ - modifier moduleOnly() { - if (modules[msg.sender] == address(0)) { - (bytes32 hash, address signer) = moduleTxSignedBy(); + modifier moduleOnly() { + if (modules[msg.sender] == address(0)) { + (bytes32 hash, address signer) = moduleTxSignedBy(); - // is the signer a module? - if (modules[signer] == address(0)) { - revert NotAuthorized(msg.sender); - } + // is the signer a module? + if (modules[signer] == address(0)) { + revert NotAuthorized(msg.sender); + } - // is the provided signature fresh? - if (consumed[signer][hash]) { - revert HashAlreadyConsumed(hash); - } + // is the provided signature fresh? + if (consumed[signer][hash]) { + revert HashAlreadyConsumed(hash); + } - consumed[signer][hash] = true; - emit HashExecuted(hash); - } - - _; + consumed[signer][hash] = true; + emit HashExecuted(hash); } - function sentOrSignedBy() internal view returns (address) { - if (modules[msg.sender] != address(0)) { - return msg.sender; - } - - (, address signer) = moduleTxSignedBy(); - if (modules[signer] != address(0)) { - return signer; - } + _; + } - return address(0); + function sentOrSignedBy() internal view returns (address) { + if (modules[msg.sender] != address(0)) { + return msg.sender; } - /// @dev Disables a module on the modifier. - /// @notice This can only be called by the owner. - /// @param prevModule Module that pointed to the module to be removed in the linked list. - /// @param module Module to be removed. - function disableModule( - address prevModule, - address module - ) public override onlyOwner { - if (module == address(0) || module == SENTINEL_MODULES) - revert InvalidModule(module); - if (modules[prevModule] != module) revert AlreadyDisabledModule(module); - modules[prevModule] = modules[module]; - modules[module] = address(0); - emit DisabledModule(module); + (, address signer) = moduleTxSignedBy(); + if (modules[signer] != address(0)) { + return signer; } - /// @dev Enables a module that can add transactions to the queue - /// @param module Address of the module to be enabled - /// @notice This can only be called by the owner - function enableModule(address module) public override onlyOwner { - if (module == address(0) || module == SENTINEL_MODULES) - revert InvalidModule(module); - if (modules[module] != address(0)) revert AlreadyEnabledModule(module); - modules[module] = modules[SENTINEL_MODULES]; - modules[SENTINEL_MODULES] = module; - emit EnabledModule(module); + return address(0); + } + + /// @dev Disables a module on the modifier. + /// @notice This can only be called by the owner. + /// @param prevModule Module that pointed to the module to be removed in the linked list. + /// @param module Module to be removed. + function disableModule( + address prevModule, + address module + ) public override onlyOwner { + if (module == address(0) || module == SENTINEL_MODULES) + revert InvalidModule(module); + if (modules[prevModule] != module) revert AlreadyDisabledModule(module); + modules[prevModule] = modules[module]; + modules[module] = address(0); + emit DisabledModule(module); + } + + /// @dev Enables a module that can add transactions to the queue + /// @param module Address of the module to be enabled + /// @notice This can only be called by the owner + function enableModule(address module) public override onlyOwner { + if (module == address(0) || module == SENTINEL_MODULES) + revert InvalidModule(module); + if (modules[module] != address(0)) revert AlreadyEnabledModule(module); + modules[module] = modules[SENTINEL_MODULES]; + modules[SENTINEL_MODULES] = module; + emit EnabledModule(module); + } + + /// @dev Returns if an module is enabled + /// @return True if the module is enabled + function isModuleEnabled( + address _module + ) public view override returns (bool) { + return SENTINEL_MODULES != _module && modules[_module] != address(0); + } + + /// @dev Returns array of modules. + /// If all entries fit into a single page, the next pointer will be 0x1. + /// If another page is present, next will be the last element of the returned array. + /// @param start Start of the page. Has to be a module or start pointer (0x1 address) + /// @param pageSize Maximum number of modules that should be returned. Has to be > 0 + /// @return array Array of modules. + /// @return next Start of the next page. + function getModulesPaginated( + address start, + uint256 pageSize + ) external view override returns (address[] memory array, address next) { + if (start != SENTINEL_MODULES && !isModuleEnabled(start)) { + revert InvalidModule(start); } - - /// @dev Returns if an module is enabled - /// @return True if the module is enabled - function isModuleEnabled( - address _module - ) public view override returns (bool) { - return SENTINEL_MODULES != _module && modules[_module] != address(0); + if (pageSize == 0) { + revert InvalidPageSize(); } - /// @dev Returns array of modules. - /// If all entries fit into a single page, the next pointer will be 0x1. - /// If another page is present, next will be the last element of the returned array. - /// @param start Start of the page. Has to be a module or start pointer (0x1 address) - /// @param pageSize Maximum number of modules that should be returned. Has to be > 0 - /// @return array Array of modules. - /// @return next Start of the next page. - function getModulesPaginated( - address start, - uint256 pageSize - ) external view override returns (address[] memory array, address next) { - if (start != SENTINEL_MODULES && !isModuleEnabled(start)) { - revert InvalidModule(start); - } - if (pageSize == 0) { - revert InvalidPageSize(); - } - - // Init array with max page size - array = new address[](pageSize); - - // Populate return array - uint256 moduleCount = 0; - next = modules[start]; - while ( - next != address(0) && - next != SENTINEL_MODULES && - moduleCount < pageSize - ) { - array[moduleCount] = next; - next = modules[next]; - moduleCount++; - } - - // Because of the argument validation we can assume that - // the `currentModule` will always be either a module address - // or sentinel address (aka the end). If we haven't reached the end - // inside the loop, we need to set the next pointer to the last element - // because it skipped over to the next module which is neither included - // in the current page nor won't be included in the next one - // if you pass it as a start. - if (next != SENTINEL_MODULES) { - next = array[moduleCount - 1]; - } - // Set correct size of returned array - // solhint-disable-next-line no-inline-assembly - assembly { - mstore(array, moduleCount) - } + // Init array with max page size + array = new address[](pageSize); + + // Populate return array + uint256 moduleCount = 0; + next = modules[start]; + while ( + next != address(0) && next != SENTINEL_MODULES && moduleCount < pageSize + ) { + array[moduleCount] = next; + next = modules[next]; + moduleCount++; } - /// @dev Initializes the modules linked list. - /// @notice Should be called as part of the `setUp` / initializing function and can only be called once. - function setupModules() internal { - if (modules[SENTINEL_MODULES] != address(0)) - revert SetupModulesAlreadyCalled(); - modules[SENTINEL_MODULES] = SENTINEL_MODULES; + // Because of the argument validation we can assume that + // the `currentModule` will always be either a module address + // or sentinel address (aka the end). If we haven't reached the end + // inside the loop, we need to set the next pointer to the last element + // because it skipped over to the next module which is neither included + // in the current page nor won't be included in the next one + // if you pass it as a start. + if (next != SENTINEL_MODULES) { + next = array[moduleCount - 1]; + } + // Set correct size of returned array + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(array, moduleCount) } + } + + /// @dev Initializes the modules linked list. + /// @notice Should be called as part of the `setUp` / initializing function and can only be called once. + function setupModules() internal { + if (modules[SENTINEL_MODULES] != address(0)) + revert SetupModulesAlreadyCalled(); + modules[SENTINEL_MODULES] = SENTINEL_MODULES; + } } diff --git a/contracts/core/Module.sol b/contracts/core/Module.sol index dbf37f95..831c9ef2 100644 --- a/contracts/core/Module.sol +++ b/contracts/core/Module.sol @@ -6,71 +6,66 @@ import "../interfaces/IAvatar.sol"; /// @title Module Interface - A contract that can pass messages to a Module Manager contract if enabled by that contract. abstract contract Module is FactoryFriendly { - /// @dev Address that will ultimately execute function calls. - address public avatar; - /// @dev Address that this module will pass transactions to. - address public target; + /// @dev Address that will ultimately execute function calls. + address public avatar; + /// @dev Address that this module will pass transactions to. + address public target; - /// @dev Emitted each time the avatar is set. - event AvatarSet(address indexed previousAvatar, address indexed newAvatar); - /// @dev Emitted each time the Target is set. - event TargetSet(address indexed previousTarget, address indexed newTarget); + /// @dev Emitted each time the avatar is set. + event AvatarSet(address indexed previousAvatar, address indexed newAvatar); + /// @dev Emitted each time the Target is set. + event TargetSet(address indexed previousTarget, address indexed newTarget); - /// @dev Sets the avatar to a new avatar (`newAvatar`). - /// @notice Can only be called by the current owner. - function setAvatar(address _avatar) public onlyOwner { - address previousAvatar = avatar; - avatar = _avatar; - emit AvatarSet(previousAvatar, _avatar); - } + /// @dev Sets the avatar to a new avatar (`newAvatar`). + /// @notice Can only be called by the current owner. + function setAvatar(address _avatar) public onlyOwner { + address previousAvatar = avatar; + avatar = _avatar; + emit AvatarSet(previousAvatar, _avatar); + } - /// @dev Sets the target to a new target (`newTarget`). - /// @notice Can only be called by the current owner. - function setTarget(address _target) public onlyOwner { - address previousTarget = target; - target = _target; - emit TargetSet(previousTarget, _target); - } + /// @dev Sets the target to a new target (`newTarget`). + /// @notice Can only be called by the current owner. + function setTarget(address _target) public onlyOwner { + address previousTarget = target; + target = _target; + emit TargetSet(previousTarget, _target); + } - /// @dev Passes a transaction to be executed by the avatar. - /// @notice Can only be called by this contract. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function exec( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) internal virtual returns (bool success) { - return - IAvatar(target).execTransactionFromModule( - to, - value, - data, - operation - ); - } + /// @dev Passes a transaction to be executed by the avatar. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function exec( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal virtual returns (bool success) { + return + IAvatar(target).execTransactionFromModule(to, value, data, operation); + } - /// @dev Passes a transaction to be executed by the target and returns data. - /// @notice Can only be called by this contract. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function execAndReturnData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) internal virtual returns (bool success, bytes memory returnData) { - return - IAvatar(target).execTransactionFromModuleReturnData( - to, - value, - data, - operation - ); - } + /// @dev Passes a transaction to be executed by the target and returns data. + /// @notice Can only be called by this contract. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execAndReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) internal virtual returns (bool success, bytes memory returnData) { + return + IAvatar(target).execTransactionFromModuleReturnData( + to, + value, + data, + operation + ); + } } diff --git a/contracts/factory/FactoryFriendly.sol b/contracts/factory/FactoryFriendly.sol index 1f736df6..96e6e43a 100644 --- a/contracts/factory/FactoryFriendly.sol +++ b/contracts/factory/FactoryFriendly.sol @@ -6,5 +6,5 @@ pragma solidity >=0.7.0 <0.9.0; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract FactoryFriendly is OwnableUpgradeable { - function setUp(bytes memory initializeParams) public virtual; + function setUp(bytes memory initializeParams) public virtual; } diff --git a/contracts/factory/ModuleProxyFactory.sol b/contracts/factory/ModuleProxyFactory.sol index ff2e26dc..419b940e 100644 --- a/contracts/factory/ModuleProxyFactory.sol +++ b/contracts/factory/ModuleProxyFactory.sol @@ -2,53 +2,50 @@ pragma solidity >=0.8.0; contract ModuleProxyFactory { - event ModuleProxyCreation( - address indexed proxy, - address indexed masterCopy + event ModuleProxyCreation(address indexed proxy, address indexed masterCopy); + + /// `target` can not be zero. + error ZeroAddress(address target); + + /// `target` has no code deployed. + error TargetHasNoCode(address target); + + /// `address_` is already taken. + error TakenAddress(address address_); + + /// @notice Initialization failed. + error FailedInitialization(); + + function createProxy( + address target, + bytes32 salt + ) internal returns (address result) { + if (address(target) == address(0)) revert ZeroAddress(target); + if (address(target).code.length == 0) revert TargetHasNoCode(target); + bytes memory deployment = abi.encodePacked( + hex"602d8060093d393df3363d3d373d3d3d363d73", + target, + hex"5af43d82803e903d91602b57fd5bf3" ); - - /// `target` can not be zero. - error ZeroAddress(address target); - - /// `target` has no code deployed. - error TargetHasNoCode(address target); - - /// `address_` is already taken. - error TakenAddress(address address_); - - /// @notice Initialization failed. - error FailedInitialization(); - - function createProxy( - address target, - bytes32 salt - ) internal returns (address result) { - if (address(target) == address(0)) revert ZeroAddress(target); - if (address(target).code.length == 0) revert TargetHasNoCode(target); - bytes memory deployment = abi.encodePacked( - hex"602d8060093d393df3363d3d373d3d3d363d73", - target, - hex"5af43d82803e903d91602b57fd5bf3" - ); - // solhint-disable-next-line no-inline-assembly - assembly { - result := create2(0, add(deployment, 0x20), mload(deployment), salt) - } - if (result == address(0)) revert TakenAddress(result); + // solhint-disable-next-line no-inline-assembly + assembly { + result := create2(0, add(deployment, 0x20), mload(deployment), salt) } + if (result == address(0)) revert TakenAddress(result); + } + + function deployModule( + address masterCopy, + bytes memory initializer, + uint256 saltNonce + ) public returns (address proxy) { + proxy = createProxy( + masterCopy, + keccak256(abi.encodePacked(keccak256(initializer), saltNonce)) + ); + (bool success, ) = proxy.call(initializer); + if (!success) revert FailedInitialization(); - function deployModule( - address masterCopy, - bytes memory initializer, - uint256 saltNonce - ) public returns (address proxy) { - proxy = createProxy( - masterCopy, - keccak256(abi.encodePacked(keccak256(initializer), saltNonce)) - ); - (bool success, ) = proxy.call(initializer); - if (!success) revert FailedInitialization(); - - emit ModuleProxyCreation(proxy, masterCopy); - } + emit ModuleProxyCreation(proxy, masterCopy); + } } diff --git a/contracts/guard/BaseGuard.sol b/contracts/guard/BaseGuard.sol index 6e892bbc..d6d691e7 100644 --- a/contracts/guard/BaseGuard.sol +++ b/contracts/guard/BaseGuard.sol @@ -6,30 +6,30 @@ import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "../interfaces/IGuard.sol"; abstract contract BaseGuard is IERC165 { - function supportsInterface( - bytes4 interfaceId - ) external pure override returns (bool) { - return - interfaceId == type(IGuard).interfaceId || // 0xe6d7a83a - interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7 - } + function supportsInterface( + bytes4 interfaceId + ) external pure override returns (bool) { + return + interfaceId == type(IGuard).interfaceId || // 0xe6d7a83a + interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7 + } - /// @dev Module transactions only use the first four parameters: to, value, data, and operation. - /// Module.sol hardcodes the remaining parameters as 0 since they are not used for module transactions. - /// @notice This interface is used to maintain compatibilty with Gnosis Safe transaction guards. - function checkTransaction( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation, - uint256 safeTxGas, - uint256 baseGas, - uint256 gasPrice, - address gasToken, - address payable refundReceiver, - bytes memory signatures, - address msgSender - ) external virtual; + /// @dev Module transactions only use the first four parameters: to, value, data, and operation. + /// Module.sol hardcodes the remaining parameters as 0 since they are not used for module transactions. + /// @notice This interface is used to maintain compatibilty with Gnosis Safe transaction guards. + function checkTransaction( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation, + uint256 safeTxGas, + uint256 baseGas, + uint256 gasPrice, + address gasToken, + address payable refundReceiver, + bytes memory signatures, + address msgSender + ) external virtual; - function checkAfterExecution(bytes32 txHash, bool success) external virtual; + function checkAfterExecution(bytes32 txHash, bool success) external virtual; } diff --git a/contracts/guard/Guardable.sol b/contracts/guard/Guardable.sol index 886f85c6..71ed9ea2 100644 --- a/contracts/guard/Guardable.sol +++ b/contracts/guard/Guardable.sol @@ -7,25 +7,25 @@ import "./BaseGuard.sol"; /// @title Guardable - A contract that manages fallback calls made to this contract contract Guardable is OwnableUpgradeable { - address public guard; + address public guard; - event ChangedGuard(address guard); + event ChangedGuard(address guard); - /// `guard_` does not implement IERC165. - error NotIERC165Compliant(address guard_); + /// `guard_` does not implement IERC165. + error NotIERC165Compliant(address guard_); - /// @dev Set a guard that checks transactions before execution. - /// @param _guard The address of the guard to be used or the 0 address to disable the guard. - function setGuard(address _guard) external onlyOwner { - if (_guard != address(0)) { - if (!BaseGuard(_guard).supportsInterface(type(IGuard).interfaceId)) - revert NotIERC165Compliant(_guard); - } - guard = _guard; - emit ChangedGuard(guard); + /// @dev Set a guard that checks transactions before execution. + /// @param _guard The address of the guard to be used or the 0 address to disable the guard. + function setGuard(address _guard) external onlyOwner { + if (_guard != address(0)) { + if (!BaseGuard(_guard).supportsInterface(type(IGuard).interfaceId)) + revert NotIERC165Compliant(_guard); } + guard = _guard; + emit ChangedGuard(guard); + } - function getGuard() external view returns (address _guard) { - return guard; - } + function getGuard() external view returns (address _guard) { + return guard; + } } diff --git a/contracts/interfaces/IAvatar.sol b/contracts/interfaces/IAvatar.sol index 7c4ebfdc..64bf1ec1 100644 --- a/contracts/interfaces/IAvatar.sol +++ b/contracts/interfaces/IAvatar.sol @@ -6,66 +6,66 @@ pragma solidity >=0.7.0 <0.9.0; import "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; interface IAvatar { - event EnabledModule(address module); - event DisabledModule(address module); - event ExecutionFromModuleSuccess(address indexed module); - event ExecutionFromModuleFailure(address indexed module); + event EnabledModule(address module); + event DisabledModule(address module); + event ExecutionFromModuleSuccess(address indexed module); + event ExecutionFromModuleFailure(address indexed module); - /// @dev Enables a module on the avatar. - /// @notice Can only be called by the avatar. - /// @notice Modules should be stored as a linked list. - /// @notice Must emit EnabledModule(address module) if successful. - /// @param module Module to be enabled. - function enableModule(address module) external; + /// @dev Enables a module on the avatar. + /// @notice Can only be called by the avatar. + /// @notice Modules should be stored as a linked list. + /// @notice Must emit EnabledModule(address module) if successful. + /// @param module Module to be enabled. + function enableModule(address module) external; - /// @dev Disables a module on the avatar. - /// @notice Can only be called by the avatar. - /// @notice Must emit DisabledModule(address module) if successful. - /// @param prevModule Address that pointed to the module to be removed in the linked list - /// @param module Module to be removed. - function disableModule(address prevModule, address module) external; + /// @dev Disables a module on the avatar. + /// @notice Can only be called by the avatar. + /// @notice Must emit DisabledModule(address module) if successful. + /// @param prevModule Address that pointed to the module to be removed in the linked list + /// @param module Module to be removed. + function disableModule(address prevModule, address module) external; - /// @dev Allows a Module to execute a transaction. - /// @notice Can only be called by an enabled module. - /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful. - /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function execTransactionFromModule( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) external returns (bool success); + /// @dev Allows a Module to execute a transaction. + /// @notice Can only be called by an enabled module. + /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful. + /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execTransactionFromModule( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) external returns (bool success); - /// @dev Allows a Module to execute a transaction and return data - /// @notice Can only be called by an enabled module. - /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful. - /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful. - /// @param to Destination address of module transaction. - /// @param value Ether value of module transaction. - /// @param data Data payload of module transaction. - /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. - function execTransactionFromModuleReturnData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) external returns (bool success, bytes memory returnData); + /// @dev Allows a Module to execute a transaction and return data + /// @notice Can only be called by an enabled module. + /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful. + /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful. + /// @param to Destination address of module transaction. + /// @param value Ether value of module transaction. + /// @param data Data payload of module transaction. + /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. + function execTransactionFromModuleReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) external returns (bool success, bytes memory returnData); - /// @dev Returns if an module is enabled - /// @return True if the module is enabled - function isModuleEnabled(address module) external view returns (bool); + /// @dev Returns if an module is enabled + /// @return True if the module is enabled + function isModuleEnabled(address module) external view returns (bool); - /// @dev Returns array of modules. - /// @param start Start of the page. - /// @param pageSize Maximum number of modules that should be returned. - /// @return array Array of modules. - /// @return next Start of the next page. - function getModulesPaginated( - address start, - uint256 pageSize - ) external view returns (address[] memory array, address next); + /// @dev Returns array of modules. + /// @param start Start of the page. + /// @param pageSize Maximum number of modules that should be returned. + /// @return array Array of modules. + /// @return next Start of the next page. + function getModulesPaginated( + address start, + uint256 pageSize + ) external view returns (address[] memory array, address next); } diff --git a/contracts/interfaces/IGuard.sol b/contracts/interfaces/IGuard.sol index b3926126..f0323f37 100644 --- a/contracts/interfaces/IGuard.sol +++ b/contracts/interfaces/IGuard.sol @@ -4,19 +4,19 @@ pragma solidity >=0.7.0 <0.9.0; import "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; interface IGuard { - function checkTransaction( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation, - uint256 safeTxGas, - uint256 baseGas, - uint256 gasPrice, - address gasToken, - address payable refundReceiver, - bytes memory signatures, - address msgSender - ) external; + function checkTransaction( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation, + uint256 safeTxGas, + uint256 baseGas, + uint256 gasPrice, + address gasToken, + address payable refundReceiver, + bytes memory signatures, + address msgSender + ) external; - function checkAfterExecution(bytes32 txHash, bool success) external; + function checkAfterExecution(bytes32 txHash, bool success) external; } diff --git a/contracts/signature/ExecutionTracker.sol b/contracts/signature/ExecutionTracker.sol index ad88b1d4..2d3119a9 100644 --- a/contracts/signature/ExecutionTracker.sol +++ b/contracts/signature/ExecutionTracker.sol @@ -3,15 +3,15 @@ pragma solidity >=0.8.0 <0.9.0; /// @title ExecutionTracker - A contract that keeps track of executed and invalidated hashes contract ExecutionTracker { - error HashAlreadyConsumed(bytes32); + error HashAlreadyConsumed(bytes32); - event HashExecuted(bytes32); - event HashInvalidated(bytes32); + event HashExecuted(bytes32); + event HashInvalidated(bytes32); - mapping(address => mapping(bytes32 => bool)) public consumed; + mapping(address => mapping(bytes32 => bool)) public consumed; - function invalidate(bytes32 hash) external { - consumed[msg.sender][hash] = true; - emit HashInvalidated(hash); - } + function invalidate(bytes32 hash) external { + consumed[msg.sender][hash] = true; + emit HashInvalidated(hash); + } } diff --git a/contracts/signature/IERC1271.sol b/contracts/signature/IERC1271.sol index 90e1927b..214a71a7 100644 --- a/contracts/signature/IERC1271.sol +++ b/contracts/signature/IERC1271.sol @@ -3,17 +3,17 @@ pragma solidity >=0.7.0 <0.9.0; interface IERC1271 { - /** - * @notice EIP1271 method to validate a signature. - * @param hash Hash of the data signed on the behalf of address(this). - * @param signature Signature byte array associated with _data. - * - * MUST return the bytes4 magic value 0x1626ba7e when function passes. - * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) - * MUST allow external calls - */ - function isValidSignature( - bytes32 hash, - bytes memory signature - ) external view returns (bytes4); + /** + * @notice EIP1271 method to validate a signature. + * @param hash Hash of the data signed on the behalf of address(this). + * @param signature Signature byte array associated with _data. + * + * MUST return the bytes4 magic value 0x1626ba7e when function passes. + * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) + * MUST allow external calls + */ + function isValidSignature( + bytes32 hash, + bytes memory signature + ) external view returns (bytes4); } diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index 21d1d145..fba4ccc5 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -6,148 +6,148 @@ import "./IERC1271.sol"; /// @title SignatureChecker - A contract that retrieves and validates signatures appended to transaction calldata. /// @dev currently supports eip-712 and eip-1271 signatures abstract contract SignatureChecker { - /** - * @notice Searches for a signature, validates it, and returns the signer's address. - * @dev When signature not found or invalid, zero address is returned - * @return The address of the signer. - */ - function moduleTxSignedBy() internal view returns (bytes32, address) { - bytes calldata data = msg.data; - - /* - * The idea is to extend `onlyModule` and provide signature checking - * without code changes to inheriting contracts (Modifiers). - * - * Since it's a generic mechanism, there is no way to conclusively - * identify the trailing bytes as a signature. We simply slice those - * and recover signer. - * - * As a result, we impose a minimum calldata length equal to a function - * selector plus salt, plus a signature (i.e., 4 + 32 + 65 bytes), any - * shorter and calldata it guaranteed to not contain a signature. - */ - if (data.length < 4 + 32 + 65) { - return (bytes32(0), address(0)); - } - - (uint8 v, bytes32 r, bytes32 s) = _splitSignature(data); + /** + * @notice Searches for a signature, validates it, and returns the signer's address. + * @dev When signature not found or invalid, zero address is returned + * @return The address of the signer. + */ + function moduleTxSignedBy() internal view returns (bytes32, address) { + bytes calldata data = msg.data; - uint256 end = data.length - (32 + 65); - bytes32 salt = bytes32(data[end:]); + /* + * The idea is to extend `onlyModule` and provide signature checking + * without code changes to inheriting contracts (Modifiers). + * + * Since it's a generic mechanism, there is no way to conclusively + * identify the trailing bytes as a signature. We simply slice those + * and recover signer. + * + * As a result, we impose a minimum calldata length equal to a function + * selector plus salt, plus a signature (i.e., 4 + 32 + 65 bytes), any + * shorter and calldata it guaranteed to not contain a signature. + */ + if (data.length < 4 + 32 + 65) { + return (bytes32(0), address(0)); + } - /* - * When handling contract signatures: - * v - is zero - * r - contains the signer - * s - contains the offset within calldata where the signer specific - * signature is located - * - * We detect contract signatures by checking: - * 1- `v` is zero - * 2- `s` points within the buffer, is after selector, is before - * salt and delimits a non-zero length buffer - */ - if (v == 0) { - uint256 start = uint256(s); - if (start < 4 || start > end) { - return (bytes32(0), address(0)); - } - address signer = address(uint160(uint256(r))); + (uint8 v, bytes32 r, bytes32 s) = _splitSignature(data); - bytes32 hash = moduleTxHash(data[:start], salt); - return - _isValidContractSignature(signer, hash, data[start:end]) - ? (hash, signer) - : (bytes32(0), address(0)); - } else { - bytes32 hash = moduleTxHash(data[:end], salt); - return (hash, ecrecover(hash, v, r, s)); - } - } + uint256 end = data.length - (32 + 65); + bytes32 salt = bytes32(data[end:]); - /** - * @notice Hashes the transaction EIP-712 data structure. - * @dev The produced hash is intended to be signed. - * @param data The current transaction's calldata. - * @param salt The salt value. - * @return The 32-byte hash that is to be signed. + /* + * When handling contract signatures: + * v - is zero + * r - contains the signer + * s - contains the offset within calldata where the signer specific + * signature is located + * + * We detect contract signatures by checking: + * 1- `v` is zero + * 2- `s` points within the buffer, is after selector, is before + * salt and delimits a non-zero length buffer */ - function moduleTxHash( - bytes calldata data, - bytes32 salt - ) public view returns (bytes32) { - bytes32 domainSeparator = keccak256( - abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) - ); - bytes memory moduleTxData = abi.encodePacked( - bytes1(0x19), - bytes1(0x01), - domainSeparator, - keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), salt)) - ); - return keccak256(moduleTxData); - } + if (v == 0) { + uint256 start = uint256(s); + if (start < 4 || start > end) { + return (bytes32(0), address(0)); + } + address signer = address(uint160(uint256(r))); - /** - * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`. - * @param data The current transaction's calldata. - * @return v The ECDSA v value - * @return r The ECDSA r value - * @return s The ECDSA s value - */ - function _splitSignature( - bytes calldata data - ) private pure returns (uint8 v, bytes32 r, bytes32 s) { - v = uint8(bytes1(data[data.length - 1:])); - r = bytes32(data[data.length - 65:]); - s = bytes32(data[data.length - 33:]); + bytes32 hash = moduleTxHash(data[:start], salt); + return + _isValidContractSignature(signer, hash, data[start:end]) + ? (hash, signer) + : (bytes32(0), address(0)); + } else { + bytes32 hash = moduleTxHash(data[:end], salt); + return (hash, ecrecover(hash, v, r, s)); } + } - /** - * @dev Calls the signer contract, and validates the contract signature. - * @param signer The address of the signer contract. - * @param hash Hash of the data signed - * @param signature The contract signature. - * @return result Indicates whether the signature is valid. - */ - function _isValidContractSignature( - address signer, - bytes32 hash, - bytes calldata signature - ) internal view returns (bool result) { - uint256 size; - assembly { - size := extcodesize(signer) - } - if (size == 0) { - return false; - } + /** + * @notice Hashes the transaction EIP-712 data structure. + * @dev The produced hash is intended to be signed. + * @param data The current transaction's calldata. + * @param salt The salt value. + * @return The 32-byte hash that is to be signed. + */ + function moduleTxHash( + bytes calldata data, + bytes32 salt + ) public view returns (bytes32) { + bytes32 domainSeparator = keccak256( + abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) + ); + bytes memory moduleTxData = abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + domainSeparator, + keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), salt)) + ); + return keccak256(moduleTxData); + } - (, bytes memory returnData) = signer.staticcall( - abi.encodeWithSelector( - IERC1271.isValidSignature.selector, - hash, - signature - ) - ); + /** + * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`. + * @param data The current transaction's calldata. + * @return v The ECDSA v value + * @return r The ECDSA r value + * @return s The ECDSA s value + */ + function _splitSignature( + bytes calldata data + ) private pure returns (uint8 v, bytes32 r, bytes32 s) { + v = uint8(bytes1(data[data.length - 1:])); + r = bytes32(data[data.length - 65:]); + s = bytes32(data[data.length - 33:]); + } - return bytes4(returnData) == EIP1271_MAGIC_VALUE; + /** + * @dev Calls the signer contract, and validates the contract signature. + * @param signer The address of the signer contract. + * @param hash Hash of the data signed + * @param signature The contract signature. + * @return result Indicates whether the signature is valid. + */ + function _isValidContractSignature( + address signer, + bytes32 hash, + bytes calldata signature + ) internal view returns (bool result) { + uint256 size; + assembly { + size := extcodesize(signer) } + if (size == 0) { + return false; + } + + (, bytes memory returnData) = signer.staticcall( + abi.encodeWithSelector( + IERC1271.isValidSignature.selector, + hash, + signature + ) + ); + + return bytes4(returnData) == EIP1271_MAGIC_VALUE; + } - // keccak256( - // "EIP712Domain(uint256 chainId,address verifyingContract)" - // ); - bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = - 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; + // keccak256( + // "EIP712Domain(uint256 chainId,address verifyingContract)" + // ); + bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = + 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; - // keccak256( - // "ModuleTx(bytes data,bytes32 salt)" - // ); - bytes32 private constant MODULE_TX_TYPEHASH = - 0x2939aeeda3ca260200c9f7b436b19e13207547ccc65cfedc857751c5ea6d91d4; + // keccak256( + // "ModuleTx(bytes data,bytes32 salt)" + // ); + bytes32 private constant MODULE_TX_TYPEHASH = + 0x2939aeeda3ca260200c9f7b436b19e13207547ccc65cfedc857751c5ea6d91d4; - // bytes4(keccak256( - // "isValidSignature(bytes32,bytes)" - // )); - bytes4 private constant EIP1271_MAGIC_VALUE = 0x1626ba7e; + // bytes4(keccak256( + // "isValidSignature(bytes32,bytes)" + // )); + bytes4 private constant EIP1271_MAGIC_VALUE = 0x1626ba7e; } diff --git a/contracts/test/TestAvatar.sol b/contracts/test/TestAvatar.sol index a3399efd..c2fb3713 100644 --- a/contracts/test/TestAvatar.sol +++ b/contracts/test/TestAvatar.sol @@ -2,63 +2,63 @@ pragma solidity >=0.8.0; contract Enum { - enum Operation { - Call, - DelegateCall - } + enum Operation { + Call, + DelegateCall + } } contract TestAvatar { - address public module; + address public module; - receive() external payable {} + receive() external payable {} - function enableModule(address _module) external { - module = _module; - } + function enableModule(address _module) external { + module = _module; + } - function disableModule(address, address) external { - module = address(0); - } + function disableModule(address, address) external { + module = address(0); + } - function isModuleEnabled(address _module) external view returns (bool) { - if (module == _module) { - return true; - } else { - return false; - } + function isModuleEnabled(address _module) external view returns (bool) { + if (module == _module) { + return true; + } else { + return false; } + } - function execTransactionFromModule( - address payable to, - uint256 value, - bytes calldata data, - uint8 operation - ) external returns (bool success) { - require(msg.sender == module, "Not authorized"); - if (operation == 1) (success, ) = to.delegatecall(data); - else (success, ) = to.call{value: value}(data); - } + function execTransactionFromModule( + address payable to, + uint256 value, + bytes calldata data, + uint8 operation + ) external returns (bool success) { + require(msg.sender == module, "Not authorized"); + if (operation == 1) (success, ) = to.delegatecall(data); + else (success, ) = to.call{value: value}(data); + } - function execTransactionFromModuleReturnData( - address payable to, - uint256 value, - bytes calldata data, - uint8 operation - ) external returns (bool success, bytes memory returnData) { - require(msg.sender == module, "Not authorized"); - if (operation == 1) (success, ) = to.delegatecall(data); - else (success, returnData) = to.call{value: value}(data); - } + function execTransactionFromModuleReturnData( + address payable to, + uint256 value, + bytes calldata data, + uint8 operation + ) external returns (bool success, bytes memory returnData) { + require(msg.sender == module, "Not authorized"); + if (operation == 1) (success, ) = to.delegatecall(data); + else (success, returnData) = to.call{value: value}(data); + } - function getModulesPaginated( - address, - uint256 pageSize - ) external view returns (address[] memory array, address next) { - // Init array with max page size - array = new address[](pageSize); + function getModulesPaginated( + address, + uint256 pageSize + ) external view returns (address[] memory array, address next) { + // Init array with max page size + array = new address[](pageSize); - array[0] = module; - next = module; - } + array[0] = module; + next = module; + } } diff --git a/contracts/test/TestGuard.sol b/contracts/test/TestGuard.sol index 72bb06b1..cc967626 100644 --- a/contracts/test/TestGuard.sol +++ b/contracts/test/TestGuard.sol @@ -4,72 +4,72 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/GuardableModule.sol"; contract TestGuard is FactoryFriendly, BaseGuard { - event PreChecked(address sender); - event PostChecked(bool checked); + event PreChecked(address sender); + event PostChecked(bool checked); - address public module; + address public module; - constructor(address _module) { - bytes memory initParams = abi.encode(_module); - setUp(initParams); - } + constructor(address _module) { + bytes memory initParams = abi.encode(_module); + setUp(initParams); + } - function setModule(address _module) public { - module = _module; - } + function setModule(address _module) public { + module = _module; + } - function checkTransaction( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation, - uint256, - uint256, - uint256, - address, - address payable, - bytes memory, - address sender - ) public override { - require(to != address(0), "Cannot send to zero address"); - require(value != 1337, "Cannot send 1337"); - require(bytes3(data) != bytes3(0xbaddad), "Cannot call 0xbaddad"); - require(operation != Enum.Operation(1), "No delegate calls"); - emit PreChecked(sender); - } + function checkTransaction( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation, + uint256, + uint256, + uint256, + address, + address payable, + bytes memory, + address sender + ) public override { + require(to != address(0), "Cannot send to zero address"); + require(value != 1337, "Cannot send 1337"); + require(bytes3(data) != bytes3(0xbaddad), "Cannot call 0xbaddad"); + require(operation != Enum.Operation(1), "No delegate calls"); + emit PreChecked(sender); + } - function checkAfterExecution(bytes32, bool) public override { - require( - GuardableModule(module).guard() == address(this), - "Module cannot remove its own guard." - ); - emit PostChecked(true); - } + function checkAfterExecution(bytes32, bool) public override { + require( + GuardableModule(module).guard() == address(this), + "Module cannot remove its own guard." + ); + emit PostChecked(true); + } - function setUp(bytes memory initializeParams) public override initializer { - address _module = abi.decode(initializeParams, (address)); - module = _module; - } + function setUp(bytes memory initializeParams) public override initializer { + address _module = abi.decode(initializeParams, (address)); + module = _module; + } } contract TestNonCompliantGuard is IERC165 { - function supportsInterface(bytes4) external pure returns (bool) { - return false; - } + function supportsInterface(bytes4) external pure returns (bool) { + return false; + } - function checkTransaction( - address, - uint256, - bytes memory, - Enum.Operation, - uint256, - uint256, - uint256, - address, - address, - bytes memory, - address - ) public {} + function checkTransaction( + address, + uint256, + bytes memory, + Enum.Operation, + uint256, + uint256, + uint256, + address, + address, + bytes memory, + address + ) public {} - function checkAfterExecution(bytes32, bool) public {} + function checkAfterExecution(bytes32, bool) public {} } diff --git a/contracts/test/TestGuardableModifier.sol b/contracts/test/TestGuardableModifier.sol index 4b2e02c2..92c257e9 100644 --- a/contracts/test/TestGuardableModifier.sol +++ b/contracts/test/TestGuardableModifier.sol @@ -4,84 +4,79 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/GuardableModifier.sol"; contract TestGuardableModifier is GuardableModifier { - event Executed( - address to, - uint256 value, - bytes data, - Enum.Operation operation, - bool success - ); + event Executed( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bool success + ); - event ExecutedAndReturnedData( - address to, - uint256 value, - bytes data, - Enum.Operation operation, - bytes returnData, - bool success - ); + event ExecutedAndReturnedData( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bytes returnData, + bool success + ); - constructor(address _avatar, address _target) { - bytes memory initParams = abi.encode(_avatar, _target); - setUp(initParams); - } + constructor(address _avatar, address _target) { + bytes memory initParams = abi.encode(_avatar, _target); + setUp(initParams); + } - /// @dev Passes a transaction to the modifier. - /// @param to Destination address of module transaction - /// @param value Ether value of module transaction - /// @param data Data payload of module transaction - /// @param operation Operation type of module transaction - /// @notice Can only be called by enabled modules - function execTransactionFromModule( - address to, - uint256 value, - bytes calldata data, - Enum.Operation operation - ) public override moduleOnly returns (bool success) { - success = exec(to, value, data, operation); - emit Executed(to, value, data, operation, success); - } + /// @dev Passes a transaction to the modifier. + /// @param to Destination address of module transaction + /// @param value Ether value of module transaction + /// @param data Data payload of module transaction + /// @param operation Operation type of module transaction + /// @notice Can only be called by enabled modules + function execTransactionFromModule( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public override moduleOnly returns (bool success) { + success = exec(to, value, data, operation); + emit Executed(to, value, data, operation, success); + } - /// @dev Passes a transaction to the modifier, expects return data. - /// @param to Destination address of module transaction - /// @param value Ether value of module transaction - /// @param data Data payload of module transaction - /// @param operation Operation type of module transaction - /// @notice Can only be called by enabled modules - function execTransactionFromModuleReturnData( - address to, - uint256 value, - bytes calldata data, - Enum.Operation operation - ) - public - override - moduleOnly - returns (bool success, bytes memory returnData) - { - (success, returnData) = execAndReturnData(to, value, data, operation); - emit ExecutedAndReturnedData( - to, - value, - data, - operation, - returnData, - success - ); - } + /// @dev Passes a transaction to the modifier, expects return data. + /// @param to Destination address of module transaction + /// @param value Ether value of module transaction + /// @param data Data payload of module transaction + /// @param operation Operation type of module transaction + /// @notice Can only be called by enabled modules + function execTransactionFromModuleReturnData( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public override moduleOnly returns (bool success, bytes memory returnData) { + (success, returnData) = execAndReturnData(to, value, data, operation); + emit ExecutedAndReturnedData( + to, + value, + data, + operation, + returnData, + success + ); + } - function setUp(bytes memory initializeParams) public override initializer { - setupModules(); - __Ownable_init(msg.sender); - (address _avatar, address _target) = abi.decode( - initializeParams, - (address, address) - ); - avatar = _avatar; - target = _target; - } + function setUp(bytes memory initializeParams) public override initializer { + setupModules(); + __Ownable_init(msg.sender); + (address _avatar, address _target) = abi.decode( + initializeParams, + (address, address) + ); + avatar = _avatar; + target = _target; + } - function attemptToSetupModules() public { - setupModules(); - } + function attemptToSetupModules() public { + setupModules(); + } } diff --git a/contracts/test/TestModifier.sol b/contracts/test/TestModifier.sol index e2bcc468..adbed17c 100644 --- a/contracts/test/TestModifier.sol +++ b/contracts/test/TestModifier.sol @@ -6,84 +6,79 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/Modifier.sol"; contract TestModifier is Modifier { - event Executed( - address to, - uint256 value, - bytes data, - Enum.Operation operation, - bool success - ); + event Executed( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bool success + ); - event ExecutedAndReturnedData( - address to, - uint256 value, - bytes data, - Enum.Operation operation, - bytes returnData, - bool success - ); + event ExecutedAndReturnedData( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bytes returnData, + bool success + ); - constructor(address _avatar, address _target) { - bytes memory initParams = abi.encode(_avatar, _target); - setUp(initParams); - } + constructor(address _avatar, address _target) { + bytes memory initParams = abi.encode(_avatar, _target); + setUp(initParams); + } - /// @dev Passes a transaction to the modifier. - /// @param to Destination address of module transaction - /// @param value Ether value of module transaction - /// @param data Data payload of module transaction - /// @param operation Operation type of module transaction - /// @notice Can only be called by enabled modules - function execTransactionFromModule( - address to, - uint256 value, - bytes calldata data, - Enum.Operation operation - ) public override moduleOnly returns (bool success) { - success = exec(to, value, data, operation); - emit Executed(to, value, data, operation, success); - } + /// @dev Passes a transaction to the modifier. + /// @param to Destination address of module transaction + /// @param value Ether value of module transaction + /// @param data Data payload of module transaction + /// @param operation Operation type of module transaction + /// @notice Can only be called by enabled modules + function execTransactionFromModule( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public override moduleOnly returns (bool success) { + success = exec(to, value, data, operation); + emit Executed(to, value, data, operation, success); + } - /// @dev Passes a transaction to the modifier, expects return data. - /// @param to Destination address of module transaction - /// @param value Ether value of module transaction - /// @param data Data payload of module transaction - /// @param operation Operation type of module transaction - /// @notice Can only be called by enabled modules - function execTransactionFromModuleReturnData( - address to, - uint256 value, - bytes calldata data, - Enum.Operation operation - ) - public - override - moduleOnly - returns (bool success, bytes memory returnData) - { - (success, returnData) = execAndReturnData(to, value, data, operation); - emit ExecutedAndReturnedData( - to, - value, - data, - operation, - returnData, - success - ); - } + /// @dev Passes a transaction to the modifier, expects return data. + /// @param to Destination address of module transaction + /// @param value Ether value of module transaction + /// @param data Data payload of module transaction + /// @param operation Operation type of module transaction + /// @notice Can only be called by enabled modules + function execTransactionFromModuleReturnData( + address to, + uint256 value, + bytes calldata data, + Enum.Operation operation + ) public override moduleOnly returns (bool success, bytes memory returnData) { + (success, returnData) = execAndReturnData(to, value, data, operation); + emit ExecutedAndReturnedData( + to, + value, + data, + operation, + returnData, + success + ); + } - function setUp(bytes memory initializeParams) public override initializer { - (address _avatar, address _target) = abi.decode( - initializeParams, - (address, address) - ); - setupModules(); - _transferOwnership(msg.sender); - avatar = _avatar; - target = _target; - } + function setUp(bytes memory initializeParams) public override initializer { + (address _avatar, address _target) = abi.decode( + initializeParams, + (address, address) + ); + setupModules(); + _transferOwnership(msg.sender); + avatar = _avatar; + target = _target; + } - function attemptToSetupModules() public { - setupModules(); - } + function attemptToSetupModules() public { + setupModules(); + } } diff --git a/contracts/test/TestModule.sol b/contracts/test/TestModule.sol index 5e6d2ce4..0bb46c09 100644 --- a/contracts/test/TestModule.sol +++ b/contracts/test/TestModule.sol @@ -6,61 +6,61 @@ pragma solidity >=0.7.0 <0.9.0; import "../core/GuardableModule.sol"; contract TestModule is GuardableModule { - constructor(address _avatar, address _target) { - bytes memory initParams = abi.encode(_avatar, _target); - setUp(initParams); - } + constructor(address _avatar, address _target) { + bytes memory initParams = abi.encode(_avatar, _target); + setUp(initParams); + } - event executed( - address to, - uint256 value, - bytes data, - Enum.Operation operation, - bool success - ); - event executedAndReturnedData( - address to, - uint256 value, - bytes data, - Enum.Operation operation, - bytes returnData, - bool success - ); + event executed( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bool success + ); + event executedAndReturnedData( + address to, + uint256 value, + bytes data, + Enum.Operation operation, + bytes returnData, + bool success + ); - function executeTransaction( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) public returns (bool success) { - success = exec(to, value, data, operation); - emit executed(to, value, data, operation, success); - } + function executeTransaction( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) public returns (bool success) { + success = exec(to, value, data, operation); + emit executed(to, value, data, operation, success); + } - function executeTransactionReturnData( - address to, - uint256 value, - bytes memory data, - Enum.Operation operation - ) public returns (bool success, bytes memory returnData) { - (success, returnData) = execAndReturnData(to, value, data, operation); - emit executedAndReturnedData( - to, - value, - data, - operation, - returnData, - success - ); - } + function executeTransactionReturnData( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) public returns (bool success, bytes memory returnData) { + (success, returnData) = execAndReturnData(to, value, data, operation); + emit executedAndReturnedData( + to, + value, + data, + operation, + returnData, + success + ); + } - function setUp(bytes memory initializeParams) public override initializer { - __Ownable_init(msg.sender); - (address _avatar, address _target) = abi.decode( - initializeParams, - (address, address) - ); - avatar = _avatar; - target = _target; - } + function setUp(bytes memory initializeParams) public override initializer { + __Ownable_init(msg.sender); + (address _avatar, address _target) = abi.decode( + initializeParams, + (address, address) + ); + avatar = _avatar; + target = _target; + } } diff --git a/contracts/test/TestSignature.sol b/contracts/test/TestSignature.sol index 1614cc26..c7be472f 100644 --- a/contracts/test/TestSignature.sol +++ b/contracts/test/TestSignature.sol @@ -4,68 +4,68 @@ pragma solidity >=0.8.0; import "../signature/SignatureChecker.sol"; contract ContractSignerYes is IERC1271 { - function isValidSignature( - bytes32, - bytes memory - ) external pure override returns (bytes4) { - return 0x1626ba7e; - } + function isValidSignature( + bytes32, + bytes memory + ) external pure override returns (bytes4) { + return 0x1626ba7e; + } } contract ContractSignerNo is IERC1271 { - function isValidSignature( - bytes32, - bytes memory - ) external pure override returns (bytes4) { - return 0x33333333; - } + function isValidSignature( + bytes32, + bytes memory + ) external pure override returns (bytes4) { + return 0x33333333; + } } contract ContractSignerMaybe is IERC1271 { - function isValidSignature( - bytes32, - bytes memory contractSpecificSignature - ) external pure override returns (bytes4) { - bool isValid = contractSpecificSignature.length == 6 && - bytes6(contractSpecificSignature) == 0x001122334455; + function isValidSignature( + bytes32, + bytes memory contractSpecificSignature + ) external pure override returns (bytes4) { + bool isValid = contractSpecificSignature.length == 6 && + bytes6(contractSpecificSignature) == 0x001122334455; - return isValid ? bytes4(0x1626ba7e) : bytes4(0x33333333); - } + return isValid ? bytes4(0x1626ba7e) : bytes4(0x33333333); + } } contract ContractSignerOnlyEmpty is IERC1271 { - function isValidSignature( - bytes32, - bytes memory contractSpecificSignature - ) external pure override returns (bytes4) { - bool isValid = contractSpecificSignature.length == 0; - return isValid ? bytes4(0x1626ba7e) : bytes4(0x33333333); - } + function isValidSignature( + bytes32, + bytes memory contractSpecificSignature + ) external pure override returns (bytes4) { + bool isValid = contractSpecificSignature.length == 0; + return isValid ? bytes4(0x1626ba7e) : bytes4(0x33333333); + } } contract ContractSignerFaulty {} contract ContractSignerReturnSize { - function isValidSignature( - bytes32, - bytes memory - ) external pure returns (bytes2) { - return 0x1626; - } + function isValidSignature( + bytes32, + bytes memory + ) external pure returns (bytes2) { + return 0x1626; + } } contract TestSignature is SignatureChecker { - event Hello(address signer); + event Hello(address signer); - event Goodbye(address signer); + event Goodbye(address signer); - function hello() public { - (, address signer) = moduleTxSignedBy(); - emit Hello(signer); - } + function hello() public { + (, address signer) = moduleTxSignedBy(); + emit Hello(signer); + } - function goodbye(uint256, bytes memory) public { - (, address signer) = moduleTxSignedBy(); - emit Goodbye(signer); - } + function goodbye(uint256, bytes memory) public { + (, address signer) = moduleTxSignedBy(); + emit Goodbye(signer); + } } From 10b7701cb3ff731356f5e792f81fb3c3e58b1ecb Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 15:00:52 +0100 Subject: [PATCH 53/82] Fix lint:ts --- .eslintrc.js | 16 +++++++++++++++- hardhat.config.ts | 3 ++- sdk/contracts.ts | 3 --- sdk/factory/__tests__/index.spec.ts | 3 +-- sdk/factory/deployModuleFactory.ts | 10 ++++++++-- sdk/factory/mastercopyDeployer.ts | 1 + sdk/factory/moduleDeployer.ts | 4 +++- tasks/deploy-replay.ts | 1 + tasks/singleton-deployment.ts | 1 + test/01_IAvatar.spec.ts | 2 +- test/03_Modifier.spec.ts | 12 ++++++------ test/04_Guard.spec.ts | 4 ++-- test/05_ModuleProxyFactory.spec.ts | 1 + test/06_SignatureChecker.spec.ts | 13 +++++++------ test/07_GuardableModifier.spec.ts | 11 ++++++----- 15 files changed, 55 insertions(+), 30 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index a44e353e..b51b99cc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,13 +33,27 @@ module.exports = { "import/order": [ "error", { - groups: [["builtin", "external"]], + groups: [ + "builtin", + "external", + "internal", + "parent", + "sibling", + "index", + "object", + "type", + ], alphabetize: { order: "asc", }, + "newlines-between": "always", }, ], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { ignoreRestSiblings: true }, + ], }, }; diff --git a/hardhat.config.ts b/hardhat.config.ts index 53497ee1..c682e9ff 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,8 +1,9 @@ import "@nomicfoundation/hardhat-toolbox"; import dotenv from "dotenv"; -import type { HttpNetworkUserConfig } from "hardhat/types"; import yargs from "yargs"; + +import type { HttpNetworkUserConfig } from "hardhat/types"; import "hardhat-change-network"; const { network } = yargs diff --git a/sdk/contracts.ts b/sdk/contracts.ts index 53a44019..c6f97200 100644 --- a/sdk/contracts.ts +++ b/sdk/contracts.ts @@ -18,9 +18,7 @@ import RealityEthAbi from "./abi/RealityEth.json"; import RolesAbi from "./abi/Roles.json"; import ScopeGuardAbi from "./abi/ScopeGuard.json"; import TellorAbi from "./abi/Tellor.json"; - import { KnownContracts } from "./factory/types"; - import * as BridgeInitData from "./initData/Bridge"; import * as CirculatingSupplyErc20InitData from "./initData/CirculatingSupplyErc20"; import * as CirculatingSupplyErc721InitData from "./initData/CirculatingSupplyErc721"; @@ -38,7 +36,6 @@ import * as RealityErc20InitData from "./initData/RealityErc20"; import * as RealityEthInitData from "./initData/RealityEth"; import * as RolesInitData from "./initData/Roles"; import * as ScopeGuardInitData from "./initData/ScopeGuard"; - import { factories } from "./types"; export enum SupportedNetworks { diff --git a/sdk/factory/__tests__/index.spec.ts b/sdk/factory/__tests__/index.spec.ts index 258f1757..f04ba243 100644 --- a/sdk/factory/__tests__/index.spec.ts +++ b/sdk/factory/__tests__/index.spec.ts @@ -14,7 +14,6 @@ import { getModuleInstance, getModuleFactoryAndMasterCopy, } from "../moduleDeployer"; - import { KnownContracts } from "../types"; const AddressOne = "0x0000000000000000000000000000000000000001"; @@ -31,7 +30,7 @@ describe("Factory JS functions ", () => { } it("should execute transaction and retrieve expected address ", async () => { - const { mock, chainId } = await loadFixture(setup); + const { chainId } = await loadFixture(setup); const [signer] = await hre.ethers.getSigners(); diff --git a/sdk/factory/deployModuleFactory.ts b/sdk/factory/deployModuleFactory.ts index be2b0f99..df495a80 100644 --- a/sdk/factory/deployModuleFactory.ts +++ b/sdk/factory/deployModuleFactory.ts @@ -1,11 +1,17 @@ +import assert from "assert"; + import { constants as ethersConstants, ethers } from "ethers"; + +import { MasterCopyInitData } from "../contracts"; + import { getSingletonFactory } from "./singletonFactory"; import { KnownContracts } from "./types"; -import { MasterCopyInitData } from "../contracts"; const { AddressZero } = ethersConstants; -const FactoryInitData = MasterCopyInitData[KnownContracts.FACTORY]!; +const FactoryInitData = MasterCopyInitData[KnownContracts.FACTORY]; + +assert(FactoryInitData); /** * Deploy the Module Proxy Factory via the singleton factory. diff --git a/sdk/factory/mastercopyDeployer.ts b/sdk/factory/mastercopyDeployer.ts index 7f5dacae..2516f8fc 100644 --- a/sdk/factory/mastercopyDeployer.ts +++ b/sdk/factory/mastercopyDeployer.ts @@ -5,6 +5,7 @@ import { ethers, } from "ethers"; import { keccak256, getCreate2Address, getAddress } from "ethers/lib/utils"; + import { getSingletonFactory } from "./singletonFactory"; const { AddressZero } = ethersConstants; diff --git a/sdk/factory/moduleDeployer.ts b/sdk/factory/moduleDeployer.ts index 9f055f06..95fe4bf2 100644 --- a/sdk/factory/moduleDeployer.ts +++ b/sdk/factory/moduleDeployer.ts @@ -1,6 +1,6 @@ import { Provider } from "@ethersproject/providers"; import { ethers, Contract, Signer, BigNumber } from "ethers"; -import { KnownContracts } from "./types"; + import { ContractAddresses, ContractAbis, @@ -9,6 +9,8 @@ import { } from "../contracts"; import { ModuleProxyFactory__factory } from "../types"; +import { KnownContracts } from "./types"; + type ABI = any[] | readonly any[]; type TxAndExpectedAddress = { diff --git a/tasks/deploy-replay.ts b/tasks/deploy-replay.ts index b9a34073..772026fe 100644 --- a/tasks/deploy-replay.ts +++ b/tasks/deploy-replay.ts @@ -1,5 +1,6 @@ import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; + import { KnownContracts, MasterCopyInitData, diff --git a/tasks/singleton-deployment.ts b/tasks/singleton-deployment.ts index 3c25ed9e..5e28fde0 100644 --- a/tasks/singleton-deployment.ts +++ b/tasks/singleton-deployment.ts @@ -1,5 +1,6 @@ import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; + import { KnownContracts, MasterCopyInitData } from "../sdk/factory"; import { deployModuleFactory } from "../sdk/factory/deployModuleFactory"; diff --git a/test/01_IAvatar.spec.ts b/test/01_IAvatar.spec.ts index 8fae82e6..ab9134d8 100644 --- a/test/01_IAvatar.spec.ts +++ b/test/01_IAvatar.spec.ts @@ -1,8 +1,8 @@ import { AddressZero } from "@ethersproject/constants"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; - import { expect } from "chai"; import hre from "hardhat"; + import { TestAvatar__factory } from "../typechain-types"; describe("IAvatar", async () => { diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 30563533..259595cb 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -1,15 +1,15 @@ -import hre from "hardhat"; -import { expect } from "chai"; -import { PopulatedTransaction } from "ethers"; - import { AddressZero } from "@ethersproject/constants"; import { AddressOne } from "@gnosis.pm/safe-contracts"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { PopulatedTransaction } from "ethers"; +import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; +import hre from "hardhat"; -import typedDataForTransaction from "./typedDataForTransaction"; import { TestAvatar__factory, TestModifier__factory } from "../typechain-types"; -import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; + +import typedDataForTransaction from "./typedDataForTransaction"; describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; diff --git a/test/04_Guard.spec.ts b/test/04_Guard.spec.ts index 2914ddb2..4cee01ec 100644 --- a/test/04_Guard.spec.ts +++ b/test/04_Guard.spec.ts @@ -1,8 +1,8 @@ +import { AddressZero } from "@ethersproject/constants"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import hre from "hardhat"; -import { AddressZero } from "@ethersproject/constants"; -import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { TestGuard__factory, TestModule__factory } from "../typechain-types"; async function setupTests() { diff --git a/test/05_ModuleProxyFactory.spec.ts b/test/05_ModuleProxyFactory.spec.ts index 7f0951c0..c6386cbb 100644 --- a/test/05_ModuleProxyFactory.spec.ts +++ b/test/05_ModuleProxyFactory.spec.ts @@ -3,6 +3,7 @@ import { AddressOne } from "@gnosis.pm/safe-contracts"; import { expect } from "chai"; import { Contract } from "ethers"; import { ethers } from "hardhat"; + import { calculateProxyAddress } from "../sdk/factory"; describe("ModuleProxyFactory", async () => { diff --git a/test/06_SignatureChecker.spec.ts b/test/06_SignatureChecker.spec.ts index 3c0f26cf..c93b8ee8 100644 --- a/test/06_SignatureChecker.spec.ts +++ b/test/06_SignatureChecker.spec.ts @@ -1,17 +1,18 @@ -import hre from "hardhat"; -import { TestSignature__factory } from "../typechain-types"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; -import { PopulatedTransaction } from "ethers"; -import { expect } from "chai"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; - -import typedDataForTransaction from "./typedDataForTransaction"; +import { expect } from "chai"; +import { PopulatedTransaction } from "ethers"; import { defaultAbiCoder, keccak256, solidityPack, toUtf8Bytes, } from "ethers/lib/utils"; +import hre from "hardhat"; + +import { TestSignature__factory } from "../typechain-types"; + +import typedDataForTransaction from "./typedDataForTransaction"; describe("SignatureChecker", async () => { async function setup() { diff --git a/test/07_GuardableModifier.spec.ts b/test/07_GuardableModifier.spec.ts index 801ed16e..a9a853a4 100644 --- a/test/07_GuardableModifier.spec.ts +++ b/test/07_GuardableModifier.spec.ts @@ -1,16 +1,17 @@ -import hre from "hardhat"; -import { expect } from "chai"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { PopulatedTransaction } from "ethers"; +import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; +import hre from "hardhat"; import { TestAvatar__factory, TestGuard__factory, TestGuardableModifier__factory, } from "../typechain-types"; + import typedDataForTransaction from "./typedDataForTransaction"; -import { PopulatedTransaction } from "ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; describe("GuardableModifier", async () => { async function setupTests() { From 5165ce2f377c291d4bfe71d21948d9df0fdf6224 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 15:31:08 +0100 Subject: [PATCH 54/82] Fix lint:sol --- .solhint.json | 29 ++++++++++++------------ .solhintignore | 1 + contracts/core/GuardableModifier.sol | 9 ++++++-- contracts/core/GuardableModule.sol | 7 ++++-- contracts/core/Modifier.sol | 9 ++++---- contracts/core/Module.sol | 6 +++-- contracts/factory/FactoryFriendly.sol | 2 +- contracts/guard/BaseGuard.sol | 7 +++--- contracts/guard/Guardable.sol | 7 +++--- contracts/interfaces/IAvatar.sol | 2 +- contracts/interfaces/IGuard.sol | 2 +- contracts/signature/SignatureChecker.sol | 3 ++- contracts/test/Imports.sol | 6 ----- contracts/test/TestGuard.sol | 9 +++++++- 14 files changed, 58 insertions(+), 41 deletions(-) create mode 100644 .solhintignore delete mode 100644 contracts/test/Imports.sol diff --git a/.solhint.json b/.solhint.json index 1ac53412..f4eeab0e 100644 --- a/.solhint.json +++ b/.solhint.json @@ -1,16 +1,17 @@ { - "extends": "solhint:recommended", - "rules": { - "compiler-version": "off", - "func-visibility": [ - "warn", - { - "ignoreConstructors": true - } - ], - "not-rely-on-time": "off", - "reason-string": "off", - "no-empty-blocks": "off", - "avoid-low-level-calls": "off" - } + "extends": "solhint:recommended", + "rules": { + "compiler-version": "off", + "func-visibility": [ + "warn", + { + "ignoreConstructors": true + } + ], + "not-rely-on-time": "off", + "reason-string": "off", + "no-empty-blocks": "off", + "avoid-low-level-calls": "off", + "no-inline-assembly": "off" + } } diff --git a/.solhintignore b/.solhintignore new file mode 100644 index 00000000..7ec58e1b --- /dev/null +++ b/.solhintignore @@ -0,0 +1 @@ +./contracts/test \ No newline at end of file diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index e630a241..984c86b3 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -1,8 +1,13 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "../guard/Guardable.sol"; -import "./Modifier.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; + +import {Guardable} from "../guard/Guardable.sol"; +import {IAvatar} from "../interfaces/IAvatar.sol"; +import {IGuard} from "../interfaces/IGuard.sol"; +import {Modifier} from "./Modifier.sol"; +import {Module} from "./Module.sol"; abstract contract GuardableModifier is Module, Guardable, Modifier { /// @dev Passes a transaction to be executed by the avatar. diff --git a/contracts/core/GuardableModule.sol b/contracts/core/GuardableModule.sol index b0691548..39a0e0d2 100644 --- a/contracts/core/GuardableModule.sol +++ b/contracts/core/GuardableModule.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "../guard/Guardable.sol"; -import "./Module.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; +import {IGuard} from "../interfaces/IGuard.sol"; +import {Guardable} from "../guard/Guardable.sol"; +import {Module} from "./Module.sol"; +import {IAvatar} from "../interfaces/IAvatar.sol"; /// @title GuardableModule - A contract that can pass messages to a Module Manager contract if enabled by that contract. abstract contract GuardableModule is Module, Guardable { diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index 7e56aa3d..d44f0ee2 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "../interfaces/IAvatar.sol"; -import "../signature/ExecutionTracker.sol"; -import "../signature/SignatureChecker.sol"; -import "./Module.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; +import {ExecutionTracker} from "../signature/ExecutionTracker.sol"; +import {IAvatar} from "../interfaces/IAvatar.sol"; +import {Module} from "./Module.sol"; +import {SignatureChecker} from "../signature/SignatureChecker.sol"; /// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. abstract contract Modifier is diff --git a/contracts/core/Module.sol b/contracts/core/Module.sol index 831c9ef2..8140aef2 100644 --- a/contracts/core/Module.sol +++ b/contracts/core/Module.sol @@ -1,8 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "../factory/FactoryFriendly.sol"; -import "../interfaces/IAvatar.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; + +import {FactoryFriendly} from "../factory/FactoryFriendly.sol"; +import {IAvatar} from "../interfaces/IAvatar.sol"; /// @title Module Interface - A contract that can pass messages to a Module Manager contract if enabled by that contract. abstract contract Module is FactoryFriendly { diff --git a/contracts/factory/FactoryFriendly.sol b/contracts/factory/FactoryFriendly.sol index 96e6e43a..e996bfc2 100644 --- a/contracts/factory/FactoryFriendly.sol +++ b/contracts/factory/FactoryFriendly.sol @@ -3,7 +3,7 @@ /// @title Zodiac FactoryFriendly - A contract that allows other contracts to be initializable and pass bytes as arguments to define contract state pragma solidity >=0.7.0 <0.9.0; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract FactoryFriendly is OwnableUpgradeable { function setUp(bytes memory initializeParams) public virtual; diff --git a/contracts/guard/BaseGuard.sol b/contracts/guard/BaseGuard.sol index d6d691e7..aef3aadb 100644 --- a/contracts/guard/BaseGuard.sol +++ b/contracts/guard/BaseGuard.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; -import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import "../interfaces/IGuard.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +import {IGuard} from "../interfaces/IGuard.sol"; abstract contract BaseGuard is IERC165 { function supportsInterface( diff --git a/contracts/guard/Guardable.sol b/contracts/guard/Guardable.sol index 71ed9ea2..fe2ba156 100644 --- a/contracts/guard/Guardable.sol +++ b/contracts/guard/Guardable.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "./BaseGuard.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +import {BaseGuard} from "../guard/BaseGuard.sol"; +import {IGuard} from "../interfaces/IGuard.sol"; /// @title Guardable - A contract that manages fallback calls made to this contract contract Guardable is OwnableUpgradeable { diff --git a/contracts/interfaces/IAvatar.sol b/contracts/interfaces/IAvatar.sol index 64bf1ec1..099456cd 100644 --- a/contracts/interfaces/IAvatar.sol +++ b/contracts/interfaces/IAvatar.sol @@ -3,7 +3,7 @@ /// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract. pragma solidity >=0.7.0 <0.9.0; -import "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; interface IAvatar { event EnabledModule(address module); diff --git a/contracts/interfaces/IGuard.sol b/contracts/interfaces/IGuard.sol index f0323f37..008a68b4 100644 --- a/contracts/interfaces/IGuard.sol +++ b/contracts/interfaces/IGuard.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; interface IGuard { function checkTransaction( diff --git a/contracts/signature/SignatureChecker.sol b/contracts/signature/SignatureChecker.sol index fba4ccc5..4a8fc5b3 100644 --- a/contracts/signature/SignatureChecker.sol +++ b/contracts/signature/SignatureChecker.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -import "./IERC1271.sol"; +import {IERC1271} from "./IERC1271.sol"; /// @title SignatureChecker - A contract that retrieves and validates signatures appended to transaction calldata. /// @dev currently supports eip-712 and eip-1271 signatures @@ -116,6 +116,7 @@ abstract contract SignatureChecker { bytes calldata signature ) internal view returns (bool result) { uint256 size; + // eslint-disable-line no-inline-assembly assembly { size := extcodesize(signer) } diff --git a/contracts/test/Imports.sol b/contracts/test/Imports.sol deleted file mode 100644 index ddd872f3..00000000 --- a/contracts/test/Imports.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.6.0 <0.7.0; - -// We import the contract so truffle compiles it, and we have the ABI -// available when working from truffle console. -import "@gnosis.pm/mock-contract/contracts/MockContract.sol"; diff --git a/contracts/test/TestGuard.sol b/contracts/test/TestGuard.sol index cc967626..c0fc46e4 100644 --- a/contracts/test/TestGuard.sol +++ b/contracts/test/TestGuard.sol @@ -1,7 +1,14 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "../core/GuardableModule.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +import {BaseGuard} from "../guard/BaseGuard.sol"; +import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; +import {FactoryFriendly} from "../factory/FactoryFriendly.sol"; +import {GuardableModule} from "../core/GuardableModule.sol"; + +/* solhint-disable */ contract TestGuard is FactoryFriendly, BaseGuard { event PreChecked(address sender); From c169eb76b2a2ebec741a196e0d03bce28dc3722d Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 15:36:29 +0100 Subject: [PATCH 55/82] Bump dependencies --- package.json | 6 +- yarn.lock | 401 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 299 insertions(+), 108 deletions(-) diff --git a/package.json b/package.json index b53d1791..78d895bd 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "@types/mocha": "^10.0.0", "@types/node": "^18.8.5", "@types/yargs": "^17.0.13", - "@typescript-eslint/eslint-plugin": "^5.40.0", - "@typescript-eslint/parser": "^5.40.0", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "chai": "^4.3.7", "dotenv": "^16.0.3", "eslint": "^8.25.0", @@ -77,7 +77,7 @@ "prettier": "^3.0.3", "prettier-plugin-solidity": "^1.1.3", "rimraf": "^5.0.1", - "solhint": "^3.3.7", + "solhint": "^4.0.0", "solhint-plugin-prettier": "^0.1.0", "solidity-coverage": "^0.8.4", "ts-node": "^10.9.1", diff --git a/yarn.lock b/yarn.lock index 55206cb7..ca9709c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -72,14 +72,14 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@eslint-community/eslint-utils@^4.2.0": +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== @@ -854,6 +854,27 @@ picocolors "^1.0.0" tslib "^2.6.0" +"@pnpm/config.env-replace@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" + integrity sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w== + +"@pnpm/network.ca-file@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz#2ab05e09c1af0cdf2fcf5035bea1484e222f7983" + integrity sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA== + dependencies: + graceful-fs "4.2.10" + +"@pnpm/npm-conf@^2.1.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz#0058baf1c26cbb63a828f0193795401684ac86f0" + integrity sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA== + dependencies: + "@pnpm/config.env-replace" "^1.1.0" + "@pnpm/network.ca-file" "^1.0.1" + config-chain "^1.1.11" + "@prettier/sync@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@prettier/sync/-/sync-0.3.0.tgz#91f2cfc23490a21586d1cf89c6f72157c000ca1e" @@ -966,6 +987,11 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" +"@sindresorhus/is@^5.2.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" + integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== + "@solidity-parser/parser@^0.14.0": version "0.14.5" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" @@ -980,6 +1006,13 @@ dependencies: antlr4ts "^0.5.0-alpha.4" +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -1063,7 +1096,12 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/json-schema@^7.0.9": +"@types/http-cache-semantics@^4.0.2": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#a3ff232bf7d5c55f38e4e45693eda2ebb545794d" + integrity sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA== + +"@types/json-schema@^7.0.12": version "7.0.14" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== @@ -1144,7 +1182,7 @@ dependencies: "@types/node" "*" -"@types/semver@^7.3.12": +"@types/semver@^7.5.0": version "7.5.4" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff" integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ== @@ -1161,89 +1199,90 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.40.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" - integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== +"@typescript-eslint/eslint-plugin@^6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz#d8ce497dc0ed42066e195c8ecc40d45c7b1254f4" + integrity sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg== dependencies: - "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/type-utils" "5.62.0" - "@typescript-eslint/utils" "5.62.0" + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.9.1" + "@typescript-eslint/type-utils" "6.9.1" + "@typescript-eslint/utils" "6.9.1" + "@typescript-eslint/visitor-keys" "6.9.1" debug "^4.3.4" graphemer "^1.4.0" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.40.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" - integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== - dependencies: - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.9.1.tgz#4f685f672f8b9580beb38d5fb99d52fc3e34f7a3" + integrity sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg== + dependencies: + "@typescript-eslint/scope-manager" "6.9.1" + "@typescript-eslint/types" "6.9.1" + "@typescript-eslint/typescript-estree" "6.9.1" + "@typescript-eslint/visitor-keys" "6.9.1" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== +"@typescript-eslint/scope-manager@6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz#e96afeb9a68ad1cd816dba233351f61e13956b75" + integrity sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg== dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" + "@typescript-eslint/types" "6.9.1" + "@typescript-eslint/visitor-keys" "6.9.1" -"@typescript-eslint/type-utils@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" - integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== +"@typescript-eslint/type-utils@6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz#efd5db20ed35a74d3c7d8fba51b830ecba09ce32" + integrity sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg== dependencies: - "@typescript-eslint/typescript-estree" "5.62.0" - "@typescript-eslint/utils" "5.62.0" + "@typescript-eslint/typescript-estree" "6.9.1" + "@typescript-eslint/utils" "6.9.1" debug "^4.3.4" - tsutils "^3.21.0" + ts-api-utils "^1.0.1" -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== +"@typescript-eslint/types@6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.9.1.tgz#a6cfc20db0fcedcb2f397ea728ef583e0ee72459" + integrity sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ== -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== +"@typescript-eslint/typescript-estree@6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz#8c77910a49a04f0607ba94d78772da07dab275ad" + integrity sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw== dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" + "@typescript-eslint/types" "6.9.1" + "@typescript-eslint/visitor-keys" "6.9.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.9.1.tgz#763da41281ef0d16974517b5f0d02d85897a1c1e" + integrity sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.9.1" + "@typescript-eslint/types" "6.9.1" + "@typescript-eslint/typescript-estree" "6.9.1" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@6.9.1": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz#6753a9225a0ba00459b15d6456b9c2780b66707d" + integrity sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw== + dependencies: + "@typescript-eslint/types" "6.9.1" + eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": version "1.2.0" @@ -1732,6 +1771,24 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cacheable-lookup@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" + integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== + +cacheable-request@^10.2.8: + version "10.2.14" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" + integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== + dependencies: + "@types/http-cache-semantics" "^4.0.2" + get-stream "^6.0.1" + http-cache-semantics "^4.1.1" + keyv "^4.5.3" + mimic-response "^4.0.0" + normalize-url "^8.0.0" + responselike "^3.0.0" + call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" @@ -1980,6 +2037,14 @@ concat-stream@^1.6.0, concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" +config-chain@^1.1.11: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + cookie@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -2071,6 +2136,13 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + deep-eql@^4.0.1, deep-eql@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" @@ -2078,7 +2150,7 @@ deep-eql@^4.0.1, deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" -deep-extend@~0.6.0: +deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== @@ -2106,6 +2178,11 @@ default-browser@^4.0.0: execa "^7.1.1" titleize "^3.0.0" +defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" @@ -2397,14 +2474,6 @@ eslint-plugin-prettier@^5.0.1: prettier-linter-helpers "^1.0.0" synckit "^0.8.5" -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - eslint-scope@^7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" @@ -2500,11 +2569,6 @@ estraverse@^1.9.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" @@ -2824,6 +2888,11 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +form-data-encoder@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" + integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== + form-data@^2.2.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -3132,6 +3201,28 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +got@^12.1.0: + version "12.6.1" + resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" + integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.8" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +graceful-fs@4.2.10: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -3349,6 +3440,11 @@ http-basic@^8.1.1: http-response-object "^3.0.1" parse-cache-control "^1.0.1" +http-cache-semantics@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -3367,6 +3463,14 @@ http-response-object@^3.0.1: dependencies: "@types/node" "^10.0.3" +http2-wrapper@^2.1.10: + version "2.2.0" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3" + integrity sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -3448,7 +3552,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@^1.3.5: +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -3812,6 +3916,13 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +latest-version@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" + integrity sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg== + dependencies: + package-json "^8.1.0" + level-supports@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" @@ -3904,6 +4015,11 @@ loupe@^2.3.6: dependencies: get-func-name "^2.0.1" +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -4016,6 +4132,16 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +mimic-response@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" + integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -4144,11 +4270,6 @@ napi-macros@^2.2.2: resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.2.2.tgz#817fef20c3e0e40a963fbf7b37d1600bd0201044" integrity sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g== -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -4193,6 +4314,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-url@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.0.tgz#593dbd284f743e8dcf6a5ddf8fadff149c82701a" + integrity sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw== + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -4338,6 +4464,11 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -4378,6 +4509,16 @@ p-try@^1.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== +package-json@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" + integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== + dependencies: + got "^12.1.0" + registry-auth-token "^5.0.1" + registry-url "^6.0.0" + semver "^7.3.7" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -4527,6 +4668,11 @@ promise@^8.0.0: dependencies: asap "~2.0.6" +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -4549,6 +4695,11 @@ queue-microtask@^1.2.2, queue-microtask@^1.2.3: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -4566,6 +4717,16 @@ raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +rc@1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + readable-stream@^2.2.2: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" @@ -4623,6 +4784,20 @@ regexp.prototype.flags@^1.5.1: define-properties "^1.2.0" set-function-name "^2.0.0" +registry-auth-token@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.2.tgz#8b026cc507c8552ebbe06724136267e63302f756" + integrity sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ== + dependencies: + "@pnpm/npm-conf" "^2.1.0" + +registry-url@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" + integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== + dependencies: + rc "1.2.8" + req-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" @@ -4647,6 +4822,11 @@ require-from-string@^2.0.0, require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -4678,6 +4858,13 @@ resolve@^1.1.6, resolve@^1.22.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +responselike@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" + integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== + dependencies: + lowercase-keys "^3.0.0" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -4823,7 +5010,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2: +semver@^7.3.4, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -4959,10 +5146,10 @@ solhint-plugin-prettier@^0.1.0: "@prettier/sync" "^0.3.0" prettier-linter-helpers "^1.0.0" -solhint@^3.3.7: - version "3.6.2" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.6.2.tgz#2b2acbec8fdc37b2c68206a71ba89c7f519943fe" - integrity sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ== +solhint@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-4.0.0.tgz#fbd27ec9c8348b4fea90b5b469a5c95d625d2e59" + integrity sha512-bFViMcFvhqVd/HK3Roo7xZXX5nbujS7Bxeg5vnZc9QvH0yCWCrQ38Yrn1pbAY9tlKROc6wFr+rK1mxYgYrjZgA== dependencies: "@solidity-parser/parser" "^0.16.0" ajv "^6.12.6" @@ -4975,6 +5162,7 @@ solhint@^3.3.7: glob "^8.0.3" ignore "^5.2.4" js-yaml "^4.1.0" + latest-version "^7.0.0" lodash "^4.17.21" pluralize "^8.0.0" semver "^7.5.2" @@ -5172,6 +5360,11 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + supports-color@8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -5296,6 +5489,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +ts-api-utils@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" + integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== + ts-command-line-args@^2.2.0: version "2.5.1" resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" @@ -5340,7 +5538,7 @@ tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -5355,13 +5553,6 @@ tsort@0.0.1: resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" From d0b988c5b29272ee43b3b6f90b7e1857da0ec776 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 15:55:06 +0100 Subject: [PATCH 56/82] Rename --- contracts/core/GuardableModifier.sol | 4 ++-- contracts/core/Modifier.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/core/GuardableModifier.sol b/contracts/core/GuardableModifier.sol index 984c86b3..e7004769 100644 --- a/contracts/core/GuardableModifier.sol +++ b/contracts/core/GuardableModifier.sol @@ -37,7 +37,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - sentOrSignedBy() + sentOrSignedByModule() ); } success = IAvatar(target).execTransactionFromModule( @@ -78,7 +78,7 @@ abstract contract GuardableModifier is Module, Guardable, Modifier { address(0), payable(0), "", - sentOrSignedBy() + sentOrSignedByModule() ); } diff --git a/contracts/core/Modifier.sol b/contracts/core/Modifier.sol index d44f0ee2..0f44c88b 100644 --- a/contracts/core/Modifier.sol +++ b/contracts/core/Modifier.sol @@ -96,7 +96,7 @@ abstract contract Modifier is _; } - function sentOrSignedBy() internal view returns (address) { + function sentOrSignedByModule() internal view returns (address) { if (modules[msg.sender] != address(0)) { return msg.sender; } From 3d56dc2ab34dd699f4b9d43108a20e5a0568db63 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 16:38:53 +0100 Subject: [PATCH 57/82] Tests for sentOrSignedByModule --- contracts/test/TestModifier.sol | 4 ++ test/03_Modifier.spec.ts | 101 +++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/contracts/test/TestModifier.sol b/contracts/test/TestModifier.sol index adbed17c..f175384d 100644 --- a/contracts/test/TestModifier.sol +++ b/contracts/test/TestModifier.sol @@ -78,6 +78,10 @@ contract TestModifier is Modifier { target = _target; } + function exposeSentOrSignedByModule() external view returns (address) { + return sentOrSignedByModule(); + } + function attemptToSetupModules() public { setupModules(); } diff --git a/test/03_Modifier.spec.ts b/test/03_Modifier.spec.ts index 259595cb..16c95505 100644 --- a/test/03_Modifier.spec.ts +++ b/test/03_Modifier.spec.ts @@ -4,7 +4,7 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; import { PopulatedTransaction } from "ethers"; -import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; +import { defaultAbiCoder, keccak256, toUtf8Bytes } from "ethers/lib/utils"; import hre from "hardhat"; import { TestAvatar__factory, TestModifier__factory } from "../typechain-types"; @@ -15,7 +15,7 @@ describe("Modifier", async () => { const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001"; async function setupTests() { - const [signer] = await hre.ethers.getSigners(); + const [signer, alice, bob, charlie] = await hre.ethers.getSigners(); const Avatar = await hre.ethers.getContractFactory("TestAvatar"); const avatar = await Avatar.connect(signer).deploy(); const iAvatar = TestAvatar__factory.connect(avatar.address, signer); @@ -42,6 +42,9 @@ describe("Modifier", async () => { iAvatar, modifier: TestModifier__factory.connect(modifier.address, signer), tx, + alice, + bob, + charlie, }; } @@ -700,6 +703,81 @@ describe("Modifier", async () => { ).to.be.revertedWithCustomError(modifier, "HashAlreadyConsumed"); }); }); + + describe("sentOrSignedByModule", async () => { + it("returns msg.sender if msg.sender is module", async () => { + const { modifier, alice, bob } = await loadFixture(setupTests); + + await modifier.enableModule(alice.address); + expect( + await modifier.connect(alice).exposeSentOrSignedByModule() + ).to.equal(alice.address); + + expect(await modifier.connect(bob).exposeSentOrSignedByModule()).to.equal( + AddressZero + ); + }); + + it("returns msg.sender if msg.sender is module, even if valid sig appended", async () => { + const { modifier, alice, bob, charlie } = await loadFixture(setupTests); + + await modifier.enableModule(alice.address); + await modifier.enableModule(bob.address); + + const transaction = await signTransaction( + modifier.address, + await modifier.populateTransaction.exposeSentOrSignedByModule(), + keccak256(toUtf8Bytes("something salty")), + bob + ); + + // if alice sends it, msg.sender is taken into account, because alice module + expect(await alice.call(transaction)).to.equal( + defaultAbiCoder.encode(["address"], [alice.address]) + ); + + // if charlie sends it, signature is taken into account because bob module + expect(await charlie.call(transaction)).to.equal( + defaultAbiCoder.encode(["address"], [bob.address]) + ); + }); + + it("returns signer if signer is module", async () => { + const { modifier, alice, charlie } = await loadFixture(setupTests); + + await modifier.enableModule(alice.address); + + const transaction = await signTransaction( + modifier.address, + await modifier.populateTransaction.exposeSentOrSignedByModule(), + keccak256(toUtf8Bytes("something salty")), + alice + ); + + // if alice sends it, msg.sender is taken into account, because alice module + expect(await charlie.call(transaction)).to.equal( + defaultAbiCoder.encode(["address"], [alice.address]) + ); + }); + + it("returns zero if signer is not module and message sender not a module", async () => { + const { modifier, alice, charlie } = await loadFixture(setupTests); + + // no modules enabled + + const transaction = await signTransaction( + modifier.address, + await modifier.populateTransaction.exposeSentOrSignedByModule(), + keccak256(toUtf8Bytes("something salty")), + alice + ); + + // if alice sends it, msg.sender is taken into account, because alice module + expect(await charlie.call(transaction)).to.equal( + defaultAbiCoder.encode(["address"], [AddressZero]) + ); + }); + }); }); async function sign( @@ -717,3 +795,22 @@ async function sign( return `${salt}${signature.slice(2)}`; } + +async function signTransaction( + contract: string, + { from, ...transaction }: PopulatedTransaction, + salt: string, + signer: SignerWithAddress +) { + const { domain, types, message } = typedDataForTransaction( + { contract, chainId: 31337, salt }, + transaction.data || "0x" + ); + + const signature = await signer._signTypedData(domain, types, message); + + return { + ...transaction, + data: `${transaction.data as string}${salt.slice(2)}${signature.slice(2)}`, + }; +} From 0312a26fd0c3138da996fb84c50106e798137d04 Mon Sep 17 00:00:00 2001 From: Cristovao Honorato Date: Tue, 31 Oct 2023 17:21:46 +0100 Subject: [PATCH 58/82] Bump package.json version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78d895bd..16188935 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.4.0", + "version": "3.4.1", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", From 1842d03a20c780de3f6b4e7d3cd5bd86206c16fa Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Tue, 7 Nov 2023 10:36:25 +0100 Subject: [PATCH 59/82] Keep Delay mod version history --- sdk/contracts.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/contracts.ts b/sdk/contracts.ts index c6f97200..611ff639 100644 --- a/sdk/contracts.ts +++ b/sdk/contracts.ts @@ -76,7 +76,8 @@ const CanonicalAddresses: Record< "1.0.0": "0x03B5eBD2CB2e3339E93774A1Eb7c8634B8C393A9", }, [KnownContracts.DELAY]: { - "1.0.0": "0xd54895B1121A2eE3f37b502F507631FA1331BED6", + "1.0.0": "0xD62129BF40CD1694b3d9D9847367783a1A4d5cB4", + "1.0.1": "0xd54895B1121A2eE3f37b502F507631FA1331BED6", }, [KnownContracts.FACTORY]: { "1.0.0": "0x00000000062c52e29e8029dc2413172f6d619d85", From 2333afb84a42216b0776382b84f6080b653c8efc Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Tue, 7 Nov 2023 10:40:21 +0100 Subject: [PATCH 60/82] bump version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 16188935..411e19a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.4.1", + "version": "3.4.2", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", @@ -92,4 +92,4 @@ "@openzeppelin/contracts-upgradeable": "^5.0.0", "ethers": "^5.7.1" } -} +} \ No newline at end of file From c59d9e576befa33d3e7a8f126d40c88af6e19037 Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Fri, 15 Dec 2023 16:54:53 +0100 Subject: [PATCH 61/82] add Roles V2 --- sdk/abi/{Roles.json => RolesV1.json} | 2 +- sdk/abi/RolesV2.json | 1408 +++++++++++++++++++++++++ sdk/contracts.ts | 25 +- sdk/factory/types.ts | 6 +- sdk/initData/{Roles.ts => RolesV1.ts} | 0 sdk/initData/RolesV2.ts | 4 + 6 files changed, 1438 insertions(+), 7 deletions(-) rename sdk/abi/{Roles.json => RolesV1.json} (99%) create mode 100644 sdk/abi/RolesV2.json rename sdk/initData/{Roles.ts => RolesV1.ts} (100%) create mode 100644 sdk/initData/RolesV2.ts diff --git a/sdk/abi/Roles.json b/sdk/abi/RolesV1.json similarity index 99% rename from sdk/abi/Roles.json rename to sdk/abi/RolesV1.json index 475a7710..48c9ca47 100644 --- a/sdk/abi/Roles.json +++ b/sdk/abi/RolesV1.json @@ -987,4 +987,4 @@ "stateMutability": "nonpayable", "type": "function" } -] +] \ No newline at end of file diff --git a/sdk/abi/RolesV2.json b/sdk/abi/RolesV2.json new file mode 100644 index 00000000..32948967 --- /dev/null +++ b/sdk/abi/RolesV2.json @@ -0,0 +1,1408 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_avatar", + "type": "address" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "AlreadyDisabledModule", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "AlreadyEnabledModule", + "type": "error" + }, + { + "inputs": [], + "name": "ArraysDifferentLength", + "type": "error" + }, + { + "inputs": [], + "name": "CalldataOutOfBounds", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum PermissionChecker.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "info", + "type": "bytes32" + } + ], + "name": "ConditionViolation", + "type": "error" + }, + { + "inputs": [], + "name": "FunctionSignatureTooShort", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "HashAlreadyConsumed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "InvalidModule", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPageSize", + "type": "error" + }, + { + "inputs": [], + "name": "MalformedMultiEntrypoint", + "type": "error" + }, + { + "inputs": [], + "name": "ModuleTransactionFailed", + "type": "error" + }, + { + "inputs": [], + "name": "NoMembership", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "NotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "SetupModulesAlreadyCalled", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" + } + ], + "name": "AllowFunction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" + } + ], + "name": "AllowTarget", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32[]", + "name": "roleKeys", + "type": "bytes32[]" + }, + { + "indexed": false, + "internalType": "bool[]", + "name": "memberOf", + "type": "bool[]" + } + ], + "name": "AssignRoles", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAvatar", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAvatar", + "type": "address" + } + ], + "name": "AvatarSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "allowanceKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "consumed", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newBalance", + "type": "uint128" + } + ], + "name": "ConsumeAllowance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "DisabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "EnabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ExecutionFromModuleFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ExecutionFromModuleSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "HashExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "HashInvalidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "RevokeFunction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "RevokeTarget", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "avatar", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "RolesModSetup", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "parent", + "type": "uint8" + }, + { + "internalType": "enum ParameterType", + "name": "paramType", + "type": "uint8" + }, + { + "internalType": "enum Operator", + "name": "operator", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "compValue", + "type": "bytes" + } + ], + "indexed": false, + "internalType": "struct ConditionFlat[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" + } + ], + "name": "ScopeFunction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "ScopeTarget", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "allowanceKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "balance", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "maxRefill", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "refill", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "period", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "SetAllowance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "defaultRoleKey", + "type": "bytes32" + } + ], + "name": "SetDefaultRole", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "contract ITransactionUnwrapper", + "name": "adapter", + "type": "address" + } + ], + "name": "SetUnwrapAdapter", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousTarget", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newTarget", + "type": "address" + } + ], + "name": "TargetSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" + } + ], + "name": "allowFunction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" + } + ], + "name": "allowTarget", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "allowances", + "outputs": [ + { + "internalType": "uint128", + "name": "refill", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "maxRefill", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "period", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "balance", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "roleKeys", + "type": "bytes32[]" + }, + { + "internalType": "bool[]", + "name": "memberOf", + "type": "bool[]" + } + ], + "name": "assignRoles", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "avatar", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "consumed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "defaultRoles", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevModule", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "disableModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "enableModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModuleReturnData", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "shouldRevert", + "type": "bool" + } + ], + "name": "execTransactionWithRole", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "shouldRevert", + "type": "bool" + } + ], + "name": "execTransactionWithRoleReturnData", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "start", + "type": "address" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getModulesPaginated", + "outputs": [ + { + "internalType": "address[]", + "name": "array", + "type": "address[]" + }, + { + "internalType": "address", + "name": "next", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "invalidate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_module", + "type": "address" + } + ], + "name": "isModuleEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "moduleTxHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "revokeFunction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "revokeTarget", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "parent", + "type": "uint8" + }, + { + "internalType": "enum ParameterType", + "name": "paramType", + "type": "uint8" + }, + { + "internalType": "enum Operator", + "name": "operator", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "compValue", + "type": "bytes" + } + ], + "internalType": "struct ConditionFlat[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "internalType": "enum ExecutionOptions", + "name": "options", + "type": "uint8" + } + ], + "name": "scopeFunction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "scopeTarget", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "internalType": "uint128", + "name": "balance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "maxRefill", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "refill", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "period", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "setAllowance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_avatar", + "type": "address" + } + ], + "name": "setAvatar", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "roleKey", + "type": "bytes32" + } + ], + "name": "setDefaultRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setTarget", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + }, + { + "internalType": "contract ITransactionUnwrapper", + "name": "adapter", + "type": "address" + } + ], + "name": "setTransactionUnwrapper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initParams", + "type": "bytes" + } + ], + "name": "setUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "target", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "unwrappers", + "outputs": [ + { + "internalType": "contract ITransactionUnwrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/sdk/contracts.ts b/sdk/contracts.ts index 611ff639..d0389c26 100644 --- a/sdk/contracts.ts +++ b/sdk/contracts.ts @@ -15,7 +15,8 @@ import OzGovernorAbi from "./abi/OzGovernor.json"; import PermissionsAbi from "./abi/Permissions.json"; import RealityErc20Abi from "./abi/RealityErc20.json"; import RealityEthAbi from "./abi/RealityEth.json"; -import RolesAbi from "./abi/Roles.json"; +import RolesV1Abi from "./abi/RolesV1.json"; +import RolesV2Abi from "./abi/RolesV2.json"; import ScopeGuardAbi from "./abi/ScopeGuard.json"; import TellorAbi from "./abi/Tellor.json"; import { KnownContracts } from "./factory/types"; @@ -34,7 +35,8 @@ import * as OzGovernorInitData from "./initData/OzGovernor"; import * as PermissionsInitData from "./initData/Permissions"; import * as RealityErc20InitData from "./initData/RealityErc20"; import * as RealityEthInitData from "./initData/RealityEth"; -import * as RolesInitData from "./initData/Roles"; +import * as RolesV1InitData from "./initData/RolesV1"; +import * as RolesV2InitData from "./initData/RolesV2"; import * as ScopeGuardInitData from "./initData/ScopeGuard"; import { factories } from "./types"; @@ -109,9 +111,16 @@ const CanonicalAddresses: Record< "1.0.0": "0x85388a8cd772b19a468F982Dc264C238856939C9", "1.1.0": "0xD8DfC1d938D7D163C5231688341e9635E9011889", }, + [KnownContracts.ROLES_V1]: { + "1.0.0": "0x85388a8cd772b19a468F982Dc264C238856939C9", + "1.1.0": "0xD8DfC1d938D7D163C5231688341e9635E9011889", + }, [KnownContracts.PERMISSIONS]: { "1.0.0": "0x33D1C5A5B6a7f3885c7467e829aaa21698937597", }, + [KnownContracts.ROLES_V2]: { + "2.1.0": "0x9646fDAD06d3e24444381f44362a3B0eB343D337", + }, [KnownContracts.TELLOR]: { "2.1.0": "0xa89EC2C1e218CfBb0F82829E95352CeAbDEe9A69", }, @@ -236,7 +245,9 @@ export const ContractAbis: Record = { [KnownContracts.OZ_GOVERNOR]: OzGovernorAbi, [KnownContracts.REALITY_ERC20]: RealityErc20Abi, [KnownContracts.REALITY_ETH]: RealityEthAbi, - [KnownContracts.ROLES]: RolesAbi, + [KnownContracts.ROLES]: RolesV1Abi, + [KnownContracts.ROLES_V1]: RolesV1Abi, + [KnownContracts.ROLES_V2]: RolesV2Abi, [KnownContracts.SCOPE_GUARD]: ScopeGuardAbi, [KnownContracts.TELLOR]: TellorAbi, [KnownContracts.MULTISEND_ENCODER]: MultisendEncoderAbi, @@ -261,7 +272,9 @@ export const ContractFactories = { [KnownContracts.OZ_GOVERNOR]: factories.OzGovernor__factory, [KnownContracts.REALITY_ERC20]: factories.RealityErc20__factory, [KnownContracts.REALITY_ETH]: factories.RealityEth__factory, - [KnownContracts.ROLES]: factories.Roles__factory, + [KnownContracts.ROLES]: factories.RolesV1__factory, + [KnownContracts.ROLES_V1]: factories.RolesV1__factory, + [KnownContracts.ROLES_V2]: factories.RolesV2__factory, [KnownContracts.SCOPE_GUARD]: factories.ScopeGuard__factory, [KnownContracts.TELLOR]: factories.Tellor__factory, [KnownContracts.MULTISEND_ENCODER]: factories.MultisendEncoder__factory, @@ -287,7 +300,9 @@ export const MasterCopyInitData: Record< [KnownContracts.OZ_GOVERNOR]: OzGovernorInitData, [KnownContracts.REALITY_ERC20]: RealityErc20InitData, [KnownContracts.REALITY_ETH]: RealityEthInitData, - [KnownContracts.ROLES]: RolesInitData, + [KnownContracts.ROLES]: RolesV1InitData, + [KnownContracts.ROLES_V1]: RolesV1InitData, + [KnownContracts.ROLES_V2]: RolesV2InitData, [KnownContracts.SCOPE_GUARD]: ScopeGuardInitData, [KnownContracts.TELLOR]: undefined, [KnownContracts.MULTISEND_ENCODER]: MultisendEncoderInitData, diff --git a/sdk/factory/types.ts b/sdk/factory/types.ts index 863f5f2c..015f075f 100644 --- a/sdk/factory/types.ts +++ b/sdk/factory/types.ts @@ -14,7 +14,9 @@ export type { Permissions, RealityErc20, RealityEth, - Roles, + RolesV1 as Roles, + RolesV1, + RolesV2, ScopeGuard, Tellor, Usul, @@ -35,6 +37,8 @@ export enum KnownContracts { SCOPE_GUARD = "scopeGuard", FACTORY = "factory", ROLES = "roles", + ROLES_V1 = "roles_v1", + ROLES_V2 = "roles_v2", OZ_GOVERNOR = "ozGovernor", ERC20_VOTES = "erc20Votes", ERC721_VOTES = "erc721Votes", diff --git a/sdk/initData/Roles.ts b/sdk/initData/RolesV1.ts similarity index 100% rename from sdk/initData/Roles.ts rename to sdk/initData/RolesV1.ts diff --git a/sdk/initData/RolesV2.ts b/sdk/initData/RolesV2.ts new file mode 100644 index 00000000..339c5ad8 --- /dev/null +++ b/sdk/initData/RolesV2.ts @@ -0,0 +1,4 @@ +export const salt = + "0x0000000000000000000000000000000000000000000000000000000000000000"; +export const initCode = + "0x608060405234801562000010575f80fd5b506040516200630a3803806200630a83398101604081905262000033916200035a565b604080516001600160a01b038581166020830152848116828401528316606080830191909152825180830390910181526080909101909152620000768162000080565b50505050620003ab565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff1615906001600160401b03165f81158015620000ca5750825b90505f826001600160401b03166001148015620000e65750303b155b905081158015620000f5575080155b15620001145760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b031916600117855583156200014357845460ff60401b1916680100000000000000001785555b5f805f888060200190518101906200015c91906200035a565b919450925090506200016e8362000240565b5f80546001600160a01b038085166001600160a01b0319928316179092556001805492841692909116919091179055620001a7620002b0565b6040516001600160a01b038281168252808416919085169033907f34d3b96a088381c6843a1f9d94d251afa88f83cc7a0d17fc23a7057506a3fc6d9060200160405180910390a450505083156200023857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b60015f5260036020527fa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c546001600160a01b031615620003035760405163dfd49ebd60e01b815260040160405180910390fd5b60015f81905260036020527fa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c80546001600160a01b0319169091179055565b6001600160a01b038116811462000357575f80fd5b50565b5f805f606084860312156200036d575f80fd5b83516200037a8162000342565b60208501519093506200038d8162000342565b6040850151909250620003a08162000342565b809150509250925092565b615f5180620003b95f395ff3fe608060405234801561000f575f80fd5b50600436106101ab575f3560e01c80637508dd98116100eb578063b3dd25c71161008f578063b3dd25c71461044a578063c6fe87471461045d578063cc2f845214610470578063d4b8399214610491578063d8afba76146104a4578063e009cfde146104b7578063e29dfba8146104ca578063f2fde38b146104f7575f80fd5b80637508dd98146103bd578063776d1a01146103d05780637b0da5b2146103e35780638da5cb5b146103f6578063946d364e146103fe578063957ed2b314610411578063a4f9edbf14610424578063a8ec43ee14610437575f80fd5b8063468721a711610152578063468721a7146102ac5780635229073f146102bf5780635aef7de6146102d25780635e7c9fe8146102e4578063610b59251461037c57806366523f7d1461038f57806369ecc3cf146103a2578063715018a6146103b5575f80fd5b80630172a43a146101af578063086cfca8146101c45780630c6c76b8146101d75780632916a9af146101ea5780632959513c146101fd5780632b99e5061461023b5780632d3c25471461025c5780632d9ad53d14610289575b5f80fd5b6101c26101bd366004614d45565b61050a565b005b6101c26101d2366004614d73565b6105e0565b6101c26101e5366004614d45565b610637565b6101c26101f8366004614da5565b61070b565b61022561020b366004614deb565b60066020525f90815260409020546001600160a01b031681565b6040516102329190614e02565b60405180910390f35b61024e610249366004614e6c565b6107b0565b604051610232929190614f42565b61027b61026a366004614d73565b60076020525f908152604090205481565b604051908152602001610232565b61029c610297366004614d73565b610854565b6040519015158152602001610232565b61029c6102ba366004614f5c565b61088d565b61024e6102cd366004614f5c565b61090f565b5f54610225906001600160a01b031681565b61033d6102f2366004614deb565b60056020525f9081526040902080546001909101546001600160801b0380831692600160801b90048116916001600160401b0380821692600160401b83041691600160c01b90041685565b604080516001600160801b03968716815294861660208601526001600160401b039384169085015293166060830152909116608082015260a001610232565b6101c261038a366004614d73565b610998565b6101c261039d366004614fca565b610aa7565b6101c26103b0366004614deb565b610b31565b6101c2610b83565b6101c26103cb366004615140565b610b96565b6101c26103de366004614d73565b610c69565b6101c26103f13660046152b3565b610cc2565b610225610d9d565b6101c261040c3660046152e5565b610dcb565b6101c261041f36600461534f565b610e23565b6101c26104323660046153cb565b610f38565b6101c2610445366004615428565b6110f1565b6101c2610458366004615491565b6112ea565b61029c61046b366004614e6c565b61136a565b61048361047e3660046152e5565b611408565b6040516102329291906154dd565b600154610225906001600160a01b031681565b61027b6104b2366004615539565b611598565b6101c26104c5366004615580565b6116b6565b61029c6104d83660046152e5565b600260209081525f928352604080842090915290825290205460ff1681565b6101c2610505366004614d73565b6117ad565b6105126117ea565b6040805180820182525f8082526020808301829052858252600481528382206001600160a01b0386168352600190810190915292902081518154929391929091839160ff19169083600281111561056b5761056b6155ac565b021790555060208201518154829061ff001916610100836003811115610593576105936155ac565b021790555050604080518481526001600160a01b03841660208201527f3ccf62aacc3286173cedf5c20ec550071636a2faf0a3b28d93841736a43f822b9250015b60405180910390a15050565b6105e86117ea565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f52ae88b092de36f87fb43fe794eb1381023b9c1bce563a871154022c63dce3429190a35050565b61063f6117ea565b6040805180820190915280600281526020015f90525f8381526004602090815260408083206001600160a01b038616845260019081019092529091208251815491929091839160ff199091169083600281111561069e5761069e6155ac565b021790555060208201518154829061ff0019166101008360038111156106c6576106c66155ac565b021790555050604080518481526001600160a01b03841660208201527f277465b84f512b759d745fab70327b693ee21ce592fca91a3f491739a25fa76a9250016105d4565b6107136117ea565b60a082901c63ffffffff60401b16606084811b6001600160601b031916919091175f9081526006602090815260409182902080546001600160a01b0319166001600160a01b03868116918217909255835191881682526001600160e01b0319871692820192909252918201527f1330d96b64c7e86736f77e027ca34223dd3d1d08049281281c9d597d8098ed5991015b60405180910390a1505050565b5f60605f6107c2858b8b8b8b8b61181c565b90506107cd81611a77565b61080f8a8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c9250611bd0915050565b909350915083801561081f575082155b1561083d5760405163d27b44a960e01b815260040160405180910390fd5b6108478184611c5a565b5097509795505050505050565b5f60016001600160a01b0383161480159061088757506001600160a01b038281165f908152600360205260409020541615155b92915050565b335f9081526007602052604081205481906108ac90888888888861181c565b90506108b781611a77565b6108f9878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250899250611d46915050565b91506109058183611c5a565b5095945050505050565b335f90815260076020526040812054606090829061093190898989898961181c565b905061093c81611a77565b61097e888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508a9250611bd0915050565b909350915061098d8184611c5a565b509550959350505050565b6109a06117ea565b6001600160a01b03811615806109bf57506001600160a01b0381166001145b156109e85780604051635c93ff2f60e11b81526004016109df9190614e02565b60405180910390fd5b6001600160a01b038181165f908152600360205260409020541615610a225780604051632061897360e01b81526004016109df9190614e02565b60036020525f80516020615efc83398151915280546001600160a01b038381165f81815260408082208054949095166001600160a01b03199485161790945560019052835490911617909155517fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844090610a9c908390614e02565b60405180910390a150565b610aaf6117ea565b5f83815260046020526040812060020190610aca8484611dc7565b81526020019081526020015f205f90557f32a3a599b308fc900a0e6513db2ad40bf0c94367da90048a4b308d8c6b2dd6ea8383836040516107a3939291909283526001600160a01b039190911660208301526001600160e01b031916604082015260600190565b335f908152600260209081526040808320848452825291829020805460ff1916600117905590518281527f89a77869d7b8125ba16e08a92ddc8cc26fb1fa47241971167954489a5e66c2559101610a9c565b610b8b6117ea565b610b945f611de7565b565b610b9e6117ea565b60405163783a904760e01b8152736a6Af4b16458Bc39817e4019fB02BD3b26d410499063783a904790610bd59085906004016155e4565b5f6040518083038186803b158015610beb575f80fd5b505af4158015610bfd573d5f803e3d5ffd5b5050505f868152600460205260409020610c239150610c1c8686611dc7565b8484611e57565b7f4f6c340456f64db31a3d003c1224ba1de058557b1cdf71f21ae48ce4a4f64f528585858585604051610c5a959493929190615691565b60405180910390a15050505050565b610c716117ea565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f90cc2f570a6eb594b1580ea3e41247d2d73a55281889e86bd4ec2fc29c7e62d6905f90a35050565b610cca6117ea565b604080518082019091528060018152602001826003811115610cee57610cee6155ac565b90525f8481526004602090815260408083206001600160a01b038716845260019081019092529091208251815491929091839160ff1990911690836002811115610d3a57610d3a6155ac565b021790555060208201518154829061ff001916610100836003811115610d6257610d626155ac565b02179055509050507f05e4ec9b54e94ad676ef61d57214f6d57d752ed2022dea5e5f956d5df7ccb2508383836040516107a39392919061575d565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b610dd36117ea565b6001600160a01b0382165f81815260076020908152604091829020849055815192835282018390527f60c85b61661a191efceebca036d48b290e04a1f08dd96472b920adbdd50c64e891016105d4565b610e2b6117ea565b828114610e4b576040516374f4d53760e01b815260040160405180910390fd5b5f5b61ffff8116841115610eea5782828261ffff16818110610e6f57610e6f615780565b9050602002016020810190610e849190615794565b60045f87878561ffff16818110610e9d57610e9d615780565b602090810292909201358352508181019290925260409081015f9081206001600160a01b038b1682529092529020805460ff1916911515919091179055610ee3816157c3565b9050610e4d565b50610ef485610854565b610f0157610f0185610998565b7f9f8368fa4ddcbd561efd7ad2a2174235bf5b840a73fb18f20db9705c114624988585858585604051610c5a9594939291906157e3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610f7c5750825b90505f826001600160401b03166001148015610f975750303b155b905081158015610fa5575080155b15610fc35760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610fed57845460ff60401b1916600160401b1785555b5f805f888060200190518101906110049190615872565b92509250925061101383611de7565b5f80546001600160a01b038085166001600160a01b031992831617909255600180549284169290911691909117905561104a611f06565b816001600160a01b0316836001600160a01b0316336001600160a01b03167f34d3b96a088381c6843a1f9d94d251afa88f83cc7a0d17fc23a7057506a3fc6d846040516110979190614e02565b60405180910390a450505083156110e957845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906020015b60405180910390a15b505050505050565b6110f96117ea565b836001600160801b03165f03611116576001600160801b03611118565b835b9350806001600160401b03165f036111305742611132565b805b90506040518060a00160405280846001600160801b03168152602001856001600160801b03168152602001836001600160401b03168152602001866001600160801b03168152602001826001600160401b031681525060055f8881526020019081526020015f205f820151815f015f6101000a8154816001600160801b0302191690836001600160801b031602179055506020820151815f0160106101000a8154816001600160801b0302191690836001600160801b031602179055506040820151816001015f6101000a8154816001600160401b0302191690836001600160401b0316021790555060608201518160010160086101000a8154816001600160801b0302191690836001600160801b0316021790555060808201518160010160186101000a8154816001600160401b0302191690836001600160401b031602179055509050507f63d7ec44a20b176da1d60d75259d264ee67b3d8213706afa71a28f69ed8ebece8686868686866040516110e0969594939291909586526001600160801b0394851660208701529284166040860152921660608401526001600160401b0391821660808401521660a082015260c00190565b6112f26117ea565b6112fb81611f71565b5f858152600460205260408120600201906113168686611dc7565b81526020019081526020015f20819055507f9603b65b11492fec54ccc3d9feb93536f804d82e12228187ff730a253fc283ee8484848460405161135c94939291906158b1565b60405180910390a150505050565b5f8061137a848a8a8a8a8a61181c565b905061138581611a77565b6113c7898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508b9250611d46915050565b91508280156113d4575081155b156113f25760405163d27b44a960e01b815260040160405180910390fd5b6113fc8183611c5a565b50979650505050505050565b60605f6001600160a01b03841660011480159061142b575061142984610854565b155b1561144b5783604051635c93ff2f60e11b81526004016109df9190614e02565b825f0361146b576040516372dbed9760e11b815260040160405180910390fd5b826001600160401b0381111561148357611483614ffc565b6040519080825280602002602001820160405280156114ac578160200160208202803683370190505b506001600160a01b038086165f90815260036020526040812054929450911691505b6001600160a01b038216158015906114f057506001600160a01b038216600114155b80156114fb57508381105b15611555578183828151811061151357611513615780565b6001600160a01b039283166020918202929092018101919091529281165f9081526003909352604090922054909116908061154d816158e4565b9150506114ce565b6001600160a01b03821660011461158d57826115726001836158fc565b8151811061158257611582615780565b602002602001015191505b808352509250929050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218602082015246918101919091523060608201525f9081906080016040516020818303038152906040528051906020012090505f601960f81b600160f81b837f2939aeeda3ca260200c9f7b436b19e13207547ccc65cfedc857751c5ea6d91d45f1b898960405161162e92919061590f565b6040805191829003822060208301939093528101919091526060810188905260800160408051808303601f190181529082905280516020918201206001600160f81b0319958616918301919091529290931660218401526022830152604282015260620160408051601f198184030181529190528051602090910120925050505b9392505050565b6116be6117ea565b6001600160a01b03811615806116dd57506001600160a01b0381166001145b156116fd5780604051635c93ff2f60e11b81526004016109df9190614e02565b6001600160a01b038281165f9081526003602052604090205481169082161461173b5780604051638b4189ff60e01b81526004016109df9190614e02565b6001600160a01b038181165f81815260036020526040808220805487861684528284208054919096166001600160a01b0319918216179095559290915281549092169055517faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace4054276906105d4908390614e02565b6117b56117ea565b6001600160a01b0381166117de575f604051631e4fbdf760e01b81526004016109df9190614e02565b6117e781611de7565b50565b336117f3610d9d565b6001600160a01b031614610b94573360405163118cdaa760e01b81526004016109df9190614e02565b335f908152600360205260409020546060906001600160a01b031661192c575f80611845611f94565b6001600160a01b038082165f90815260036020526040902054929450909250166118845733604051634a0bfec160e01b81526004016109df9190614e02565b6001600160a01b0381165f90815260026020908152604080832085845290915290205460ff16156118cb57604051639e1dc0c560e01b8152600481018390526024016109df565b6001600160a01b0381165f908152600260209081526040808320858452825291829020805460ff1916600117905590518381527f8c8e19e7e8e193118a05465d7676e82215052d3cb150628fbf598105dc2bb6ab910160405180910390a150505b5f87900361194d57604051631fb1d3e560e31b815260040160405180910390fd5b5f8781526004602052604081209081906119656120ef565b6001600160a01b0316815260208101919091526040015f205460ff1661199e57604051631fb1d3e560e31b815260040160405180910390fd5b5f6119e4886119ad878961591e565b60a01c63ffffffff60401b1660609190911b6001600160601b031916175f908152600660205260409020546001600160a01b031690565b90505f6119ef614ce1565b6001600160a01b038316611a1957611a0f848b8b8b8b8b875f015161214a565b9092509050611a2e565b611a2883858c8c8c8c8c612398565b90925090505b5f826013811115611a4157611a416155ac565b14611a66576020810151604051631a1537eb60e31b81526109df91849160040161594e565b5193505050505b9695505050505050565b80515f5b81811015611bcb575f838281518110611a9657611a96615780565b60209081029190910181015180516040808301515f83815260058652828120835160a08101855281546001600160801b038082168352600160801b90910481169882019890985260018201546001600160401b0380821696830196909652600160401b81049098166060820152600160c01b90970490931660808701529395509193919290918190611b2890426124dd565b9150915085602001516001600160801b0316826001600160801b031614611b5157611b5161596c565b816001600160801b0316846001600160801b03161115611b7357611b7361596c565b611b7d8483615980565b600193840180546001600160401b03938416600160c01b026001600160c01b036001600160801b0394909416600160401b029390931693169290921717905550939093019250611a7b915050565b505050565b600154604051635229073f60e01b81525f916060916001600160a01b0390911690635229073f90611c0b9089908990899089906004016159b0565b5f604051808303815f875af1158015611c26573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c4d9190810190615a27565b9150915094509492505050565b81515f5b81811015611d40575f848281518110611c7957611c79615780565b602002602001015190505f815f015190508415611cf657604082015160208301517f90355d540c2980efb4c360996dfc5405ee87e812e4f3db843857547cbdb5af65918391611cc9908290615980565b604080519384526001600160801b03928316602085015291169082015260600160405180910390a1611d36565b6020808301515f8381526005909252604090912060010180546001600160801b03909216600160401b02600160401b600160c01b03199092169190911790555b5050600101611c5e565b50505050565b60015460405163468721a760e01b81525f916001600160a01b03169063468721a790611d7c9088908890889088906004016159b0565b6020604051808303815f875af1158015611d98573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dbc9190615a6a565b90505b949350505050565b60a01c63ffffffff60401b1660609190911b6001600160601b0319161790565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b604051634031b16960e11b81525f907361C5B1bE435391fDd7BC6703F3740C0d11728a8C9063806362d290611e909086906004016155e4565b5f60405180830381865af4158015611eaa573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611ed19190810190615a85565b90505f611edd82612600565b9050611eeb84518483612719565b5f958652600290960160205250506040909220929092555050565b60015f5260036020525f80516020615efc833981519152546001600160a01b031615611f455760405163dfd49ebd60e01b815260040160405180910390fd5b60015f81905260036020525f80516020615efc83398151915280546001600160a01b0319169091179055565b5f600160d81b60e0836003811115611f8b57611f8b6155ac565b901b1792915050565b5f8080366065811015611fac57505f93849350915050565b5f805f611fb9858561274a565b919450925090505f611fcc6061866158fc565b90505f611fdb8683818a615ab6565b611fe491615add565b90508460ff165f0361206a57826004811080611fff57508281115b1561201557505f998a9950975050505050505050565b845f61202c61202684838c8e615ab6565b86611598565b905061204a82828c8c87908a9261204593929190615ab6565b6127c0565b612055575f80612058565b80825b9b509b50505050505050505050509091565b5f61208061207a84838a8c615ab6565b84611598565b604080515f81526020810180835283905260ff8916918101919091526060810187905260808101869052909150819060019060a0016020604051602081039080840390855afa1580156120d5573d5f803e3d5ffd5b505050602060405103519950995050505050505050509091565b335f908152600360205260408120546001600160a01b03161561211157503390565b5f61211a611f94565b6001600160a01b038082165f908152600360205260409020549193501615905061214357919050565b5f91505090565b5f612153614ce1565b84158015906121625750600485105b1561218057604051632342609160e11b815260040160405180910390fd5b60026001600160a01b0389165f90815260018b01602052604090205460ff1660028111156121b0576121b06155ac565b036122f2575f6121c9896121c4888a61591e565b611dc7565b5f81815260028c01602052604081205491925081900361221b57600360405180604001604052808781526020018a8a90612203919061591e565b6001600160e01b03191681525093509350505061238c565b5f80612226836128a2565b915091505f6122368c8a846128cc565b90505f81601381111561224b5761224b6155ac565b1461227257604080518082019091528881525f6020820152909650945061238c9350505050565b821561229e575f60405180604001604052808a81526020015f801b81525096509650505050505061238c565b505050506122e88a82898960405180608001604052808f6001600160a01b031681526020018e81526020018a81526020018b60018111156122e1576122e16155ac565b9052612980565b925092505061238c565b60016001600160a01b0389165f90815260018b01602052604090205460ff166002811115612322576123226155ac565b03612373576001600160a01b0388165f90815260018a0160205260409020546123569088908690610100900460ff166128cc565b604080518082019091528481525f6020820152909250905061238c565b5050604080518082019091528181525f60208201526002905b97509795505050505050565b5f6123a1614ce1565b60405163c7a7b63560e01b81526001600160a01b038a169063c7a7b635906123d5908a908a908a908a908a90600401615b22565b5f60405180830381865afa92505050801561241157506040513d5f823e601f3d908101601f1916820160405261240e9190810190615b58565b60015b61242e576040516315e649e960e01b815260040160405180910390fd5b5f5b81518110156124cf575f82828151811061244c5761244c615780565b602002602001015190505f816060015190505f82608001518261246f9190615c29565b905061249a8d846020015185604001518d8d8790879261249193929190615ab6565b88518c5161214a565b90975095505f8760138111156124b2576124b26155ac565b146124c157505050505061238c565b836001019350505050612430565b505097509795505050505050565b5f8083604001516001600160401b03165f148061251e5750836040015184608001516125099190615c3c565b6001600160401b0316836001600160401b0316105b15612534575050606082015160808301516125f9565b5f846040015185608001518561254a9190615c5c565b6125549190615c90565b905084602001516001600160801b031685606001516001600160801b031610156125cf57845161258e906001600160401b03831690615cb5565b856060015161259d9190615cd8565b925084602001516001600160801b0316836001600160801b0316106125c65784602001516125c8565b825b92506125d7565b846060015192505b60408501516125e69082615cf8565b85608001516125f59190615c3c565b9150505b9250929050565b5f8061260b836129eb565b905061266d818051602091820120604080516001600160f81b03198185015273ce0042b868300000d44a59004da54a005ffdcf9f60601b60218201525f6035820152605580820193909352815180820390930183526075019052805191012090565b9150813b5f8190036127125760405163257b1f8160e11b815273ce0042b868300000d44a59004da54a005ffdcf9f90634af63f02906126b29085905f90600401615d1b565b6020604051808303815f875af11580156126ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126f29190615d3c565b6001600160a01b0316836001600160a01b0316146127125761271261596c565b5050919050565b5f6001600160a01b03821660e0846003811115612738576127386155ac565b60f087901b911b171790509392505050565b5f8080848461275a6001826158fc565b612765928290615ab6565b61276e91615d57565b60f81c925084846127806041826158fc565b61278b928290615ab6565b61279491615add565b915084846127a36021826158fc565b6127ae928290615ab6565b6127b791615add565b90509250925092565b5f843b8082036127d3575f915050611dbf565b5f866001600160a01b0316631626ba7e60e01b8787876040516024016127fb93929190615d85565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516128399190615d9e565b5f60405180830381855afa9150503d805f8114612871576040519150601f19603f3d011682016040523d82523d5f602084013e612876565b606091505b509150630b135d3f60e11b905061288c82615db9565b6001600160e01b03191614979650505050505050565b600160d81b811615155f60e083901c60ff1660038111156128c5576128c56155ac565b9050915091565b5f80841180156128ee575060018260038111156128eb576128eb6155ac565b14155b801561290c57506003826003811115612909576129096155ac565b14155b15612919575060046116af565b600183600181111561292d5761292d6155ac565b14801561294c57506002826003811115612949576129496155ac565b14155b801561296a57506003826003811115612967576129676155ac565b14155b15612977575060016116af565b505f9392505050565b5f612989614ce1565b5f806129958989612a23565b915091505f6129a5888885612bea565b90505f866040015151116129b957816129c7565b6129c7866040015183612c3f565b60408701526129d9888885848a612f65565b945094505050505b9550959350505050565b6060815160016129fb9190615c29565b82604051602001612a0d929190615df0565b6040516020818303038152906040529050919050565b612a4c6040805160808101909152805f81526020015f81525f6020820152606060409091015290565b5f82815260028401602052604081205460609160f082901c916001600160a01b031690612a788261320b565b90505f80612a868386613283565b915091505f805b8351811015612baa575f848281518110612aa957612aa9615780565b6020026020010151604001519050601c601f811115612aca57612aca6155ac565b81601f811115612adc57612adc6155ac565b10612af157612aea836158e4565b9250612ba1565b600f81601f811115612b0557612b056155ac565b03612ba1576010858381518110612b1e57612b1e615780565b602002602001015160400190601f811115612b3b57612b3b6155ac565b9081601f811115612b4e57612b4e6155ac565b9052505f54604051612b6c916001600160a01b031690602001614e02565b60405160208183030381529060405280519060200120848381518110612b9457612b94615780565b6020026020010181815250505b50600101612a8d565b50612bc08383612bb986613473565b5f8c6135b6565b875f8211612bce5787612bd9565b612bd984848461378c565b975097505050505050509250929050565b612c0c60405180606001604052805f81526020015f8152602001606081525090565b5f612c1683613972565b9050612c2d85856004848560200151515f88613afe565b505f8152602081019290925250919050565b606082515f03612c50575080610887565b81515f03612c5f575081610887565b81518351612c6d9190615c29565b6001600160401b03811115612c8457612c84614ffc565b604051908082528060200260200182016040528015612ccd57816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181612ca25790505b5083519091505f5b81811015612dc357848181518110612cef57612cef615780565b60200260200101515f0151838281518110612d0c57612d0c615780565b60200260200101515f018181525050848181518110612d2d57612d2d615780565b602002602001015160200151838281518110612d4b57612d4b615780565b6020026020010151602001906001600160801b031690816001600160801b031681525050848181518110612d8157612d81615780565b602002602001015160400151838281518110612d9f57612d9f615780565b60209081029190910101516001600160801b03909116604090910152600101612cd5565b505f5b8351811015612f50575f80612df787878581518110612de757612de7615780565b60200260200101515f0151613ca9565b915091508015612e5a57858381518110612e1357612e13615780565b602002602001015160400151858381518110612e3157612e31615780565b6020026020010151604001818151612e499190615cd8565b6001600160801b0316905250612f46565b858381518110612e6c57612e6c615780565b60200260200101515f0151858581518110612e8957612e89615780565b60200260200101515f018181525050858381518110612eaa57612eaa615780565b602002602001015160200151858581518110612ec857612ec8615780565b6020026020010151602001906001600160801b031690816001600160801b031681525050858381518110612efe57612efe615780565b602002602001015160400151858581518110612f1c57612f1c615780565b60209081029190910101516001600160801b0390911660409091015283612f42816158e4565b9450505b5050600101612dc6565b508151811015612f5e578082525b5092915050565b5f612f6e614ce1565b6020850151601081601f811115612f8757612f876155ac565b10156130e1575f81601f811115612fa057612fa06155ac565b03612fc55750506040805180820182529083015181525f6020820181905291506129e1565b600581601f811115612fd957612fd96155ac565b03612ff557612feb8888888888613cfe565b92509250506129e1565b600181601f811115613009576130096155ac565b0361301b57612feb8888888888613e19565b600281601f81111561302f5761302f6155ac565b0361304157612feb8888888888613ee9565b600381601f811115613055576130556155ac565b0361306757612feb8888888888613f71565b600681601f81111561307b5761307b6155ac565b0361308d57612feb8888888888614019565b600781601f8111156130a1576130a16155ac565b036130b357612feb8888888888614110565b600881601f8111156130c7576130c76155ac565b146130d4576130d461596c565b612feb888888888861418f565b601281601f8111156130f5576130f56155ac565b11613127576131068888888861430a565b6040805180820182529086015181525f602082015290935091506129e19050565b601481601f81111561313b5761313b6155ac565b1161314c5761310688888888614411565b601581601f811115613160576131606155ac565b036131715761310688888888614493565b601681601f811115613185576131856155ac565b0361319757612feb888888888861456e565b601c81601f8111156131ab576131ab6155ac565b036131bd57612feb8888888888614653565b601d81601f8111156131d1576131d16155ac565b036131e057612feb868561468d565b601e81601f8111156131f4576131f46155ac565b146132015761320161596c565b612feb86856146d8565b6060813b6001811161321f5761321f61596c565b60015f61322c82846158fc565b9050806001600160401b0381111561324657613246614ffc565b6040519080825280601f01601f191660200182016040528015613270576020820181803683370190505b509350808260208601873c505050919050565b606080826001600160401b0381111561329e5761329e614ffc565b6040519080825280602002602001820160405280156132d757816020015b6132c4614cf8565b8152602001906001900390816132bc5790505b509150826001600160401b038111156132f2576132f2614ffc565b60405190808252806020026020018201604052801561331b578160200160208202803683370190505b5090505f60208161332d600287615e46565b613338906020615c29565b90505f5b8681101561346857878301519350613355600284615c29565b92505f8460f01c90505f87838151811061337157613371615780565b6020908102919091010151600883901c60ff1681529050600582901c60071660068111156133a1576133a16155ac565b816020019060068111156133b7576133b76155ac565b908160068111156133ca576133ca6155ac565b905250601f828116908111156133e2576133e26155ac565b8160400190601f8111156133f8576133f86155ac565b9081601f81111561340b5761340b6155ac565b90525060108160400151601f811115613426576134266155ac565b1061345e5789840151955061343c602085615c29565b93508587848151811061345157613451615780565b6020026020010181815250505b505060010161333c565b505050509250929050565b8051606090806134855761348561596c565b806001600160401b0381111561349d5761349d614ffc565b6040519080825280602002602001820160405280156134ef57816020015b6134dc60405180606001604052805f81526020015f81526020015f81525090565b8152602001906001900390816134bb5790505b5091505f19825f8151811061350657613506615780565b60209081029190910101515260015b81811015612712575f1983828151811061353157613531615780565b60200260200101515f0181815250505f8385838151811061355457613554615780565b60200260200101515f015160ff168151811061357257613572615780565b602002602001015190505f19815f01510361358b578181525b613596826001615c29565b6020820181905281516135a8916158fc565b604090910152600101613515565b5f8583815181106135c9576135c9615780565b602002602001015190508060200151825f019060068111156135ed576135ed6155ac565b90816006811115613600576136006155ac565b90525060408101516020830190601f81111561361e5761361e6155ac565b9081601f811115613631576136316155ac565b8152505084838151811061364757613647615780565b602002602001015182604001818152505083838151811061366a5761366a615780565b6020026020010151604001515f036136825750613785565b5f84848151811061369557613695615780565b60200260200101515f015190505f8585815181106136b5576136b5615780565b6020026020010151604001519050806001600160401b038111156136db576136db614ffc565b60405190808252806020026020018201604052801561373557816020015b6137226040805160808101909152805f81526020015f81525f6020820152606060409091015290565b8152602001906001900390816136f95790505b5060608501525f5b81811015613780576137788989896137558588615c29565b8960600151868151811061376b5761376b615780565b60200260200101516135b6565b60010161373d565b505050505b5050505050565b8251606090826001600160401b038111156137a9576137a9614ffc565b6040519080825280602002602001820160405280156137f257816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816137c75790505b5091505f805b8281101561395c57601c87828151811061381457613814615780565b602002602001015160400151601f811115613831576138316155ac565b1061394c575f86828151811061384957613849615780565b602002602001015190505f61385e8683613ca9565b915050801561386e57505061394c565b8186858151811061388157613881615780565b602090810291909101810151919091525f83815260058252604090819020815160a08101835281546001600160801b038082168352600160801b9091048116948201949094526001909101546001600160401b0380821693830193909352600160401b81049093166060820152600160c01b90920416608082015261390690426124dd565b5086858151811061391957613919615780565b6020026020010151602001816001600160801b03166001600160801b0316815250508380613946906158e4565b94505050505b613955816158e4565b90506137f8565b5083811015613969578083525b50509392505050565b61397a614d20565b60018260200151601f811115613992576139926155ac565b101580156139b6575060038260200151601f8111156139b3576139b36155ac565b11155b156139f5575f826060015151116139cf576139cf61596c565b61088782606001515f815181106139e8576139e8615780565b6020026020010151613972565b815181906006811115613a0a57613a0a6155ac565b90816006811115613a1d57613a1d6155ac565b90525060608201515115613af9575f600483516006811115613a4157613a416155ac565b14613a5157826060015151613a54565b60015b9050806001600160401b03811115613a6e57613a6e614ffc565b604051908082528060200260200182016040528015613aa757816020015b613a94614d20565b815260200190600190039081613a8c5790505b5060208301525f5b8181101561271257613ad0846060015182815181106139e8576139e8615780565b83602001518281518110613ae657613ae6615780565b6020908102919091010152600101613aaf565b919050565b826001600160401b03811115613b1657613b16614ffc565b604051908082528060200260200182016040528015613b6957816020015b613b5660405180606001604052805f81526020015f8152602001606081525090565b815260200190600190039081613b345790505b5060408201525f8215613b9f57613b9c85602001515f81518110613b8f57613b8f615780565b6020026020010151614715565b90505b5f805b85811015613c9d5784613bcb57613bc887602001518281518110613b8f57613b8f615780565b92505b613c2a8a8a613bdd8d8d8d888a6147fb565b8a6020015189613bed5785613bef565b5f5b81518110613bff57613bff615780565b602002602001015188604001518681518110613c1d57613c1d615780565b6020026020010151614838565b5f84604001518281518110613c4157613c41615780565b602002602001015160200151905083613c6457613c5f816020615c29565b613c66565b805b85602001818151613c779190615c29565b90525083613c86576020613c88565b805b613c929084615c29565b925050600101613ba2565b50505050505050505050565b81515f908190815b81811015613cf15784868281518110613ccc57613ccc615780565b60200260200101515f015103613ce9579250600191506125f99050565b600101613cb1565b505f958695509350505050565b5f613d07614ce1565b60408084015182528401515160608601515114613d2757600a91506129e1565b5f5b856060015151811015613e0b57613dc4888888606001518481518110613d5157613d51615780565b602002602001015188604001518581518110613d6f57613d6f615780565b602002602001015160405180608001604052808a5f01516001600160a01b031681526020018a602001518152602001885f015181526020018a606001516001811115613dbd57613dbd6155ac565b9052612f65565b90935091505f836013811115613ddc57613ddc6155ac565b14613e035750604080518082018252908401518152602091820151918101919091526129e1565b600101613d29565b505f91509550959350505050565b5f613e22614ce1565b604083015181525f5b856060015151811015613e0b57613ea2888888606001518481518110613e5357613e53615780565b60200260200101518860405180608001604052808a5f01516001600160a01b031681526020018a602001518152602001885f015181526020018a606001516001811115613dbd57613dbd6155ac565b90935091505f836013811115613eba57613eba6155ac565b14613ee15750604080518082018252908401518152602091820151918101919091526129e1565b600101613e2b565b5f613ef2614ce1565b604083015181525f5b856060015151811015613f4e57613f23888888606001518481518110613e5357613e53615780565b90935091505f836013811115613f3b57613f3b6155ac565b03613f4657506129e1565b600101613efb565b50506040805180820182529201518252505f602082015260059590945092505050565b5f613f7a614ce1565b5f5b856060015151811015613ff657613fb3888888606001518481518110613fa457613fa4615780565b60200260200101518888612f65565b5092505f836013811115613fc957613fc96155ac565b03613fee5750506040805180820182529083015181525f6020820152600691506129e1565b600101613f7c565b50506040805180820182529201518252505f602082018190529590945092505050565b5f614022614ce1565b604083015181526060850151515f5b818110156140ec576140c0898989606001515f8151811061405457614054615780565b60200260200101518960400151858151811061407257614072615780565b602002602001015160405180608001604052808b5f01516001600160a01b031681526020018b602001518152602001895f015181526020018b606001516001811115613dbd57613dbd6155ac565b90945092505f8460138111156140d8576140d86155ac565b036140e45750506129e1565b600101614031565b5050604080518082018252930151835250505f6020820152600c9590945092505050565b5f614119614ce1565b604083015181525f5b846040015151811015613e0b5761414a888888606001515f81518110613d5157613d51615780565b90935091505f836013811115614162576141626155ac565b146141875750506040805180820182529083015181525f6020820152600b91506129e1565b600101614122565b5f614198614ce1565b60408084015182528401515115806141b95750846060015151846040015151115b156141c757600d91506129e1565b5f805b8560400151518110156142fb575f805b8860600151518110156142c0576001811b84165f036142b0575f8061427c8d8d8d60600151868151811061421057614210615780565b60200260200101518d60400151898151811061422e5761422e615780565b602002602001015160405180608001604052808f5f01516001600160a01b031681526020018f6020015181526020018d5f015181526020018f606001516001811115613dbd57613dbd6155ac565b90925090505f826013811115614294576142946155ac565b036142ad57955050600180821b949094179391506142c0565b50505b6142b9816158e4565b90506141da565b50806142ea5750506040805180820182529085015181525f6020820152600d935091506129e19050565b506142f4816158e4565b90506141ca565b505f9250509550959350505050565b602082015160408301515f919082601083601f81111561432c5761432c6155ac565b146143445761433f8888875f01516149d5565b61436e565b6143578888875f01518860200151614a0c565b60405161436592919061590f565b60405180910390205b9050601083601f811115614384576143846155ac565b1480156143915750818114155b156143a25760079350505050611dbf565b601183601f8111156143b6576143b66155ac565b1480156143c35750818111155b156143d45760089350505050611dbf565b601283601f8111156143e8576143e86155ac565b1480156143f55750818110155b156144065760099350505050611dbf565b5f9350505050611dbf565b6020820151604083015182515f929190839061443090899089906149d5565b9050601383601f811115614446576144466155ac565b1480156144535750818113155b156144645760089350505050611dbf565b601483601f811115614478576144786155ac565b1480156143f557508181126144065760099350505050611dbf565b60408201515f90816001855160068111156144b0576144b06155ac565b149050365f6144fc8989856144c65760206144c8565b5f5b89516144d79160ff1690615c29565b866144e35760206144e5565b5f5b60ff168a602001516144f791906158fc565b614a0c565b909250905060f084901c81811061451b57600e95505050505050611dbf565b6001600160881b0319601086901b8116608887901b82165f61453f8686818a615ab6565b61454891615add565b9050818382161461455a57600f61455c565b5f5b9e9d5050505050505050505050505050565b5f614577614ce1565b5f856040015160601c90505f86604001515f1c60a01b90505f80836001600160a01b031663b0acb980885f015189602001518e8e8c606001518e5f01518f602001518b6040518963ffffffff1660e01b81526004016145dd989796959493929190615e5d565b6040805180830381865afa1580156145f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061461b9190615ebc565b915091508161462b57601061462d565b5f5b604080518082018252980151885260208801919091529a95995094975050505050505050565b5f61465c614ce1565b5f61466b8888875f01516149d5565b5f1c905061467e81878660400151614a28565b92509250509550959350505050565b5f614696614ce1565b6146a98360200151858560400151614a28565b90925090505f8260138111156146c1576146c16155ac565b146146cd5760136146cf565b5f5b91509250929050565b5f6146e1614ce1565b6146f16001858560400151614a28565b90925090505f826013811115614709576147096155ac565b146146cd5760126146cf565b80515f90600181600681111561472d5761472d6155ac565b0361473b5750600192915050565b600281600681111561474f5761474f6155ac565b148061476c5750600481600681111561476a5761476a6155ac565b145b8061478857506005816006811115614786576147866155ac565b145b806147a4575060068160068111156147a2576147a26155ac565b145b156147b157505f92915050565b6020830151515f5b818110156147f0576147da85602001518281518110613b8f57613b8f615780565b6147e857505f949350505050565b6001016147b9565b506001949350505050565b5f806148078486615c29565b9050821561481657905061482f565b6148218787836149d5565b61482b9086615c29565b9150505b95945050505050565b8151600181600681111561484e5761484e6155ac565b0361485e576020828101526149cb565b6002816006811115614872576148726155ac565b0361489f5761488a6148858787876149d5565b614b5a565b614895906020615c29565b60208301526149cb565b60038160068111156148b3576148b36155ac565b036148d1576148cc868686868760200151515f88613afe565b6149cb565b60048160068111156148e5576148e56155ac565b036149295761490e86866148fa876020615c29565b866149068b8b8b6149d5565b600188613afe565b6020826020018181516149219190615c29565b9052506149cb565b600581600681111561493d5761493d6155ac565b148061495a57506006816006811115614958576149586155ac565b145b156149cb576149ac86866005846006811115614978576149786155ac565b14614983575f614986565b60045b60ff16614994886020615c29565b61499e9190615c29565b868760200151515f88613afe565b6149ba6148858787876149d5565b6149c5906020615c29565b60208301525b5091909152505050565b5f826149e2836020615c29565b1115614a0157604051631d098e2d60e21b815260040160405180910390fd5b509190910135919050565b365f858486614a1b8683615c29565b92611c4d93929190615ab6565b5f614a31614ce1565b5f80614a41858760400151613ca9565b9150915080614a5257614a5261596c565b848281518110614a6457614a64615780565b6020026020010151602001516001600160801b0316858381518110614a8b57614a8b615780565b6020026020010151604001516001600160801b031688614aab9190615c29565b1115614aef5760116040518060400160405280878152602001878581518110614ad657614ad6615780565b60200260200101515f0151815250935093505050614b52565b614af885614b88565b945086858381518110614b0d57614b0d615780565b6020026020010151604001818151614b259190615cd8565b6001600160801b031690525050604080518082019091528481525f6020820181905293509150614b529050565b935093915050565b5f60206001614b698483615c29565b614b7391906158fc565b614b7d9190615ee8565b610887906020615e46565b8051606090806001600160401b03811115614ba557614ba5614ffc565b604051908082528060200260200182016040528015614bee57816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181614bc35790505b5091505f5b8181101561271257838181518110614c0d57614c0d615780565b60200260200101515f0151838281518110614c2a57614c2a615780565b60200260200101515f018181525050838181518110614c4b57614c4b615780565b602002602001015160200151838281518110614c6957614c69615780565b6020026020010151602001906001600160801b031690816001600160801b031681525050838181518110614c9f57614c9f615780565b602002602001015160400151838281518110614cbd57614cbd615780565b60209081029190910101516001600160801b03909116604090910152600101614bf3565b60408051808201909152606081525f602082015290565b60408051608081019091525f808252602082019081526020015f5b8152602001606081525090565b60408051808201909152805f614d13565b6001600160a01b03811681146117e7575f80fd5b5f8060408385031215614d56575f80fd5b823591506020830135614d6881614d31565b809150509250929050565b5f60208284031215614d83575f80fd5b81356116af81614d31565b80356001600160e01b031981168114613af9575f80fd5b5f805f60608486031215614db7575f80fd5b8335614dc281614d31565b9250614dd060208501614d8e565b91506040840135614de081614d31565b809150509250925092565b5f60208284031215614dfb575f80fd5b5035919050565b6001600160a01b0391909116815260200190565b5f8083601f840112614e26575f80fd5b5081356001600160401b03811115614e3c575f80fd5b6020830191508360208285010111156125f9575f80fd5b600281106117e7575f80fd5b80151581146117e7575f80fd5b5f805f805f805f60c0888a031215614e82575f80fd5b8735614e8d81614d31565b96506020880135955060408801356001600160401b03811115614eae575f80fd5b614eba8a828b01614e16565b9096509450506060880135614ece81614e53565b92506080880135915060a0880135614ee581614e5f565b8091505092959891949750929550565b5f5b83811015614f0f578181015183820152602001614ef7565b50505f910152565b5f8151808452614f2e816020860160208601614ef5565b601f01601f19169290920160200192915050565b8215158152604060208201525f611dbf6040830184614f17565b5f805f805f60808688031215614f70575f80fd5b8535614f7b81614d31565b94506020860135935060408601356001600160401b03811115614f9c575f80fd5b614fa888828901614e16565b9094509250506060860135614fbc81614e53565b809150509295509295909350565b5f805f60608486031215614fdc575f80fd5b833592506020840135614fee81614d31565b91506127b760408501614d8e565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b038111828210171561503257615032614ffc565b60405290565b60405160a081016001600160401b038111828210171561503257615032614ffc565b604051601f8201601f191681016001600160401b038111828210171561508257615082614ffc565b604052919050565b5f6001600160401b038211156150a2576150a2614ffc565b5060051b60200190565b803560208110613af9575f80fd5b5f6001600160401b038211156150d2576150d2614ffc565b50601f01601f191660200190565b5f82601f8301126150ef575f80fd5b81356151026150fd826150ba565b61505a565b818152846020838601011115615116575f80fd5b816020850160208301375f918101602001919091529392505050565b803560048110613af9575f80fd5b5f805f805f60a08688031215615154575f80fd5b853594506151656020870135614d31565b6020860135935061517860408701614d8e565b92506001600160401b0360608701351115615191575f80fd5b6060860135860187601f8201126151a6575f80fd5b6151b36150fd823561508a565b81358082526020808301929160051b8401018a8111156151d1575f80fd5b602084015b81811015615293576001600160401b03813511156151f2575f80fd5b803585016080818e03601f19011215615209575f80fd5b615211615010565b602082013560ff811614615223575f80fd5b60208201358152600760408301351061523a575f80fd5b60408201356020820152615250606083016150ac565b60408201526001600160401b036080830135111561526c575f80fd5b61527f8e602060808501358501016150e0565b6060820152855250602093840193016151d6565b50508094505050506152a760808701615132565b90509295509295909350565b5f805f606084860312156152c5575f80fd5b8335925060208401356152d781614d31565b91506127b760408501615132565b5f80604083850312156152f6575f80fd5b823561530181614d31565b946020939093013593505050565b5f8083601f84011261531f575f80fd5b5081356001600160401b03811115615335575f80fd5b6020830191508360208260051b85010111156125f9575f80fd5b5f805f805f60608688031215615363575f80fd5b853561536e81614d31565b945060208601356001600160401b0380821115615389575f80fd5b61539589838a0161530f565b909650945060408801359150808211156153ad575f80fd5b506153ba8882890161530f565b969995985093965092949392505050565b5f602082840312156153db575f80fd5b81356001600160401b038111156153f0575f80fd5b611dbf848285016150e0565b80356001600160801b0381168114613af9575f80fd5b80356001600160401b0381168114613af9575f80fd5b5f805f805f8060c0878903121561543d575f80fd5b8635955061544d602088016153fc565b945061545b604088016153fc565b9350615469606088016153fc565b925061547760808801615412565b915061548560a08801615412565b90509295509295509295565b5f805f80608085870312156154a4575f80fd5b8435935060208501356154b681614d31565b92506154c460408601614d8e565b91506154d260608601615132565b905092959194509250565b604080825283519082018190525f906020906060840190828701845b8281101561551e5781516001600160a01b0316845292840192908401906001016154f9565b5050506001600160a01b039490941692019190915250919050565b5f805f6040848603121561554b575f80fd5b83356001600160401b03811115615560575f80fd5b61556c86828701614e16565b909790965060209590950135949350505050565b5f8060408385031215615591575f80fd5b823561559c81614d31565b91506020830135614d6881614d31565b634e487b7160e01b5f52602160045260245ffd5b600781106155d0576155d06155ac565b9052565b602081106155d0576155d06155ac565b5f6020808301818452808551808352604092508286019150828160051b8701018488015f5b8381101561567357603f198984030185528151608060ff8251168552888201516156358a8701826155c0565b5087820151615646898701826155d4565b5060609182015191850181905261565f85820183614f17565b968901969450505090860190600101615609565b509098975050505050505050565b600481106155d0576155d06155ac565b5f60a08201878352602060018060a01b03881681850152604063ffffffff60e01b881681860152606060a08187015283885180865260c08801915060c08160051b8901019550848a015f5b828110156157455760bf198a89030184528151608060ff8251168a52888201516157088a8c01826155c0565b5087820151615719898c01826155d4565b5086820151915080878b0152615731818b0183614f17565b9950505092860192908601906001016156dc565b5050505050505080915050611a6d6080830184615681565b8381526001600160a01b038316602082015260608101611dbf6040830184615681565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156157a4575f80fd5b81356116af81614e5f565b634e487b7160e01b5f52601160045260245ffd5b5f61ffff8083168181036157d9576157d96157af565b6001019392505050565b6001600160a01b0386168152606060208083018290529082018590525f906001600160fb1b03861115615814575f80fd5b8560051b80886080860137830183810360809081016040860152810185905285905f9060a0015b8682101561586457823561584e81614e5f565b151581529183019160019190910190830161583b565b9a9950505050505050505050565b5f805f60608486031215615884575f80fd5b835161588f81614d31565b60208501519093506158a081614d31565b6040850151909250614de081614d31565b8481526001600160a01b03841660208201526001600160e01b0319831660408201526080810161482f6060830184615681565b5f600182016158f5576158f56157af565b5060010190565b81810381811115610887576108876157af565b818382375f9101908152919050565b6001600160e01b031981358181169160048510156159465780818660040360031b1b83161692505b505092915050565b6040810160148410615962576159626155ac565b9281526020015290565b634e487b7160e01b5f52600160045260245ffd5b6001600160801b03828116828216039080821115612f5e57612f5e6157af565b600281106155d0576155d06155ac565b60018060a01b0385168152836020820152608060408201525f6159d66080830185614f17565b905061482f60608301846159a0565b5f82601f8301126159f4575f80fd5b8151615a026150fd826150ba565b818152846020838601011115615a16575f80fd5b611dbf826020830160208701614ef5565b5f8060408385031215615a38575f80fd5b8251615a4381614e5f565b60208401519092506001600160401b03811115615a5e575f80fd5b6125f5858286016159e5565b5f60208284031215615a7a575f80fd5b81516116af81614e5f565b5f60208284031215615a95575f80fd5b81516001600160401b03811115615aaa575f80fd5b611dbf848285016159e5565b5f8085851115615ac4575f80fd5b83861115615ad0575f80fd5b5050820193919092039150565b80356020831015610887575f19602084900360031b1b1692915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b0386168152846020820152608060408201525f615b49608083018587615afa565b9050611a6d60608301846159a0565b5f6020808385031215615b69575f80fd5b82516001600160401b03811115615b7e575f80fd5b8301601f81018513615b8e575f80fd5b8051615b9c6150fd8261508a565b81815260a09182028301840191848201919088841115615bba575f80fd5b938501935b838510156113fc5780858a031215615bd6575f8081fd5b615bde615038565b8551615be981614e53565b815285870151615bf881614d31565b8188015260408681015190820152606080870151908201526080808701519082015283529384019391850191615bbf565b80820180821115610887576108876157af565b6001600160401b03818116838216019080821115612f5e57612f5e6157af565b6001600160401b03828116828216039080821115612f5e57612f5e6157af565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b0380841680615ca957615ca9615c7c565b92169190910492915050565b6001600160801b03818116838216028082169190828114615946576159466157af565b6001600160801b03818116838216019080821115612f5e57612f5e6157af565b6001600160401b03818116838216028082169190828114615946576159466157af565b604081525f615d2d6040830185614f17565b90508260208301529392505050565b5f60208284031215615d4c575f80fd5b81516116af81614d31565b6001600160f81b031981358181169160018510156159465760019490940360031b84901b1690921692915050565b838152604060208201525f611dbc604083018486615afa565b5f8251615daf818460208701614ef5565b9190910192915050565b805160208201516001600160e01b03198082169291906004831015615de85780818460040360031b1b83161693505b505050919050565b606360f81b815260e083901b6001600160e01b03191660018201526880600e6000396000f360b81b60058201525f600e82018190528251615e3881600f850160208701614ef5565b91909101600f019392505050565b8082028115828204841417610887576108876157af565b60018060a01b038916815287602082015260e060408201525f615e8460e08301888a615afa565b9050615e9360608301876159a0565b608082019490945260a08101929092526001600160a01b03191660c09091015295945050505050565b5f8060408385031215615ecd575f80fd5b8251615ed881614e5f565b6020939093015192949293505050565b5f82615ef657615ef6615c7c565b50049056fea15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054ca2646970667358221220effee86583e9a9dfea71c1020808e6a7f1ab205668c8679fce5a2d2485ca407b64736f6c63430008150033000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"; From 0fc02ae4a164bb62ad5b3524bf4b48fdb32a0703 Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Fri, 15 Dec 2023 17:07:56 +0100 Subject: [PATCH 62/82] bump package minor --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 411e19a1..dd85000c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.4.2", + "version": "3.5.0", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", From 0a547053bf4f3c6b929f7f467b8f6f53ecd9d44f Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Mon, 8 Jan 2024 17:18:48 +0100 Subject: [PATCH 63/82] add integrity check errors to Roles ABI --- sdk/abi/RolesV2Integrity.json | 113 ++++++++++++++++++++++++++++++++++ sdk/contracts.ts | 7 ++- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 sdk/abi/RolesV2Integrity.json diff --git a/sdk/abi/RolesV2Integrity.json b/sdk/abi/RolesV2Integrity.json new file mode 100644 index 00000000..0de4fe88 --- /dev/null +++ b/sdk/abi/RolesV2Integrity.json @@ -0,0 +1,113 @@ +[ + { + "inputs": [], + "name": "NotBFS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "UnsuitableChildCount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "UnsuitableChildTypeTree", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "UnsuitableCompValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "UnsuitableParameterType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "UnsuitableParent", + "type": "error" + }, + { + "inputs": [], + "name": "UnsuitableRootNode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "UnsupportedOperator", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "parent", + "type": "uint8" + }, + { + "internalType": "enum ParameterType", + "name": "paramType", + "type": "ParameterType" + }, + { + "internalType": "enum Operator", + "name": "operator", + "type": "Operator" + }, + { + "internalType": "bytes", + "name": "compValue", + "type": "bytes" + } + ], + "internalType": "struct ConditionFlat[]", + "name": "conditions", + "type": "tuple[]" + } + ], + "name": "enforce", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] \ No newline at end of file diff --git a/sdk/contracts.ts b/sdk/contracts.ts index d0389c26..4f3d3a54 100644 --- a/sdk/contracts.ts +++ b/sdk/contracts.ts @@ -17,6 +17,7 @@ import RealityErc20Abi from "./abi/RealityErc20.json"; import RealityEthAbi from "./abi/RealityEth.json"; import RolesV1Abi from "./abi/RolesV1.json"; import RolesV2Abi from "./abi/RolesV2.json"; +import RolesV2IntegrityAbi from "./abi/RolesV2Integrity.json"; import ScopeGuardAbi from "./abi/ScopeGuard.json"; import TellorAbi from "./abi/Tellor.json"; import { KnownContracts } from "./factory/types"; @@ -247,7 +248,11 @@ export const ContractAbis: Record = { [KnownContracts.REALITY_ETH]: RealityEthAbi, [KnownContracts.ROLES]: RolesV1Abi, [KnownContracts.ROLES_V1]: RolesV1Abi, - [KnownContracts.ROLES_V2]: RolesV2Abi, + [KnownContracts.ROLES_V2]: [ + ...RolesV2Abi, + // we add the custom errors from the Integrity lib so integrity check errors can be decoded + RolesV2IntegrityAbi.filter((fragment) => fragment.type === "error"), + ], [KnownContracts.SCOPE_GUARD]: ScopeGuardAbi, [KnownContracts.TELLOR]: TellorAbi, [KnownContracts.MULTISEND_ENCODER]: MultisendEncoderAbi, From 5be6e212e8dfd6244210b60765d98638add4b809 Mon Sep 17 00:00:00 2001 From: Jan-Felix Date: Mon, 8 Jan 2024 17:32:47 +0100 Subject: [PATCH 64/82] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dd85000c..85f8d911 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/zodiac", - "version": "3.5.0", + "version": "3.5.1", "description": "Zodiac is a composable design philosophy and collection of standards for building DAO ecosystem tooling.", "author": "Auryn Macmillan ", "license": "LGPL-3.0+", From 72424d9f614dba8d52df84bfda7c4a5c226fbaf6 Mon Sep 17 00:00:00 2001 From: Colin Spence Date: Mon, 8 Jan 2024 10:00:22 -0700 Subject: [PATCH 65/82] Adds Badge assets --- branding/Badge-black/white.png | Bin 0 -> 16154 bytes branding/Badge-black/white.svg | 63 ++++++++++++++++ branding/Badge-gradient-dark.png | Bin 0 -> 31053 bytes branding/Badge-gradient-dark.svg | 70 +++++++++++++++++ branding/Badge-gradient-light.png | Bin 0 -> 27735 bytes branding/Badge-gradient-light.svg | 71 ++++++++++++++++++ branding/Badge-title-black/white.png | Bin 0 -> 24542 bytes branding/Badge-title-black/white.svg | 77 +++++++++++++++++++ branding/Badge-title-gradient-dark.png | Bin 0 -> 166591 bytes branding/Badge-title-gradient-dark.svg | 96 ++++++++++++++++++++++++ branding/Badge-title-gradient-light.png | Bin 0 -> 145056 bytes branding/Badge-title-gradient-light.svg | 85 +++++++++++++++++++++ branding/Badge-title-white/black.png | Bin 0 -> 25961 bytes branding/Badge-title-white/black.svg | 77 +++++++++++++++++++ branding/Badge-white/black.png | Bin 0 -> 17034 bytes branding/Badge-white/black.svg | 63 ++++++++++++++++ 16 files changed, 602 insertions(+) create mode 100644 branding/Badge-black/white.png create mode 100644 branding/Badge-black/white.svg create mode 100644 branding/Badge-gradient-dark.png create mode 100644 branding/Badge-gradient-dark.svg create mode 100644 branding/Badge-gradient-light.png create mode 100644 branding/Badge-gradient-light.svg create mode 100644 branding/Badge-title-black/white.png create mode 100644 branding/Badge-title-black/white.svg create mode 100644 branding/Badge-title-gradient-dark.png create mode 100644 branding/Badge-title-gradient-dark.svg create mode 100644 branding/Badge-title-gradient-light.png create mode 100644 branding/Badge-title-gradient-light.svg create mode 100644 branding/Badge-title-white/black.png create mode 100644 branding/Badge-title-white/black.svg create mode 100644 branding/Badge-white/black.png create mode 100644 branding/Badge-white/black.svg diff --git a/branding/Badge-black/white.png b/branding/Badge-black/white.png new file mode 100644 index 0000000000000000000000000000000000000000..7e58d49e71c154f24cba081d53a832e9cdef86ac GIT binary patch literal 16154 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branding/Badge-gradient-dark.png b/branding/Badge-gradient-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..61ae95ce51a3d6015f54f96032d9ca7804489cda GIT binary patch literal 31053 zcmV)MK)An&P)_0o@HKNP}$JY>ti!#z-;|Cld{z{w6vZL6b~o#NUjX{6sT} z8O2HBBtg(<7Eps4K$95TW>FC7Ms|9kdaqup>Q&XNx4(Pm{LlHmbI-eV-%`~L4d|y$ zz2&~U{?B**-+F}jh5SNZ0pf^X$fD$mY&KgF^J7AIn;hY0T_M(aLS%*T=MSY8-+q6twnh9xe!hWx zMK(QF74@s-RR0d~(gkiiQNWgu@>@v}+p;BB8W%r@@^c5|OS17RB&WSxYP0KF^Vn!{ z6A8~vChDpFzH%bdQ%&}C*J7zeUB1R&FP2Ky<-ic>{+_BMJl_|-=i=)>qz1~-PL4&w%j!`QcPwtmGsbHCDoUy0;uYrE72(b@6db4b>s_AIF2tr^6?+} z88!i$<>x-`xBLra<9F)r*8yT60C` zqChQq_3h#nF0W`HL;Fftd|Y%0-gr+>wR`32d~#s0oLRo281L(?Dv&vzqtOG9sec;4 zxO^DNX>9KGz7=+qwXozMJaz_+N}Pt_G&igFvZbpA@*J9tz0# zSV5A2?|ZbZ2DSt7K$=u@gG-iqz7t7$95p;lrYh z(Uu-sUg$n$!(8vW)8^b{vhGMg$d7$Z2|NQHt&KGua20Yrhv@|Nqcti1?=c8j>q?Lc z4MrLi4h;<2#vuyA05?Dehyia50^hG|(9_^h`%ypew8~erg6BK*eQ~CgnAw->I{5hE zY+OtWUrEmnz0-8Uo<2n30 z!Gn&qw=gq^{7?_7;&d@F{?NgpxkK~a<$NXH{0_b{0R6HBawhY1}$ zD^}0L{&HPk5d@mP4IrfWu6a$MbTrRZ+86*)pE8g=I*9LUl3Is4Rf>|hEfflrp#IgP(&rJ8t zNKiMwqc3kjzbt_)BW~Bp2mF6T3jk+MJ!`t}Rj-|nB@-TVRP8MwuY%#9r1=8PMpLz* z&n<1NwXg=825GQgdT)bV4;Eh!7PV8)S6{O>*Paif%>xa~+E|0qbp%rx`2oBf+B+hD zs}C&%Q5Rp&C~CIx%^-F3x%1AA*HfC2fm!FDlScN~9j1&aM_GS@0K{AsqJiirZr~{@p}iPH z51ha)CqlGBX?b$N2?K6z1k!Jq6O&tx28KdsFf+ITU#8=G%*7qeyVW32=R~KW$bE6T zoZS7;#L$tQGpzu9`^(A8@v;CiXhc=y0pJfueXjw0wgm9`({4IlSD@3=wJ#VL#@E{b zDg$2jP_Vbc#Z#BlH)&N3Mu#x23_i_8nMNoUAoTA@!_$7TtuU@Sr65Vm>th7o3U=S& zx4t?z{8}5IhIY85v9@Z?NU4c%1c>0zhr^jP79|- zPs#Uhdc%=;rmsd*x=$9p6BtN%8$5IsF*6`$PHVgs2CT{;^odqzYT`6f1OkoAK4hjM zOie6To&=#M!_u)-+za@#A4K!qz*uu_?rhFeYhwba;}ccVUJ%m8KGTnY%DC!`ndYc* ztu?x@P6PDXQJxk2N3$aT*xr2iQ}-VnE#<3;sCzDt{E;8!s-F`tL3v36xs?`nyED~+ z^WJE=r1ccA zJ=VzDhpde}+Lx2tbs#gae#M+1!08k88bZ>BS~$VL3EYA@x=6G`(c$3S8acbZP9fOH z(|&F>mB=W$N7|T`J`Dn&uHVxfde`=&1G^ua9IjWrsHmZg5XP^6scGk!c!|mDvI)4< z{$50QBziVpFgb9+FHIz}!xg+&E-B)FIwD6(SdhkYh#w=+fDe5kg1~}rybdDp)#~sv z|IX~pXT&=8{>ba0!^>n;nJ4ek_VPc6x9=Rto-#U55kVkJd*1Yks{!EZ<7#EA2`@0G zjWy!=bh3>;Y4RNhv?Ad89MB;OVK7hQR-T0R3Oa@vDIcF0THaG0UDrETDb-{7Tsakb z3}e!?y?QL|?AcrLpAjz+dC6#Gq7wfoB0LhY?%t#Q7hPRQ4lXa#gCe8Iq6eJA-~XJT`=jIZ%xk3Wp$@ej@ zR&|ldHofa$|L~b>r*S;E17k_I9#6)-SUTaQdehZ(wyWwon#cPl^2Z$BfL}YQ0a~Iz zY&e2LD_g(|j8cb;RJuV*k?Zm4DOy3_37$MyBkS8rc^>lhUg>|{`S`J+(tK?J-H<>1 z#DlroC&f!ZUJ^h?C5Akae~h9M>9KRBd(XOTGL}kv^g!7!ssX1m%Y3rp1NWAhmR;Yt z-3(XObbvHjgO;YFddfZL8)Hg)3@UT8iOS?usx&>Fu1LU^b2G{6d@<=&tBc7f9(E=(dnaw1pyVg$z4ei|H#Rv8Ydmdo3n{)Q z4;}0(Pfex^hmUp@j~?qj5rAE+bPslyx(B<;eJlHm{cHLQ-TmpBJtG(|hZ|f+1MgN} zc{Itere!)WwASW)CwlKPuzf%9a7a!5^iPis?Rsi*XyI9&{2=q}Fq;o%eY_L3&OSb|q0K5L|bHw_y&Ji2& zSN>ZefeR2v$%o$lCb8}QAFAKY&E&*;|NH+G@BJVDD{@Lv1wN2vr3~Vt! zS4lp+^}x!xnM!KmSvl7|kgI-KyvTA=fV?>yyG^Kk;YR6s)fGp(Pk-H1;5G1devQgi z@Hs)ox4jNzwX;Sh?*u&+-=okk^J9FewRL6kXli!%v%UH8=d;bg3jkj7wqF+KZN6M= zy5uqm+A+~iSi9bL&v(QvAN?H#^y~lo{}MO<_WKmzKmFCOE3M61yqy5d0QY_Od|T|4 ze=#7U1fX8`+R@2@b(um}HdWIB6mq#K=++g&T@!Cn6oS2vhAV5$OjS@5dlAT$(O3tkLMH)9_Y$F@#s+L*pbLguyZfDT%5c4GW}QnixL0}pn6Vf&AbE_ zUgu|KA}IoEVb;!J!QdDrt-j%`*N6>L%a6*>@Ha}Zk9#Ct+5W)Rrj%r4Lw4qr*Nskg z^(SgUa8gkUeQzi#t|R2+$U$C)#;Ty;iQ|wqrudO|)2UsMn^AuMZO;riZO53_304z;X+NI|cfGL+r zZQ~P|J)a}^D%FITn&QyUJw26u^6|-$@bO>GBNR;a0t!c#(MPeyTKZ};pI zj|`S34>wQ<*1p$#@P-DC3Qc*(7r!9xyZc*_U}zKjstD|h41{U0wCUZs;OBp_^$l*-xQZg4sTxvYw3Ic?kfv^v;4IFne`VgpX}~S z)^tINuQ+l{=*9)EGW-JV>@#?c!AKP?+8`7h+V(wNT(E!dT;`#N53dRz_r(D73l8LF zh8@IBOImU1d-l7TY(=L?>WU3l&t*;!X(J;}c$}oJtAq&Ll#H%`>{ZIn%+G#2Jh$tq z1|y^yfbrnJ^hbZ#Qu6{d@KmfIBMs9yJPX?&_+cdITX`oS*Gq~K{+;a+;p1Rt(8t-@ z(nSYKbj=5DXyDbLGPi!_4;BDAmTPw2vo6O(`4=U`GTQ ztK>=IxRcy$da9KA@q-g9i>2C0NjQ2zfgI&026$6z&YmsqcyNf{_nfhLvg_1yXV@D7 z9cwBjC>OyIK_3Wx;=Ub`Q>uFAsYeE8pLulH4|yTrzXh-uz^r}mlv8~(zS|7=VF6%Z z$T85`ftZhv-!PZ~KxpSy$HBIsCQ+J}g|+lm64>_neO}TT%rv&7dg9d!-!`_dyH{#w zr2%}t)fyCa&jd->tDy`>-(!!cuO>#RjmLM-^gk{+GSiAv$NHxC9?19C79<_LaIU!* zENQ42i2E+Nc3*n+tLE!-lZpD=(Uf1S#3~azGhVGK(xa!Ad=r^szO4B#NAip@hd(-u zCu;eb#IgJSY1RDrvsvMJ3kK&!Z+wfm=uK}?0Q&0Z|5$wDeeV_zegAu+QZ7ZFJAnV` zuYE)PCYf$tj0})`O1jk;kf0Oq{>bl(c7lCgef@t{=kw$v4~wZIhef$u7H6G*QPblM zEgzLM;vEvC*D6y9J>FNay|C5?MIhA^YrvGkHXsk@%fvU9UWQLHNWq`d>?;Ka>bf- z?0fr4-h?>8@`3;v8EkSWe#ZVxgZR3Av5YkAQegB`;`yEgGOy2Zz zB!HoL*KIsqfe8YQ`hic}+!DY%AmAI`v*THHyib4i8{$p>;ay@ef`J0rCaJ?yk31y4 z|IIrL0GkQEhsMSE@&JM+=18GFzZnDQ9adn4?+XSG--F!YV)y1e?tCD0iv!2gGvncjLeG!39$bCwXt9Tn+tnSfUViDy19(i`U9noGD_+@uXx^?q zNy`WM*3;6-Z;h8~i!%z^$O#AX#o6>&On6AcG)Mr5dnJhD62y3q`{Bmoeyn#{xxD`g zQJHW2W_y#>RMM>;I#SG7 zr=LX{=xJ&1%i|?c5+_JbD3CRX>+n#F+MoAszIK12Zy7-B*b%vS&p^#9<=t9tqDwtc z2?{)%+U&7ZVdtX*^|`5JYG7FjnQuB5OHX(8`RU}bt>0Qzn%L9J$6&2^^?QFyJ!m|n zyKeuh22I7=;emea&uXP%r~RxH*M0PqJs{wa07 zIL^k61C#4k_s(5x!Jm2^`@g; z>o-rCM0Ue*eU&fhOU*j@y+1qEua@1LBrwjC00~>$$-xzc?y)mxyVh)+t4)qd0^a_;XZC8#xZ}ONuI|)yRxgYrHvC+MU@(o3fXjXngfK2@+eqetVA6Qf9z4ZP2b*5R6W@uby4V4z2nEdXaol-C4697cmee|dV z6##uaQ8pGl1ZZFUedjqF)Pn#3pbeX8-*EB}1pE`=xlQ_@jq6Q<13bGE!JvUA*j={33+_@!g)YKyF*hRuW&T+DhYU;pFI=sF@^?Hg*RNWdY|@ikbUlT9a@jfab0pkZeagzjIul$RLY|A^PR(YFz=*WG5 zaFD|m4p0DGmxiWu`+UG>Z?;@;or2j8id>`eJg#kO+_f9beEvM6@c^~I!_2ke?ANGc z?jT+pwjb6jF5WLT$e;|)rPU0>$GGUi(SvJO_skJfG~lI#eNte8Qo(&+8h+jX_Q;Vn z_P*rTcge`#uZZK2;|B8PY~nVdy1xgKx%fBtCq_=27v!=DdNq*cVCv~8SdUt@YSBIR z-7lUB?rTqx$19xQaOqX=kOou`6u|TxHTAM)i~=tn+nO9q;FSj z2(6W24CWu-GBp3(!$Z(eH#G4eELJ#u^5(C8U4l>Z->@j^aMdp>{ukDY`0ZBdLAd|! zZ+BeDVbhneEOy#ImlB0wX9#_|WR3GZovDkxPj9xl1jVS~8HEQHuUI|F_*fcdm3yM;)Vu zZB0z2MuL-psz-KrP2KnPHDL?RCJ7P)YZl(_O+a0nZky$$Ni1v96IXi!Bf2YHturkR<~-ic<8w@guvP z?!l_-a&!p1BMA3`4jxCD}=W0LjUpHvEb{bAi z`;vDfjWTN5huC??;cH-R+)6t#b-+0^OBQ0|^L>(w+vkt{H=`Vo69MD~Bkv7s_L<5O zle|dU*kl?2xE{3(5q8#`^Z2gW?6zIGhCF8Z?e$CPHMgXyV0bCQAWofj$)qa-9BP>Y zCi{Z=r|5ib-=tyEIfG}oRCq%l`AHd~#;X(Ip$Ho@5Kf=OKL!E&T%)Qu07PidJ0(@P zZR;a4X!2PVRcn^ugK7_GdB{B>*Wqnsbi&inOz?Z~Yj_`UOq?gQu$}M^tqmUhYf`(z z%{D>6#qaPN7@N(E)8mzG59s?dx*{WOAVHbo^l){LE{A$=kUECY6dbgIR$IU3)V|!Z z{$$bKzx?w5T#;S;GI2}N$Wj|WAEp$2Z~pz~c}NOD8EcN+Gnn#-^)(oeId6mamBY_> zPu>3wWzn|sUUVW+{@E~%Xr_VLXWFXVsg>~bYjb4|TpSNqZIx>bDr0NtD4#kH;xN}< zj4(CoO2?~LT)JXkPfxOD)%gis+{%5;$>pk@RVw${%6V24WKL3yyB|Irq8QHS9>`Tc zA{HTw*2pmMM5vKU&+Ff}PuZ!yr)Cq!7<%znV)`d1@CjQ z$?dj)ry_x!LCg;j1|&cQ&4h;>*1!NTw3*Us67Wlv0cx5bpWAzfpf%Y2$XH z=#bRZUzY;`TG|$9=<6=Kz_=Pm`I_Zy!g5H_o(rVMNWC?ANcX%m8$kH z_-DG7`C9opT#@2)=s@9{N~+`*{ax|O#+5zOjYsl7td~#jTowgn7*g9DFb>%D6IY^ISaj0&IU|3;EA!f z!#20v^g9cD>zzngxy;U0(vNIAy3A&b4k1ClcLfO$aMLP`;RdV(Sp1dc0o- z(xC{B+e|oQYHL_%SNKj@3*&oRQ#bs6U+2f_MBs;pDEA$OeleJiXIhVvsKI_nQJW17 z+WEGvKT+JC1%O{HnAzs&wFdg`J+lKlpUbZ!jo>iOIPF&C31p|gvln6QrNw%zwrEH z#yQSzDM+UpnL*4N12-BzR8GkRn68&ostt00>UOEAZN7ZZ-+o1$D8YVt7P#$?{y_bO zKlnt-t$!5Q04kkS`pRt$4Y0!f2<^;0HSDM(zW>xBeA-MaU_aOapU0k>UY?(?#JRX6 zh~zoGuqI|F_%AsDf`XKl1F7OjU$S5y&kxQ1t)$~L&UI-As^0JxXycxXuRB0pBDH5t zP)>!*3GoyM(GCg?a`lP6g8KY)eCEgBS|z-?`k0L|7&8DTv|777-*EO8Kn!lkN$b!$ za2N5Q;Pk`)_NRZQ(isOwM%DBWfiD*iXt8OT*f$dFAO8M7D+&Q`1#+B`ERPgP&c9MBsq{=fCa!OT>WVaG1{ZQm z)HNg9PR>S`S=zdpsH$@LJ5_xypA%9@aSe!jOy$a{^=o?dg{lg6mkO}8pQ5q7fUvuP z>W$?8Gm>8HI$W^3=8vsQyFc7p^2XbpTU>M?S{v7{vp-92xMEU;pp^mVIou>rt$X3o z7apf=lK50>t`oM!+)wTv^=mpEQzg3pkHr~6Q7MRs;H@W(jt6aPS!g9pvG(+i2hTYS zn3BP-JE^&Y_D95T`~5%c*f3Rj4iVdS(!(Mwc8cbEEpG*`5k@Wc@u}Z_zsU!|_M8WT zzZ~>|u)Po!z-cBp4(|2!l&>;5UGCoY^wjXVXAB;5{21lXm_{#p%~opsqG~enBewa- z_**rQR$BSUY!LAyt-Ph(`E*1rWCX84#Vc++cHyiLd~SL+QA=Goy7g&8?y>4o%zb;c zS}r{Eqk+oQL36@fd1(3!=ZYB`STt2+~64u zTHf}GJhN+NXfjt$>plbc#CR~MXTH#HNmC2am`aAJ`=V2_yF!QSh%2`Rvew3p!H?vI zH%u~jr?ysx2J4JX-$XwQJLVViyZYR8BLCdOrp=PAQScx;$<2jN)_$1K4iIRcaJjwe zF+o9!d;j*!3--mKUkD!l=WqHw^PTbp$cGQ`a@yr$a)*~9xCQ`=L2VC6oX>5Rkp_2O zl$YgJ;^nw5zIF(}41*V<%e{g@jDgvS0f>9cpvNGxXOKsqnp}pz4c;k@Q8om1^_1`1 z&>#y?ILrH!sikn`wj6nFT3{)JEBHOMargP}I?UbF!;7v6Q|P77G3Ze&Oo(r8+dq%g za)%WWRV7Ma`-a*WH_pQb9pd}Xe*NwR+>ZrDAL`V=L+`rnFC~|KPE|06 zdGJQ5!N6_7Y4=LLi-C2=7jIGZdEt7$7gOv)(){d<;@Bv+f~+7nTv%-W4DS5K|L`uA zx{2$u1;#FWGWfpXTA^v9Y!j~1hJgR$o`ZLzs)z4gp;S*ue(aA7CX3+3uJI*1v^apz z%T`dG1vMfU3QMZ{Q6?Fy?mSvt6j$y5$g$gn)r32J=39=$va8Gbo$f>7vfIV9L1%}t zE**8WBT|-7jA%0zd;~FcevAuZu0vmN<84hOg5{p3u!Ys1>UnV6=^oO_`$ z;&X`1F@~PQ`C~$BzP@z4c0h9O`AXfmWaWn0RyBStsYN)7=cfCsiIuO(v!{YnF?}l6 z7p5bo&-z%cQbb2lLA?2&{a~4W43yYl>I{Q8%HRRmd0K>ET4ZZGiZAz)|CoaW+=ROs z4?fX8-WO7u1#KpXmZ;bJbf_HfBWE_tm&^ttgzb+7#j9sG2HOr%^B0w0ZE^$LwRt&#rEjgV9nWuT8sfxsCDr#K`IM zi8bfs^*giTkOH&Iu}VRl$l?BMhU5E1=`)rZxnWU4o;ta&1Pk|Sxa;=6RGjc@pZjCg zq>ra~yXyHC)k#NBdF)<;RsntZq}13?NlkIcG9s~$IXO*pbuu2<$KU^Md5r%pUM_-b zP~eew*U&057@0zF00Z~xqBp)-%{HJTh&rrLOsk zXK7`(Ea}CTsQclFCZh9=YtP%C_5Qox-R<6 z7cnbvH44si{aKsTYgB4rAaaL$7)(5fj{msp6!7e8z<_?M1nj#$_#rjZaIz0quY@Ce zxSyQA%r3Pki7E?Y!7~LHXK#xH^6aIr8J^&BC*77ym~NjjDfRSDn&87KrWXmVKg_Rsj|q2azr09oQAmI~LLJI7-kCfQ74)Q5(my zV(nV>cO&_>0V+OE_9k$!qM7uz$^AG)0}=bcfWiGi;uBI%aXfa{t)LW9b>5+T>YF6B z1KkR{)bus1Gxw|6y@J;W^u&H%;}i3J`9d|$X`6vxKm%C#R@e{HkkadlS1<3GNyc2y z+9KP`71t^ta)tdSvF5y4L8ApIbXu@#z znSG-GKz{J7x!6^wE%Wy`oG^1cyYI2m#8!}l^L_b&0?2rPVSg}=sjG-DlMngV7JSbd z7T3zhv701nVEPNVEV|NTs?JzTFJS8DzR704maL~HhdUmBtZC6`tF=t*Jm_YrtA|wD z=lj)hV8DUy@iyzv){R|S<%r)YXFJ#{Y&`O|+jiuJE`wHfxD&8iU4YzKzDb1CCYGSJ z0`+#OxZ|xK?wWb(@VwE&@|V|&hyY2XMyAC1G4nw@&+;Z*4y^G%dgj0CA!`|1PRdj|C41 zE+`fCvi{*=BFDFvXaFQbX`T>NXEQ~xb0{)uFwU6hB5PVUG%*N41MD&+8_?S+aozU) z;(Bl`T-l8Cvj1&p(us(F%l8Q`JbQs2T+3~td=pOb#EizDgO1rVAOH62R$jH;6y4U! z`zK4i<*Mg07iQr#Nz`kt?`W++O1#%isr*w0()q?K@*|DDNFWpHjU<+DoMXSS5GI>R zZ_0b%7L7rMo8Wl5H1f=W8K|~(4S}|>(-Wgg<8S_|_BX5Ka;s8UCyQ&4BLvNWW}t8z zfu)G8i5X0IzyJlnmZvg&`+ER&#hSGZ`(b*3?=_G9W#v`S9DQ7U2aw`;*dL5hTb4?H z>?#!-z?^d(rV?M03IgY2SGw4O&-k~ap@0f=Zad7bJQ(9MgXCW0ke(nv1si(~`;?h> zP|QKB$tH_odQlVcP2uxu#*weE-y~PRcGlPI#!4h*zhDrt;}NDe(Pv(s*xgl|J!+y4 ztc~yZ;^)o&Z7mJqq;Q)*V*s#W7LIJ$ZZoAdL*xm*g?^iqTYjQuIl$#c4lYW6TVG#}imG%T{`IL84M+x$E2 zRmiE|1axRjeFm2o01fa$%QJZKon1}Ry97YVJmK!at%qgwd_IeADm<2Bx zNGN)O?>RlxrdGCA=3~|Bo+~Lv50`NYa<#FOKm|>FV^%4Tg%-W~)Tslh1@t0({!tpa zVWarqSTW!>Y*bRJKT!*xS&d#9T)31ZRL@T(N(Y`Xjq5nMC7kqvhlwN^fEQdW9N2&+ z86~P<(-EC#e12qbgM~HSQj>f5Vc_@gBJHzP0vP86O$yBeU+a0KkpWzAWV<*ZLq@F9 z!V>HX{150*@N=qFLBBDk;8DShV+SW}!*DUON<# zR4NAGzROBlVm=SCsmU|am1e3$^fKSR(ayq3k_3o-iuw6^?qA!NDz@`pL;<Sn=M90t?B(A_`8*~8@y~3-()3Vv8XgpDjBnBLWYVK_*|iQ5S6tl2>;H` z$~!Vs=_=RiIsg~AZ}l=~exM?C0+DZKd{pG*t)aIPU)H^vAGKO?Ew!?QOT}z&1Vq>E{qBO&Fm8Ro!mCZ$#v2>A zpekIEawxQ(HhYQeDjCS*<8uSTN*@ zdjvt8L|QQiJIhT_aHYCa6?g8$*GUFcjI{EJiE!t-+je!Wu=w&?Nxu-1Bt&qS*?LrC;*R> zCquvQ?bBmhb7<*jmhbICTO{hEGR8J&FMHe4fSk8HAMA}_8^kWq<;HrZ~t1|T~j zS`i;SrO5mAg9>P^gI!+AN;@+I^*p8}telEPE9|06+lq#SmpgdW(hzJMZnLT|Y!3&! z+`{GY?0^2k5*KF-i`~$W2L`k(Dn#IB<8U)yE5HoxtGKcJ%RXeB*Lw11;JTolakKDy z><>W0b?l_ThY-hCu$m7AmsCNj)$7A{#o0!4xX^%&QrkOW`@o@@!$vpfP}}zol^?Sd z>0`2Lcql{zo2so{wJ;AgYZb|u@J2I<1~At}!qAHlkQ-MfjSZht5Lz4i)<(keBMZ~- zio!O$N1IkK$ZY34glqI{u{9Cj9NQNf)fa+26yf5_6O{n37NDWAi7`E{ic4vZ;*!P~>AcWUK89!R=dN3LY?J!oKkK-b};ih8-|M9~TxkWn>y_Ob&U-?ym-dpMd2 zrZ{dH6(z^xlf{BH5O7$GSAIzN3l7V{5Y|*^3Xa<~p#Yp!=MEae?l9KW062bQcl-d? z4(CQJMKXQ;k)MZKhDC{e4>_6MHr~R~Qf&nOwRvy%uC_V;-pOJQx9bV&_C%0pMlfTD zvG)S9Dx{HZo@{^|j+Q8Xob0YQV^OLGJ4oLYIyuzi6HDf2}>vaLU65ozc|og8*fq3(s1D{Yi)Zl=H{zu>Alch zXDPC0Cl3*aZU|=!p^H`5NjF^RW5bheYH@|VNvvRE^1 zln(7MYp+4OKqf597B?hHv)*@45G3L6`JqDC@M|SuW08doE&vQSm>O%RtPr!{D8pHUv|Nfx>QL-nS@)j zk5>^1wPQQ`twCM6eJjdb%H#y?frM&jOje%Y6Hq)^b$V9EuFo7XA?ZytLTw}N+z8ET z(+bw&QJ=MwTbn#26+M&2POBA~>;-0`1lxfpVp_#uxr(yZFne%&06Z{wSXya4Xl59F zFz{d#eCXysQ8yR;;rMzx(Z;Qskn{Q_?#u|ixoY|!j4?Y1leMm4sW+L z@|b->vF-u2E}nYhQc3F2U=LR1%8hR)&b%^_NQvzSFtF37U$Mv+wUOe_*>%U^*D#>%R8DMrXGGP>VuX|8ZC7Db zJ6&!Q%VB)G)2MC_)=0bB`HzrjqyvXjE(_VddX^b%!`1yr4z z%;9UDcEN2>DA`C++rG5h(CpA71+0J^Zs8g09Vt7>E{{9H=-nEJKfm)0H+D7JanSnA zL^`-2b&Lh!;i#J&jxbG-H4nkV>cmiMwHjjp@oR-S!@HS6gfBKc#fJj``ZwFn_nS7i*T&&$lV*Z*Q8^oq)_edp zI3_eAjtveBzI-Jm%h=IEd;fOg`H7OSOOjjQa&(P73E<=aFuXILrj$!u3uYG>#{hmO z11#JFBuaGl-k5sL6)Lt;+5W)7du~%J``O!C`PghZEp-1hN3&o>QJsM6vL{S%UOUzv z5d$f=(s(p~44w-GI#0M`!isrlkA>hWY0Vy7=v+^CzfugtqqecWADEsp7&CJ?#rtWN zd4`++1?uKA8p^rlY0C!9r5%K5JE0YN34?X&0p3gD>nl~L`(IRUgF2?8r&ECB(yPu< z(EfZRlWZOEgP#>zhPLv*gTYc=c%!gi`I(JD5WE7ubW#Gc(vOYo{s97+yc3S2rO zKZWNaU-c|UMLMenfD`IK?@~iokIJ9~t_j!K zN$Tp>yW8Kl1`Qkm{(C7cm;Z%l+!79sV!!23)h z)}WQ^!rP=!b4fP-kG_=_*ZtaS4klNfop($`T>C*>TB=8BV>eh&T5y!QQj8t@r_ZnF z{lGQTY@KB;osSZG(Zf!cDzjJnj1qPWZMS;2@fvo}Xpho@=4vV>V+Eaf5FGq7_t+r>q}9`LqOUxN)JIG#F#8 z&W)G-Z6!D^uM*3pT+LRSf;2# zuAZaM?%6v#YP;a12jqGM)6LoV4}=vE=}{|}ZYWS2vCwdq5t zsULi0p-VzEUtp%)N}io8ies<+)=IcpAq+mnsR_Ke7B=+M^gTPHz^pWyBb4TYMvN+A zwO1Eiitz7o{ZRnG(z`eZP8VJOnoVM2&$yx$SiTIu0msL=W6?{r9l+B;KFD_|MYi4X z+bzz6djfAslyJqm?V;kpQ?rG8AU(-g_1&*szFW=e_cngKJ7ctyJpk5n`{8=TL(da1YnlX{B;c z)rno*(+}RcCVbLJwE5Vd|8-j~#>?&6(#a~QykgQ~gh9<*4-Xzm?_9;9qdz)$0~b=O zO6t!5?&&WFzv!4FJ;;Qd5wTkLt&GK8X zTk%}b#1In738^C@gRZ2aYW$Q5P`PiFgExx zB5w%h+$yP2lx1#zCL|W3bGYYH_s2()!oa$veKCuk3S{Ttn-YR7}+E{h-4Z zQ;P<2-T(GKeAYDKaycgMkrSDy1v!)*m#bZcUwHOM1NkSnnw2a&p#@Q5uh(p^Ro6^D z^qc+Rrj*{*m^wVFlhgI=r83EF09Z7n!kj$#$h=1M*H?3-J~ z`;lLLE3(s&2C=T45|mrPE@?qc>ACKT10m`M)lx%K#E)5NeTxx$IRws!jq1v7Zc>{S znO0B*^r3w^<4kp*mmq~E<1#BY^5DIIMpl&{5;WYy;$(_iPla59_%}gCuK0^;6u2@u zrvaiWz6qG>{HbkNGif)Q*y*>J*_M*%&pj|~>Nr>S5(8d<=YI`x4)Wh`1D(^m@I zshHcKcqQ=r<8UT7#QfqZ&!=S)D0{;(M1>1WU14W+m{tJwYRUMs?b83S=w%GPZ5CFH z5?u6$$btvxS^>G8a3~qa!#S~5!`b66*AZg76|~KzzjU=SI<~5WoIT=X3OG8>8L6J! z^KPfAO6gag3zY{f9|Alq_#9lBm$2xBx3>eb?Llgl19G1-I{O#&m19xO6Qxlb9M31$ zuu#Gv`h&a_Di_YvU?zKr zHj|pVS}_{A89*_*Z~iYqH8eCw)FLc)7FD}xvXi1xXx_QUgEUTCII|9*P{}b5=&2cL zn6}I7WC;(%^~y8QPn9YCx|mgZF2ZiXrR=|%Y-^LX2nic>&FBaBz~C8fwp>??fEPy+ zUI0+nBoC7v79`sH*<`FCl~ewFESg&Ao%1rh4i%Vk2Q0lejc!LD!qb(gwX)I3&2l4d z`%Gij6-GNQE^2u!ZJ2383XMUQD##5$#1K<&hRXACzU=n|KjyZqoRpuR&6%j<$>hh7 z3^h|^VQ+YRH$RbKOEy(e?7SCbZkykVoJW_(5aKfvUjYiJ&FD$c}Xp;5^trrF4 z6P3#VAT|RdfB;R*ImvL3kjgM$UpW0>NU%aQUQk~Le zPWgysz%o{|5?fkv>8KkJmUh!BG%^6%t2*}dQ>$7%&{%Wn(j(;D?r8{jM_tE@Ey%3^ zP;Ibg`g9%OC8~W_zq&uF`Jr_!9D!@6k$YQoGO{!Cno+FvXPvWv{xwVVvd<&sx^*r# zqL1t*uR20fH=Niw7ozstv_CSn(Qs@%?~^-2nDrm5l1V?vAA+!d))uvx;mx0I=okdw zXfp%CE;&b0X)|dTo^Gp=*RCV}nN^Kb)L@g;Li6L34`iGJl5+Sw5xBwQQ63D*k)!%M zFGdg%Y!;@r!_&?B=esRyV8u! zxU>ztbK9hGM$wqC*nq_}&E5%!cJsk4H!XUsdcyowIhBKP=U?0+PNv}c5D+mnf<$># z>5se)*ceEeWlhWhpH2bZtVk6yYBg2lG|sU09#vuP9mX(h)vwv6A*r|uNHeYA7@Nb8 z=47J4Nv0a7h+^Ffx3S2@x8y`_vwciyu&J)hDh%Q|M&(jtLhX$6_4*(Vy`?359qGE` z-Qc2hpWQJLb#q2r+&qXK5^k5q$(78_gr{IOf>_h?R0(indgM!m0g5}T08jk+cr@Pe zit?zerA9Rpph$=G$p*(niwGrVIi?7FZ*g6y+iL*^Ir+xtM{Z?{sM4m*m#cM9xbsl6 zNNu}twcWf@i88~~D~HzF^Z5&61nN89+@=3oI@CyWYT-JK{f>RQcj~B~6ZkJY-6$W+ zPbZTNp~GgDYdZmm?Ofb;)x^#EH?S!86=_vo_nC8(xyTjA>#>@NAjpEGB3}OCWCD3T zrE98YC(`?pkwFkVWNr$MAO$xJM_x7DhKp%z-cG4p^T7|9MT_uk@I00h*}E-NCzy(x z4x2t1dBV7PgWeb1L(|c|WiOH=D;lvj?ObQ)Tcp;!X2wmVJV7hpC@!ouGSLfd{80xY zhr`zOnPbWF#Pb>ZFH7oeDr@ueo>42X5#nF$K$!wGsqaVD!N|g0tNzH5-he zuYT@-s~%~i>&8sCpFKOD6=$7)A@z3KBlbS`tXg#PWUPLwT!fAW+q*yf`)V0CoRdS} zK|}xBH}6o_p_V0+Pvh0{+^_sk*Q)bRrn?rbcp4V$7c0Xy6Bv@bgdFYxUfV6S+DWs- zq1UhKJsNkptVzSwp)TJ-m>%F%9?GiIarVwvx_0NQnP5-OmPn24tFDMXj}x84>3hO> zE4VsPn02U?xam|qyf0`%T*!?#|4G|XjL~i{2np#Vs3`VPP%5l;s`lei%`r`LUioFsyn0^AH9xq+K2bB)rT) zGvT(WsBHs4K^<<84}=?*C>LE{KXK|`RzSJ;Z~sP4?XNMp3sL*TfH~>kv^nf+QfF?Kjr;_?>}xVQ*=G8I>tWpS>rRyXJ#8s?wz6TB}c<2g3B9S1Y)FtKoC*NCaC0{Feg_tdTio z6Ji%9sKqMf0B_e#sgnv3JNpfT2lr{QA#t1!n$EE66`eJI_4L7gyjUbB*DD>ZOY4F{ zRL}BW$nXE@;N0l5v*m^g5w6*5xKh7bjya~mi%>0OX;9GU@s*J$EM9?u6H9e@v964X zgTp0sJFTeMsh}d_ra!;6VWp%_ZrY~Jm$m%P%W^^6LDNCA;5e9~*}{cp=7rUv zF_F(;w#?i1V&4E>M8=k0>IH^>;nFAg za@7s9fVu7d_GRnmb#P;0?7j6r=~a}VMKN1I1A}T{u&LymJ$vXpa_SsZ&kJjMD)k+_p$k)6Ejr?G)x?O!x6^ZS3DyP!Ox_hAtM+cd1 zRKFc0JNrR?oaWQ9?mm;=%oiJ;hI%6+L*eL=4a}%!d12w6WbKSD=AF2yHxMmg*Bnwz zzZ)t7#ks;d5Bsvit00{S0Ufwi9-o&A<0vS~t+>#DWrchX&WRP3{^2ilKm?#d0OZOw z?`fM~0qLZlUbvAY=R>n#(fF{~ipzfXHbv=6$7|#p)*+6dH!`{2OvGBpl7;@@P`RFJ zJep<`iWMMCZGYvJ<`Q0|5F>8|L)GYi+RC&yQhM9b4#D*38q>p;Yu)U&qL3(;nmuLl zQU-RjyiNiVoh%x|>u5k@!DR+of!lNgH3V$8ECJ+84Mx?NI1$48!8z;*^~vMaV563o zfX^NGNw0+Es3=}z@_KW*Y>|y`nC{uyJ}T;JKVNRR!{KuX`0?`YxWWm$aj7wj3Qjn} zv@&*hVLl}ikhyXrKbGhp$6p0xgsBC6z~aqMCq>YFD~Rq1a=TH}Z}yIGR#L2|zv?8C z9$yfjylsp{-DH~+^Nou7td#(8?VR-XO@_9?lx;T!WXch>LMX(h6gsN*A;p`QvY;b( zvWKR#7iNrVEf5BDxap#9f*4H6a~&9YozMz96ELc|WRxLqyG%Dlv_Kn7$4gFQA`mHK zZO$4*PlpbtM!n^aa~tO5dhTG-p>%q^PLpR156!==hI3TP=lii_ z+DrBgnh@BdRw7B%&0(=QGk_ZVr_Ckp z8D%4Vztwu?D|?d#pN%=sGdY@61%f1dle1&AF=^~$rCI~EU`K_mrZHr$T#QvplRGx-7vKWG~UhK97)kPcH4JdUWwHJx_Dw`m3E7e{?&i|x0zjY->JT%Ac2UFO3` z>M=7r^|a8{9D?x1hMD?vwA`qX<+e)I8;uOlg}p(2YJa!-HXtcM(2#v42E<Y@8vtf>Kbmk9<&a1sfQ4L$dg}n@PTZ@nOG_K6#P$PNGDL8qEw4`rVr4|75_Qzj6<)%@hDk@=rHm7q%ax;b| z=>Bm1<~5>p;Ki8Ip0jH4l!liY+7I1>rARA{Y$tMs0Ug%7tXb_I$l+3^PlYnv80efp z#Im|KQE(b)1bf7&hoBIY0LL#?j6#9zSf$a2EJJl$_;mx2JtEF5m1Fz5d;+UuFoBgX!H*9X8>vN1xCXBcKu(JKUH1Fh)WL4QqS|2jZ1nL+G5z2?&-PfWRAtNy zZZhemhDHq^;u{rZi1At-6SOL*4R!`?SSvSM930@~TnO-Mo6dAn+ZQD^SA{0ROoEw1 zfer?nF9K~VK@0~ev^6+0K*O{Fpys81=X2CU!xu`c^KxF;A0mwJwC=$@OQcHn>~}pi z66eL}qk=0~UV@iigV@^mwg#%9&yA^EnEu$bq9Ig0oL0)s(R5TV=LGR6b(1_9j$oeb z8p`qfd^JQXob6k3rEz}O0A%oFN4w#Slny+dVM7lG;RI$gGq}e4M?!;3G^ZCfnAyU{ z&ETodegI4*!dm%Dp$6grKYXj<)>`O4$NO7K&;r5_>PnSf`W?XrNK{%Lc2C~Dz zaq%#@trfH_j;)tX$m*VL@-Gw-1^~CS#XVB{lR)D80$Hk&%D;!t+P*J#a0TD7sP$5; zoN#V?W^3aNoxe@x>~rPcLBi|0Z0JwTu_hGM_Q#=~#E#`M*4i2h*(3TY??JxOYhRoE zUBl=JCn!T2HmDxk+hvmM95OPgJ2S^#9L`r3Ge{UD&7(19QP?+$6G@shr{KO3n)RpkTh z-DCNyXQ&8wodP;9ov`sW0gV8kMoE{QpoDwC(Y|(VZJP-jniKoRn|}Z4uYG+1-GJB& z^Vr&$=^U?Df*BCG)HXj3XhlFb;H}7}6E%+F3ArIV}y*9Dk-TXPp8(Bj{ zHIIf?W;d5jJD3Z%3bl4pqTWh)5I}Qb%Ev5l6)g>c0g2C$IP)C!@nEBF!c;|QI->(S zdrUJE@M2!e8iI$;siCTRMOC3|V{LAUy)}5?+NlCj!gQmNif9mrE1$!WP-yxvr{-(2 z*N%a=!Ypwo1QmMf4_sXqq6Evn&8IZD6k2uT|Vy zPP*ZUUeLOGPT;Ljyh683R9%Q%!QDAQ<-1p(V(10?fx|r5ZdA=T6;&ZNmH0fZ0%hkv z01)9d@NB_DV3!a(=NBtntG1IGX5*Z=%_@MRKhsql;KvxO;eo~8gZxa+xZ39EK45!8 zD+s_VC>!vOF9t^KQiNTX_&xHkTXAiG(F|HiZ}1%O-qyw_dbn3U7dwm}UTu~sj6DFb z%)(jAq}z=h62>K=3r#(W7(2mwH-XtDj1 zxHJa_4D;y4E>IqpAgJ@p>cMI7=^2Jo8xa8EoZB$3WsvZG7_i{eHh>|jt1QsSk?jCLFE(f6xbx}` zgI*MOZSU_r^WvO7mPdX#_VW4E5!?(Y{TMuLe|Af)9PjC=*5>CEcDEV;l7Wo}94_Jn z06(O9#l7FSr#SH(-iYfd>6?Gcpy3sy048YiRx79C_uP4i+pu!`Sv=6jGOV0=aH=;k z@pjfe6Xy8+CQyRzR9}8WQ63a<3of_fjiode6KlCxppCCjCpCMxBBu ztkNfHRN$!cl>Rd}O-?@Yfa(GQ@G`YPVzvQC#8f&FGF0$@FH^nFE?4C~e8T}^1~B#w zU~=Y{9fjhh9JsKwUEXdpmz~|kosC!%Aff(joG8TSr~mHN3(MRe021fIS$$L+>i^p938fsT?zobG~iVRH$x$4AToSpAexE68e6WgU%=ug!7Ham}I+W5lN znJJ#hb^edVf$6gVflS0P2;h+vl~WQOKYC&Tp&jF+i|A7fUwdqwTs2aTgz) z$5W3ythUEOllUC_{-KIGlH5EvWI{Jz>eu8FM`Oi&uQ0u$rUT7dQ>g{w zCB3?tf=y5Yc0?4eH0-0*ns~gD>cpNsDh%I={KnbKp3f%T3ONEaMjHB7P}e|SP|4Sm zIvfT7_FwGIooe%A`RnT+%vEoXI#x>{Uz&|wEqD2kX5)C$8@=kiyWLdEbGV7Enj6si zh1OPgsQI_cZ2~m2XP4Z;fBw#z(y=2ZX3h@-S|kj%@Ir>+C9c4;c}i<$Alk>d#9F@s zL6oqY%w87lr7pNHw{QK)f@`pwses$EXQi3g>mb6;u&Y0Ap$3$80fM~^gqM9-(2{Jl zXY%!{GRG(pC;+LTEH{tLDq1&$yG}Ts2JzFg)!u(PG`G^;XF|kJvBT1~H1k?0xi6=3 zFB*KxbI<-{fZnND0TF8LoS=R#YN2(XoZXs6YcHJ!`rujTOxnjlYXE2iM2Erwi!gr$ zx3m+1U~I5&^wZRvA}n?hDG%FbD^7LNp6jI|Z2X4BHo9P-g^N~gu|W*4QMdsO_o=X- ziw$CIhlr{++yf63{Kl_Z)&&Q=%9b!KuOQk(;ZXELsBH-6x-Jipbe%_Y#gK90+};et zkd{DJKbJ3=PQXQl;3W>obD@(S zJb$`UON2As{16Vq5)*CY)U>zV6E2KCT`T3)9Vd~jrIxKKv9+l)q0Oo|j!yM#JPk7h z<#(BttLJBSJe&1B&jG;7<+5r$3nOitT1r4`nv3LTQCjw*H@!u<)?nDcxcdG#?+}9{ zqmk9e4}Jf8>K<;DQ><ok@rWUg|y_z zESF^CpRiqVvF=QD#oMpnt*lY*35Q;A8q~h7ATdUs&x^3@u3oy4%k&dJ%T7M_s9Ek8 zqnoRAnFqI8$C~qC!&)2D-KW3$4drjPU0Lie<>T1GerVqAwg~PC!Tw-;-ha=xkGtPn zE5SLy=Zm_)s6dXrhNoiHn(T8-#B}CH?*-z z0OHgNGV)j#Q{k!l=Tbg}(A-$$s$TrBrIBYJSN`S=;oOR_w51l1xTt+jSX{YY$S3BW zdSuWw&On`nOxB*WaHl>+1WjLMfAFlcrqjdAOfwgb+JRz(lkcMh4+DS=XKf+r2mu6e zW_v%J+Yr@D*)Gw6AG%o*5;PDrBj+2uvx6q&ok%ayBJh9g7yG~Q)1Pg+Z?#HQoANI| z;&<3T2cp7M1NW-a#qT-56sBY6uIN#e0QuR5l*+?AO1Vwnw(Lf|}?mJc(ZakVZ z-VVf&xadHTr+i7aF+ei=%uk0h>(82T6A90BW!61HeV=lNxSB9f`#eOI4_b`Ae)GiM zd+%Nc-!cprOz%;vpf(fkk!HJ$poQ=mC<&)_GMB_dzfMkrNPgi5X(zYXsf+C-oL9~3 z-l>M+RPKb*AlsG2Yx(igVk>BIo~3jvvX?lvmqSpw+9A%%v($Q`Y5Mzs)1o~=yOv~O z;Te%-pgUfA-Rj;+*1D=5&(ZLu3V-2PW|LZZM!MNt>LLiR=PI@2v$K_k0EqngCp$Tx zwj7xyiYw!kx<=O&sY$ZKRKrwUJLH}dW-&mWoKFdIu~fo~rxLaK0|%AUTPLCqC@u!y zF@hWI@(ch}aM}B)pE9`Lw{H7O!yN%OXt0N65QM)6Z^riPHk_`SWHZ0J;pRVGa$W<1 z90<_hco$19%jYyf>s!MXxcd74EH&+)s_$`b*nX+W{#<$TBn4sAB02InzxU3!YrB91 z=Y!b^0T~D=h0Tcp;+y`wGv$HjgKNS)dg$N&*|(KK~|Hjj2vK!V<^FD96>37uf0gz5hlUOs`AjE!H6Lavx_CoBS zf>pZ??RYcfY_Y2&Ob4M3x+N_}?37maAKNnkQx(?K_}J9T_ z-#m0d0b#-23#I({SaGOv&(7_gaATH50a^FHa2hyEVeiiV(!@TUFRH4lO{EBZM3=_a zE00u_r=dI@eyl51Uvzy5JSR^Z@`N$UMqPq zc_g$@Jv}wK6x_Vqr=|3K<2zOxBYd`1f;g0_DWiC?j<|7f)Fntb2P4+qQ(gV`cR#Nd zt5!yy=aVbW;W_|^-E*$;DM~KwIlc;QQvt1fT|PFM9>3>b)ZM~^M>X_P28E*y%tv;ORB{j-OL97^ugnfE%~Nsm6yc3ij|7;(^XP7vtjSLxxw zQg-8MiZ3sHY8_y2|#t3)D^UGl?pBg(f74v1}4iF~MMaXaCv2|EQc#&`p}_%uuLI* zu0z&Bc?=?;qH@OAGqbw!2+nw1WIiDlDNEAG5E&%-oIH;k?ax-cN;tq`8^RH`)M<=_%WsleRvNdB^z@@`$|LGdQTbgFUaYuOM zLpNKtAW9pva5I`#vyIM4{=3cvE|q5bM{ zdO?tbwXG1sUZII|7EI4${M~wZe()!g#Rk7|s|>eRvSc7%krmmhNNkgb9^=oF{ez_y zZ~CSEaI2YAPp-Zad=mRmV@(lef(3KsA5Hvhb{ZY$)=_1ez)IOm>@jKPzai3lvyIrC`SCNNXk2Rwl zTp0p6UaDqa!&~L-fUfiJ-ZZi+r8#4;TB+7YYFiV{Q~Ah(+F$vKPEMC=i7)MJq!cjl z9>`U%7fX;O0~sQ<@)hzte_(&sd)gV(%P!h{lyfkGAP9q6(+rodP;h?^&(A%#vwz~p zKOMybSjrmKk>@y|Z3v`LsNA-*Z!^ zHX3-&xHRzI&?>{Nm2?~siITk~Z+u@{8?rCSXXLjSs~HeS9643P=`m0=~!g6 zG3Dly6>#W*hezwBavYJj<0-hbHl@1fzG_&x-qfT^i#F;?5T9!<$Or2fkA<`K z$o%kl!&=e`5g)lPSJ@(#D95FdAyE_q-G$b?RtZ()I35Bq0r z-Kl@pHrxPQ)WkIlRpUA_Aj9==Vc~lhPJV|VN&c`^yc!+=x}~jN`i%P_H*08v`;AI! z{Qc#P1N+wWC5u7w57l%sFNPhYS14C8uxDq>nY;HjCd?lXr7(LCCqSYoMzVjPyylm# z-s6~Xj|Q?sb$;6E=K0)p>%i6rmd}mv>yHA$VhcuX!Nau^(Cuj-Tu=4&m4+q$-WlrS zV2fJjfQ-D1>Lj#BX>WTasKo>sxPKj&Xz`%o{Uf9e&_-3xu<&oVjTQ6q#n6{l(rO?Z z!*wt{^X60fCyXJ-nQlTS1v#G1dW73e^5XcN&(Ewmk(9#hMVuhnoJ~l-pZ|aC&-ylO zoF2L8^+&b6=lO#C$}YDNC7wKg;E>eDKU@>$mhCto1P}fiYD7IpZ3SA@-r3#|uJwb4 z=A;=OFr6&(z!F|eaxr2r3fYN7rFgP$7l965RH$9)7p~dv4PwtKQNo6%{Tri|Hw^4s z*NaZ{I^)gt*{~y5ocvp=*JFRPGq)~Z4F^7&moF_wP8g6O;XnywaMQU*2VZ^mv?9Zf zN6GgT98qWBi=E&2)+x35VuCeV_~9bMt}EMH%C28Mo9gST?z{i7(dvB3+>o%L209U? zUBe5sv*wDbe{1KtzyLxzW3!y$#R$NFJZGM9qK?OdB|PPGone@g**Vs>U^~0N9*&2M zLHn49*j>JH;P7m*79XE1_3l1a?6ZH5sv9T+*2-v5_-m&R?ssWjbSG%W;<#k*fAjg= z%02UqycqEa8Tj~wI0158#$H%XOMBn)MC?BbYU~0jPE7Q44G$NR{k>J)&r@f_5s0Oy zVn_e%^LzVog8;}s`Q862L3oRLxB&3*t52I+_lENi4!>$_re|5UlIriN^{rVxpFcF& zRV!6grj(tP1)d3`2AT<6kjwQU$P!aM+WNC*TV##l_xNl3t$7>xYWblb-nYlJ2S`cd z>mAa7f+2Xk0z(eRg7Nt9_rGV30qy(l5C1pmZTN;V)^NUT^g$+68!X+thBNo@`m3M+ zWAWMF`RxU*3@{KtJ=Res9A+a70<;leIdetN^jppvKG>6p)rY#`l~V`1@*9?=XR}?2 z@?@cwnwpx9sToWDd(Ve|U;OJg?+{aSg@goiu^;74yc9V21HG_O`c;CwenghiYDMh435i{g;1R4Qz=8^7PP=pY3i)HnGFda62_~x3Oly!-rN@6)9F#c9cYE z>1J-b#Rz5wyZEzHs=`Jcr)mP2HfIkD)2gWObu#XH=a2OrdDY6ytjf0aJXKWe=+b;{ z&MlstDE2>kC_gk`sjC^0D{p!dZuK|L9Nd$3T+a~(%>Dxt`Jta2EiOowPl%p#x8!ms zEQ9KVYGla%QY|-@cAk~j@gL2HsLk8AH8W1ivXhZd2Qnteq?ZTB+hfgC*`9dms&hv6tr zPlyvJCmhI-y(Rw{>0ie6U%{Vw)oLuie_tlEdUZaYN_t1OZ5x{1HEy(aI@@1f^TtaK z3~pFE>m*_bnE2E+(UeFD4rx1rwYrm8)?d!9T{d4UR$`^;yee1>cPN5(d-q3vUja~c z(~$tQ0d4z()v{dFp{G?pWq{;Ozxpl}N`_WcgQvwH2n&M|MF0>OQlGr_Yi$Pu&JW4+ zPs#xl>}zJhxuMbq0|EuBT+qv&5F6}guj!q9(^8DPwdDG?t$)0r0B&%{6F0Wk$;UzFdW5_$6iq{8D zTRxviC#ulS^-8_ry3oSvtn)8y(5PWR+rpe16~?F{X$ENCAGgA4r_otB$=zPk;XQJo z4K8oqgo!;k;fy|8YyhvYJU_UWaPVfNKUsK#7cji#nY^ClwM+&;5{9*Yw9e3;BlfL4*-$-3u;r{y8T=~c11&|ZYk;Ae%8@pW| z=Gv(5V9br2clMEiGftb~>T2BrBS_dnQBMq3o6NOd)>Yk)6ZSyN>jQ zj~B&f@u2TeJ?NUd+mwd_D=qc)2g?jgkcVsXSXy!IX4T&i01=Txy&_cBtp3z2c?i<1 z;<}mZ5?uJKwSC9VS=T#FNj?yV+PLaBly=FbnA|8zH7ll;u$&ykZQUQ-KR5K#BZVQ+ zRGg2$yy~)x5A=<#nRm^w*K1p=k*}hF+QaVf_bQ}Mks}3ionc4y zf%Fu#hp#*{pBUfr^z!`SneOm$TO|s?W3t%AX8?3g)aNpLcoD*t$`H7^FlfMsZ%vnZ>Q8$2k~_Ngz_^xhgY#{%QS_shEpcTabz7>41gcrNw>U_ z^_$b?wXWEvFu0>vebqT0^3{k-tydiiH?tPUuAVqr?0eu~ex&00p+!hvco5TZUOZ_I=F9h``g&>xj1F;Q zbr*fT@}({}(5AG{Yy0Uap>GeslLz{aJb5r%m@0$|98I2avx*ST zae&dZm=L+0I@u~WI!ZucpmkA8XfJ6HJ}<0i(u{g6%ccsiIW;@AYA97OI)bv%98+?n z*_rZEc>EoKSlvm_QPssBm5O@YIhZuH{O=&2BQFuRGkxAOJp9m<}% zdS0ItRgEY$;5owb9qarI=EGi8JGkx9hDrLy3`{Gk0C}B|p{BZ;G18JBxjSzZG7`2#(RuBlz^6%x}2M^2* z{`7FTsmhBBVmjW7FHzMckm0j8Os+WptYbd3fTj&roKttc2dLFU5gu2c_8@^5Q+<&diIE6x2ym z76vY60t|vyv%#>`zN<&N=hv_4ok=BJ&!v`Bf%ze*O2g+&T26SUS_j{Nn?Xul8yM`q z@XR1^DmCBTvUhf5$8;$|A-u4LU6h;@AVb3ac zYy!%#7H(F)WrH7?dhks*^N83Im)du|^gfIZr3^wC@QONA-O+w^5xf8oTI|k!YfXx*F2d3zEA}w^H~0qt8wC zPClQ@%pIEVF6S#9wG@MJ4m8B9I2tN6z0v|PuZSUB|59OJ|!)ghpTJYO)aFmoe;RWxd2 zBHa2T1!^zYm!rKNbBFS&{Lx}+YJ4`6pDd-y`D#ME$kHc)J3N>!_V*{tW2-ayqzpm` z4J;?*bx=l{Z<2K^_nA-mmCCH}G*2@IpDIi8?a7U~G5eKWJ<0h$9G@F`@>pSD;aQ%T zoZ{n=lMZBvPBg0jz^*c389IIK^vVlPpLA1+y6b3T&!r_FEXxI5@`a%l!Y--efJzWN z(TiXCqS3wQnFLzV7#7#gf6sI3WzU(NnC}9(a|a7uHAzF}CrjyC)mu_q1zWnLVb<4| zDtC3oDm^`kT6Q2=9_&w-(@E*`HO84BQ-C6yK6@%X=D()Ih=Hu`h3%~n!f0hzk9FUr zlKo&`j-g$kATyOq5K4d{vC_?jUHUPD6+Gu2#9=Ky7h4jShntHp&M`a$S29B@m z&S-bsWCWm?&s7q|S?Q~mM<~rzlbEtA!0n;#HtQ8Q|<1F)sl&r zmrTZLy%M-Yp@hRl=ju2TWVo6-%|^sgT}2o?(yH2#<6=~M9!2Qb1{RiE-nTU|b7++s zP7{>Y!s`4y!;c?5SQyxLU~YIJl~8B&q8oM1l23pmCFmSNNLbcMy@;qmY^@P;IqlfcRTG$zvKfHc1z1d!9dBKu~mMTa#T9r(AnlYIUOlvDcIb!C&#sW(iDdZs$PMmF zip-T;bA@NbOGsXFK!zZv`Lwk6W%-DaQFXEXomZ{LX7(NHEzJ~?J;Rw&BAxKq?dAk- zH{*UYw81`BL8OoY6lVRVS!Ru2|h~eI>d5ZYU@KF*89`lPJLc@Q5cY#^P@h+PCzkm-*cs& z?>srVdf!aBx9Ysr4$FCqZ6v)FLdpLK|L zeO8g)}~;ktpJ*%4Nk zJvO?8S@$Fe&nf_TlzbC3u-4;4gu}wdzl)_YTt7&%5e=>{MBhEmJku+0`k`$sO4C3Q z)bTyrcC|bxno_7-ZQl>TEdO_4Qc?(M$Q_xjbT_-Vpb{~BY9Z@nWY_|Aw%nj zW=BpRnHgBuUoZeR*>uF6DKg-4VggP5?4Q*cU+n(U?l7OTP1QD(=4kV1y{&IjJv1HH zs@aODF$Z?p+vl0|N~3vo?{wWDkOl}o(>z}Re1R*C&eazc8LWBsK)!$9v0_F7xU1QH zdbt9a9?P4Zk%>>>B*c#VP+mXl>3KRe3o~T^-RHPkT}H7*wVE zHl=V5P8PfN9xY~`KV0aq)LKOzRgT0bPe!88iIkT;kXb0q4d3&PtpE+_9nBO*HV)1X ztnHJaPF6K{77nXHDzc>DfZ&K;&;pERW4o)GjoPyJN9VpS`LII#(W zXszn=a$j0gf z9vbVN&#vt)_AT!&Dg-J%tktzj?Dv8a9}CbXsYV-QB8Z-Ovy(wlJ5L zK)ZG^ptdD5kSfKKF)uBF-PMz*^zFW zgyu26FJH&Ym6}_atH!HUFIKI1Zn0R6&*Um;`Q9y-YD>y}26*Mr_*O#n-2O@juPr}! zK(@uw)C}sZc=-vUZ+A)l^24O)z3b-*yte#Y134_<)Ix{BFMsI*+aH(YV~c$8SVF|^ zdZlvS#mX;$+(M-HV^d6cW77P(LIMaS)Y+xdk)=rhT32}EG10r_=T+mjlV1RN2?Bsi zIwC>sY;yG9bxz>wlka`f=rxJv|0-`hk@fTIc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branding/Badge-gradient-light.png b/branding/Badge-gradient-light.png new file mode 100644 index 0000000000000000000000000000000000000000..56b0820580a608c8954ee4b57cf762a5c5894246 GIT binary patch literal 27735 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

6_j#1G|7=zqXLuz4!FN#$IN@azzwc?2Q!brK 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 i0k@M{=RbgLo&0~~6|7X-uRUM@0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branding/Badge-title-black/white.png b/branding/Badge-title-black/white.png new file mode 100644 index 0000000000000000000000000000000000000000..49aa12f55ebd054386ef6ef989dbe18acba8a923 GIT binary patch literal 24542 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�%>GocE4cO7zW?n!#5-Bd=Twer$>(f8bA~xe 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branding/Badge-title-gradient-dark.png b/branding/Badge-title-gradient-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9077032150e267e94fc22aece7668fe898dfed6a GIT binary patch literal 166591 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branding/Badge-title-gradient-light.png b/branding/Badge-title-gradient-light.png new file mode 100644 index 0000000000000000000000000000000000000000..2a1ae936343e0cf50e39cef582c9b7dc72b96f5e GIT binary patch literal 145056 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

    3ApOR4jZP=}-PqdWP>-_k0oz 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

    )YmbUk(CiiPxl$ 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