diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..c56e701 Binary files /dev/null and b/.DS_Store differ diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..0563b6e Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/orders/.editorconfig b/src/orders/.editorconfig new file mode 100644 index 0000000..746ae31 --- /dev/null +++ b/src/orders/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# All files +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.sol] +indent_size = 4 + +[*.tree] +indent_size = 1 diff --git a/src/orders/.env.example b/src/orders/.env.example new file mode 100644 index 0000000..5b223c6 --- /dev/null +++ b/src/orders/.env.example @@ -0,0 +1,37 @@ +# RPC endpoint URL for the target blockchain network +# Example: https://evm.chiado.wardenprotocol.org +RPC_URL="" + +# Chain ID of the target network +# Example: 10010 (Warden chiado), 1337 (Local) +CHAIN_ID="" + +# Address of the create2 proxy contract +# Format: 0x{40 hex characters} +CREATE2_ADDRESS="" + +# Address of the scheduler +# Format: 0x{40 hex characters} +SCHEDULER_ADDRESS="" + +# Address of the factory contract owner +# Format: 0x{40 hex characters} +FACTORY_OWNER_ADDRESS="" + +# Address of the registry contract +# Format: 0x{40 hex characters} +REGISTRY_ADDRESS="" + +# WARNING: This is a sensitive value that provides access to funds. +# Never commit the actual mnemonic to version control. +# Format: 12 or 24 word seed phrase +MNEMONIC="" + + +# Salt used to deploy registry contract +# Format: 0 to 309485009821345068724781055 random integer +REGISTRY_SALT="" + +# Salt used to deploy factory contract +# Format: 0 to 309485009821345068724781055 random integer +FACTORY_SALT="" \ No newline at end of file diff --git a/src/orders/.gitignore b/src/orders/.gitignore new file mode 100644 index 0000000..e7e891b --- /dev/null +++ b/src/orders/.gitignore @@ -0,0 +1,22 @@ +# directories +cache +coverage +node_modules +out + +# files +*.env +*.log +.DS_Store +.pnp.* +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock + +# broadcasts +broadcast/** +!broadcast/Deploy.s.sol +!broadcast/Deploy.s.sol/12345 +!broadcast/Deploy.s.sol/12345/latest.json +!broadcast/Deploy.s.sol/12345/run-latest.json diff --git a/src/orders/.prettierignore b/src/orders/.prettierignore new file mode 100644 index 0000000..2492f9b --- /dev/null +++ b/src/orders/.prettierignore @@ -0,0 +1,18 @@ +# directories +broadcast +cache +coverage +node_modules +out +lib + +# files +*.env +*.log +.DS_Store +.pnp.* +bun.lockb +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock \ No newline at end of file diff --git a/src/orders/.prettierrc.yml b/src/orders/.prettierrc.yml new file mode 100644 index 0000000..a1ecdbb --- /dev/null +++ b/src/orders/.prettierrc.yml @@ -0,0 +1,7 @@ +bracketSpacing: true +printWidth: 120 +proseWrap: "always" +singleQuote: false +tabWidth: 2 +trailingComma: "all" +useTabs: false diff --git a/src/orders/.solhint.json b/src/orders/.solhint.json new file mode 100644 index 0000000..14f780e --- /dev/null +++ b/src/orders/.solhint.json @@ -0,0 +1,14 @@ +{ + "extends": "solhint:recommended", + "rules": { + "code-complexity": ["error", 8], + "compiler-version": ["error", ">=0.8.25"], + "func-name-mixedcase": "off", + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "named-parameters-mapping": "warn", + "no-console": "off", + "not-rely-on-time": "off", + "one-contract-per-file": "off" + } +} diff --git a/src/orders/.solhintignore b/src/orders/.solhintignore new file mode 100644 index 0000000..6d1bc38 --- /dev/null +++ b/src/orders/.solhintignore @@ -0,0 +1 @@ +src/RLPEncode.sol \ No newline at end of file diff --git a/src/orders/.vscode/settings.json b/src/orders/.vscode/settings.json new file mode 100644 index 0000000..504de57 --- /dev/null +++ b/src/orders/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "[solidity]": { + "editor.defaultFormatter": "NomicFoundation.hardhat-solidity" + }, + "[toml]": { + "editor.defaultFormatter": "tamasfe.even-better-toml" + }, + "solidity.formatter": "forge", + "editor.formatOnSave": true +} diff --git a/src/orders/README.md b/src/orders/README.md new file mode 100644 index 0000000..c735fff --- /dev/null +++ b/src/orders/README.md @@ -0,0 +1,21 @@ +## Automated uniswap contracts + +### Commands + +Before using commands install dependencies with `yarn install`. + +#### Build + +```sh +yarn build +``` + +#### Tests + +```sh +yarn test +``` + +### Order + +### Factory diff --git a/src/orders/broadcast/Deploy.s.sol/12345/latest.json b/src/orders/broadcast/Deploy.s.sol/12345/latest.json new file mode 100644 index 0000000..9eb041a --- /dev/null +++ b/src/orders/broadcast/Deploy.s.sol/12345/latest.json @@ -0,0 +1,4 @@ +{ + "orderFactory": "0x7f64E16EC2557FC17150883C7DeDc7E9AD936CDF", + "registry": "0x3565F2c0C305BbEEB0A433FeAaFaCC4E8F1Dca83" +} \ No newline at end of file diff --git a/src/orders/broadcast/Deploy.s.sol/12345/run-latest.json b/src/orders/broadcast/Deploy.s.sol/12345/run-latest.json new file mode 100644 index 0000000..8227558 --- /dev/null +++ b/src/orders/broadcast/Deploy.s.sol/12345/run-latest.json @@ -0,0 +1,238 @@ +{ + "transactions": [ + { + "hash": "0xaffdfef61fa59ce8e56fc69b48db8e3e806a18d59dcf2da015370d9b71e2baf1", + "transactionType": "CREATE", + "contractName": "Create2", + "contractAddress": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "function": null, + "arguments": null, + "transaction": { + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "gas": "0x39bdf", + "value": "0x0", + "input": "0x60808060405234601557610258908161001b8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063481286e6146100375763cdcb760a1461003257600080fd5b6100d4565b346100a05760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a05760243560c05260043560a0523060805260ff608b5360206055608b2073ffffffffffffffffffffffffffffffffffffffff60405191168152f35b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a05767ffffffffffffffff6024358181116100a057366023820112156100a0578060040135918083116101c35760405190601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168201908111828210176101c35760405282815236602484840101116100a05760006020846101bf956024610198960183860137830101526004356101c8565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b6100a5565b908051156102215760208151910134f59073ffffffffffffffffffffffffffffffffffffffff8216156101f757565b60046040517f741752c2000000000000000000000000000000000000000000000000000000008152fd5b60046040517f4ca249dc000000000000000000000000000000000000000000000000000000008152fdfea164736f6c6343000819000a", + "nonce": "0x40", + "chainId": "0x3039" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x6921bf89511ae24dea797d56c0f8b25cfcf87ea12918975dde3bdcf643a7d58d", + "transactionType": "CALL", + "contractName": "Create2", + "contractAddress": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "function": "deploy(bytes32,bytes)", + "arguments": [ + "0x6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003e9", + "0x60808060405234601a5760016000556109c090816100208239f35b600080fdfe608060408181526004918236101561001657600080fd5b600090813560e01c9081630af83b281461075b575080634420e4861461059857806350cfe3c71461052f5763aa733a441461005057600080fd5b3461052c57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261052c576100866108ab565b6024356002835414610503576002835573ffffffffffffffffffffffffffffffffffffffff80921680156104db573384526001926020908482528686205416156104b357821561048b578185526002815285852083865281526100eb868620546108d3565b6104635785517f1c9feaa50000000000000000000000000000000000000000000000000000000081528181898189335af1869181610434575b50610151578787517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b869188911561040c578251927f88328a690000000000000000000000000000000000000000000000000000000084528784848183335af193841561040257889461034a575b5084885260028252808820868952825287209280519267ffffffffffffffff841161031e57509082916101c985546108d3565b601f81116102cc575b5081601f841160011461024d57508892610242575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82871b9260031b1c19161790555b337f4a13f12b0824ee061bfc467b7fc9c0f9505f9290bfc7d773a5909c36d4c22bed8580a4815580f35b0151905087806101e7565b9190601f19899516868b52838b20938b905b8282106102b3575050841161027c575b505050811b019055610218565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905587808061026f565b8484015186558b9790950194938401939081019061025f565b90919250848952828920601f850160051c810191848610610314575b8594939291601f8b920160051c01915b8281106103065750506101d2565b8b81558695508a91016102f8565b90915081906102e8565b8860416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b9093503d8089833e61035c8183610926565b81019082818303126103fe57805167ffffffffffffffff918282116103fa57019082601f830112156103ca5781519081116103ce578551926103a785601f19601f8501160185610926565b8184528482840101116103ca576103c391848085019101610978565b9288610196565b8980fd5b60248a6041877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8a80fd5b8880fd5b81513d8a823e3d90fd5b5090517fec84b1da000000000000000000000000000000000000000000000000000000008152fd5b610455919250833d851161045c575b61044d8183610926565b81019061099b565b9038610124565b503d610443565b8686517f34a849b3000000000000000000000000000000000000000000000000000000008152fd5b8686517f0af806e0000000000000000000000000000000000000000000000000000000008152fd5b8686517f15dbf9e7000000000000000000000000000000000000000000000000000000008152fd5b8585517f4595d075000000000000000000000000000000000000000000000000000000008152fd5b505050517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b80fd5b5090346105945760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610594576020918173ffffffffffffffffffffffffffffffffffffffff91826105836108ab565b168152600185522054169051908152f35b5080fd5b503461052c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105945773ffffffffffffffffffffffffffffffffffffffff90816105e86108ab565b169182156107335782845260018252848420541661070a5783517f1c9feaa50000000000000000000000000000000000000000000000000000000081528181878187875af18491816106eb575b50610662578585517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b908585926106c45750600190838552528220337fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055337f0a31ee9d46a828884b81003c8498156ea6aa15b9b54bdd0ef0b533d9eba57e558380a380f35b82517f68f46c45000000000000000000000000000000000000000000000000000000008152fd5b610703919250833d851161045c5761044d8183610926565b9038610635565b505050517f604ad035000000000000000000000000000000000000000000000000000000008152fd5b8585517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b839150346108a757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108a75773ffffffffffffffffffffffffffffffffffffffff6107a96108ab565b16835260209260028452828120602435825284528183822091858184546107cf816108d3565b9182865283860196600192600181169081600014610866575060011461082a575b848a88601f19601f8c610805848d0385610926565b6108218551968795818752519283809288015287870190610978565b01168101030190f35b9080949550528383205b828410610850575050508201018582601f19601f6108056107f0565b8054888501860152879550928401928101610834565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016895250505050151560051b83010190508582601f19601f6108056107f0565b8280fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036108ce57565b600080fd5b90600182811c9216801561091c575b60208310146108ed57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916108e2565b90601f601f19910116810190811067ffffffffffffffff82111761094957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811061098b5750506000910152565b818101518382015260200161097b565b908160209103126108ce575180151581036108ce579056fea164736f6c6343000819000a" + ], + "transaction": { + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "gas": "0xce0ce", + "value": "0x0", + "input": "0xcdcb760a6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003e9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000009e060808060405234601a5760016000556109c090816100208239f35b600080fdfe608060408181526004918236101561001657600080fd5b600090813560e01c9081630af83b281461075b575080634420e4861461059857806350cfe3c71461052f5763aa733a441461005057600080fd5b3461052c57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261052c576100866108ab565b6024356002835414610503576002835573ffffffffffffffffffffffffffffffffffffffff80921680156104db573384526001926020908482528686205416156104b357821561048b578185526002815285852083865281526100eb868620546108d3565b6104635785517f1c9feaa50000000000000000000000000000000000000000000000000000000081528181898189335af1869181610434575b50610151578787517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b869188911561040c578251927f88328a690000000000000000000000000000000000000000000000000000000084528784848183335af193841561040257889461034a575b5084885260028252808820868952825287209280519267ffffffffffffffff841161031e57509082916101c985546108d3565b601f81116102cc575b5081601f841160011461024d57508892610242575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82871b9260031b1c19161790555b337f4a13f12b0824ee061bfc467b7fc9c0f9505f9290bfc7d773a5909c36d4c22bed8580a4815580f35b0151905087806101e7565b9190601f19899516868b52838b20938b905b8282106102b3575050841161027c575b505050811b019055610218565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905587808061026f565b8484015186558b9790950194938401939081019061025f565b90919250848952828920601f850160051c810191848610610314575b8594939291601f8b920160051c01915b8281106103065750506101d2565b8b81558695508a91016102f8565b90915081906102e8565b8860416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b9093503d8089833e61035c8183610926565b81019082818303126103fe57805167ffffffffffffffff918282116103fa57019082601f830112156103ca5781519081116103ce578551926103a785601f19601f8501160185610926565b8184528482840101116103ca576103c391848085019101610978565b9288610196565b8980fd5b60248a6041877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8a80fd5b8880fd5b81513d8a823e3d90fd5b5090517fec84b1da000000000000000000000000000000000000000000000000000000008152fd5b610455919250833d851161045c575b61044d8183610926565b81019061099b565b9038610124565b503d610443565b8686517f34a849b3000000000000000000000000000000000000000000000000000000008152fd5b8686517f0af806e0000000000000000000000000000000000000000000000000000000008152fd5b8686517f15dbf9e7000000000000000000000000000000000000000000000000000000008152fd5b8585517f4595d075000000000000000000000000000000000000000000000000000000008152fd5b505050517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b80fd5b5090346105945760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610594576020918173ffffffffffffffffffffffffffffffffffffffff91826105836108ab565b168152600185522054169051908152f35b5080fd5b503461052c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105945773ffffffffffffffffffffffffffffffffffffffff90816105e86108ab565b169182156107335782845260018252848420541661070a5783517f1c9feaa50000000000000000000000000000000000000000000000000000000081528181878187875af18491816106eb575b50610662578585517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b908585926106c45750600190838552528220337fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055337f0a31ee9d46a828884b81003c8498156ea6aa15b9b54bdd0ef0b533d9eba57e558380a380f35b82517f68f46c45000000000000000000000000000000000000000000000000000000008152fd5b610703919250833d851161045c5761044d8183610926565b9038610635565b505050517f604ad035000000000000000000000000000000000000000000000000000000008152fd5b8585517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b839150346108a757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108a75773ffffffffffffffffffffffffffffffffffffffff6107a96108ab565b16835260209260028452828120602435825284528183822091858184546107cf816108d3565b9182865283860196600192600181169081600014610866575060011461082a575b848a88601f19601f8c610805848d0385610926565b6108218551968795818752519283809288015287870190610978565b01168101030190f35b9080949550528383205b828410610850575050508201018582601f19601f6108056107f0565b8054888501860152879550928401928101610834565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016895250505050151560051b83010190508582601f19601f6108056107f0565b8280fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036108ce57565b600080fd5b90600182811c9216801561091c575b60208310146108ed57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916108e2565b90601f601f19910116810190811067ffffffffffffffff82111761094957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811061098b5750506000910152565b818101518382015260200161097b565b908160209103126108ce575180151581036108ce579056fea164736f6c6343000819000a", + "nonce": "0x41", + "chainId": "0x3039" + }, + "additionalContracts": [ + { + "transactionType": "CREATE2", + "address": "0x3565f2c0c305bbeeb0a433feaafacc4e8f1dca83", + "initCode": "0x60808060405234601a5760016000556109c090816100208239f35b600080fdfe608060408181526004918236101561001657600080fd5b600090813560e01c9081630af83b281461075b575080634420e4861461059857806350cfe3c71461052f5763aa733a441461005057600080fd5b3461052c57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261052c576100866108ab565b6024356002835414610503576002835573ffffffffffffffffffffffffffffffffffffffff80921680156104db573384526001926020908482528686205416156104b357821561048b578185526002815285852083865281526100eb868620546108d3565b6104635785517f1c9feaa50000000000000000000000000000000000000000000000000000000081528181898189335af1869181610434575b50610151578787517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b869188911561040c578251927f88328a690000000000000000000000000000000000000000000000000000000084528784848183335af193841561040257889461034a575b5084885260028252808820868952825287209280519267ffffffffffffffff841161031e57509082916101c985546108d3565b601f81116102cc575b5081601f841160011461024d57508892610242575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82871b9260031b1c19161790555b337f4a13f12b0824ee061bfc467b7fc9c0f9505f9290bfc7d773a5909c36d4c22bed8580a4815580f35b0151905087806101e7565b9190601f19899516868b52838b20938b905b8282106102b3575050841161027c575b505050811b019055610218565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905587808061026f565b8484015186558b9790950194938401939081019061025f565b90919250848952828920601f850160051c810191848610610314575b8594939291601f8b920160051c01915b8281106103065750506101d2565b8b81558695508a91016102f8565b90915081906102e8565b8860416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b9093503d8089833e61035c8183610926565b81019082818303126103fe57805167ffffffffffffffff918282116103fa57019082601f830112156103ca5781519081116103ce578551926103a785601f19601f8501160185610926565b8184528482840101116103ca576103c391848085019101610978565b9288610196565b8980fd5b60248a6041877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8a80fd5b8880fd5b81513d8a823e3d90fd5b5090517fec84b1da000000000000000000000000000000000000000000000000000000008152fd5b610455919250833d851161045c575b61044d8183610926565b81019061099b565b9038610124565b503d610443565b8686517f34a849b3000000000000000000000000000000000000000000000000000000008152fd5b8686517f0af806e0000000000000000000000000000000000000000000000000000000008152fd5b8686517f15dbf9e7000000000000000000000000000000000000000000000000000000008152fd5b8585517f4595d075000000000000000000000000000000000000000000000000000000008152fd5b505050517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b80fd5b5090346105945760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610594576020918173ffffffffffffffffffffffffffffffffffffffff91826105836108ab565b168152600185522054169051908152f35b5080fd5b503461052c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105945773ffffffffffffffffffffffffffffffffffffffff90816105e86108ab565b169182156107335782845260018252848420541661070a5783517f1c9feaa50000000000000000000000000000000000000000000000000000000081528181878187875af18491816106eb575b50610662578585517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b908585926106c45750600190838552528220337fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055337f0a31ee9d46a828884b81003c8498156ea6aa15b9b54bdd0ef0b533d9eba57e558380a380f35b82517f68f46c45000000000000000000000000000000000000000000000000000000008152fd5b610703919250833d851161045c5761044d8183610926565b9038610635565b505050517f604ad035000000000000000000000000000000000000000000000000000000008152fd5b8585517f785ee9e6000000000000000000000000000000000000000000000000000000008152fd5b839150346108a757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108a75773ffffffffffffffffffffffffffffffffffffffff6107a96108ab565b16835260209260028452828120602435825284528183822091858184546107cf816108d3565b9182865283860196600192600181169081600014610866575060011461082a575b848a88601f19601f8c610805848d0385610926565b6108218551968795818752519283809288015287870190610978565b01168101030190f35b9080949550528383205b828410610850575050508201018582601f19601f6108056107f0565b8054888501860152879550928401928101610834565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016895250505050151560051b83010190508582601f19601f6108056107f0565b8280fd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036108ce57565b600080fd5b90600182811c9216801561091c575b60208310146108ed57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916108e2565b90601f601f19910116810190811067ffffffffffffffff82111761094957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811061098b5750506000910152565b818101518382015260200161097b565b908160209103126108ce575180151581036108ce579056fea164736f6c6343000819000a" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0x71351ba06c4e7c904b90ddae1192e04b8f5d53f8789bc7001f34fb13e88d80ab", + "transactionType": "CALL", + "contractName": "Create2", + "contractAddress": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "function": "deploy(bytes32,bytes)", + "arguments": [ + "0x6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003ea", + "0x60a034607357601f61520438819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607357516001600160a01b038116908190036073576001600055608052604051615175908161008f823960805181818160e901526103a60152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c90816306433b1b146100a45781630b0fdb3d14610055575080633dc48a341461005057637fddd6021461004b57600080fd5b610242565b610176565b346100a15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15760ff60406020926004358152600184522054166040519015158152f35b80fd5b346100a157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b600091031261011d57565b600080fd5b9181601f8401121561011d5782359167ffffffffffffffff831161011d576020808501948460051b01011161011d57565b6064359073ffffffffffffffffffffffffffffffffffffffff8216820361011d57565b3461011d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a08136011261011d576004359067ffffffffffffffff9081831161011d57606081843603011261011d576024359082821161011d57604090823603011261011d5760443591821161011d5761023e926101fd610217933690600401610122565b90610206610153565b9260843594600401906004016102db565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b3461011d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011d5760043573ffffffffffffffffffffffffffffffffffffffff80821680920361011d576102d26020926040516102ca816102bc8782019460243590869091604092825260208201520190565b03601f198101835282610647565b519020610b4c565b60405191168152f35b939294909160009160028354146105b9576002835560409586519182610311602082019232849091604092825260208201520190565b0392610325601f1994858101835282610647565b51902094610347610340876000526001602052604060002090565b5460ff1690565b6105905732867f4d26f9b035ac4dafb21ce257260243ad6adf7e105ac6517fe42bebde1d0828ca8780a361435e916103816020840161066a565b92808452610e0b602085013973ffffffffffffffffffffffffffffffffffffffff998a7f0000000000000000000000000000000000000000000000000000000000000000169889918b5197889560208701956103dc96610a0d565b0382810184526103ec9084610647565b8651928391602083016103fe91610b15565b61040791610b15565b0390810182526104179082610647565b6104219083610d1c565b9461042b83610b4c565b90808716908115928315610583575b50505061055257823b156100a15783517f4420e48600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86166004820152928390602490829084905af190811561054d576104e5926104ba92610534575b506000526001602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b5173ffffffffffffffffffffffffffffffffffffffff8216815233907f51cd0090f3c14be5310fb02efc5d7f8aa69cff235becdf1d944ee6c420b2deb690602090a2906105326001600055565b565b8061054161054792610612565b80610112565b386104a9565b610b40565b83517f8e6ae65f00000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b161415905038808061043a565b600488517f0ced3043000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161062657604052565b6105e3565b6040810190811067ffffffffffffffff82111761062657604052565b90601f601f19910116810190811067ffffffffffffffff82111761062657604052565b906105326040519283610647565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18236030181121561011d570190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561011d57016020813591019167ffffffffffffffff821161011d57813603831361011d57565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218236030181121561011d570190565b359067ffffffffffffffff8216820361011d57565b908281815260208091019360208360051b82010194846000925b85841061078d575050505050505090565b9091929394959685806107b583601f1986600196030188526107af8c886106aa565b906106fa565b99019401940192959493919061077c565b67ffffffffffffffff91826107da8361074d565b16815260208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181121561011d5782019260208435940190841161011d578360051b3603811361011d576108c261086761084c6108cd936108db9760e0602088015260e0870191610762565b61085960408701876106aa565b9086830360408801526106fa565b6108876108766060870161074d565b67ffffffffffffffff166060860152565b6108a76108966080870161074d565b67ffffffffffffffff166080860152565b6108b460a08601866106aa565b9085830360a08701526106fa565b9260c08101906106aa565b9160c08185039101526106fa565b90565b80357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818236030181121561011d57810191604081528235604082015260208301356060820152604083013573ffffffffffffffffffffffffffffffffffffffff811680910361011d576109756109646108db9561098093608086015260608101906106aa565b608060a086015260c08501916106fa565b92602081019061071b565b9060208184039101526107c6565b9082818152602080910193818360051b82010194846000925b8584106109b8575050505050505090565b90919293949596858082601f1985600195030187526109d78b87610678565b9082806109f660406109e986806106aa565b90918087528601916106fa565b9301359101529901940194019295949391906109a7565b9190969593949660a08352803560a0840152602081013593600485101561011d5761053296610acc610af994610abe610a55610ada9660809a60c08b01526040810190610678565b606060e08a0152610a8d610a828a6101006040610a7286806106aa565b92909301526101408d01916106fa565b9160208101906106aa565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008b8403016101208c01526106fa565b9087820360208901526108de565b91858303604087015261098e565b73ffffffffffffffffffffffffffffffffffffffff9097166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b9081519160005b838110610b2d575050016000815290565b8060208092840101518185015201610b1c565b6040513d6000823e3d90fd5b6040519060208201907fff0000000000000000000000000000000000000000000000000000000000000082523060601b602184015260358301527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605583015260558252608082019180831067ffffffffffffffff84111761062657827f010000000000000000000000000000000000000000000000000000000000000060b6610c79946108db9660405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610c5d8161062b565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051906040820182811067ffffffffffffffff82111761062657604052601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b3d15610d17573d9067ffffffffffffffff82116106265760405191610d0b6020601f19601f8401160184610647565b82523d6000602084013e565b606090565b9190610d26610c92565b92610d3081610b4c565b93843b610de0576020815191016000f573ffffffffffffffffffffffffffffffffffffffff811615610db65781600092918360208194519301915af1610d74610cdc565b50158015610dad575b610d8357565b60046040517f53de54b9000000000000000000000000000000000000000000000000000000008152fd5b50813b15610d7d565b60046040517fbbd2fe87000000000000000000000000000000000000000000000000000000008152fd5b60046040517fcd43efa1000000000000000000000000000000000000000000000000000000008152fdfe60e06040523461110b5761435e803803809161001c8260e061154c565b60e03960a0811261110b5760e0516001600160401b03811161110b5760e001906060828260e001031261110b5760405191610056836114e0565b805183526020810151600481101561110b5760208401526040810151906001600160401b03821161110b57016040818360e001031261110b576040519061009c826114fb565b80516001600160401b03811161110b576100bc908460e001908301611592565b82526020810151906001600160401b03821161110b576100e1918460e0019101611592565b60208201526040830152610100516001600160401b03811161110b5760e0016040818360e001031261110b576040519061011a826114fb565b80516001600160401b03811161110b5781016080818560e001031261110b576040519061014682611516565b8051825260208101516020830152610160604082016115e6565b60408301526060810151906001600160401b03821161110b57610188918660e0019101611592565b6060820152825260208101516001600160401b03811161110b5760e08183018560e001031261110b57604051916101be83611531565b6101c98282016115fa565b8352808201602001516001600160401b03811161110b578560e001601f828585010101121561110b578083830101516102018161160e565b9161020f604051938461154c565b818352602083018860e00160208460051b848989010101011161110b576020828787010101905b60208460051b8489890101010182106114a557505050506020840152808201604001516001600160401b03811161110b57610279908660e0019084840101611592565b604084015261028c6060838301016115fa565b606084015261029f6080838301016115fa565b608084015280820160a001516001600160401b03811161110b576102cb908660e0019084840101611592565b60a084015280820160c001516001600160401b03811161110b576102f5928660e001920101611592565b60c08201526020820152610120516001600160401b03811161110b5760e0830160ff8201121561110b578060e0015161032d8161160e565b9361033b604051958661154c565b8185526020850160e08201610100600585901b8601011161110b576101008401905b610100600585901b86010182106114275787878761037c6101406115e6565b906103886101606115e6565b602082015182516001600160a01b03851615611415576001600160a01b038316156114035760a082015151156113f15760c082015151156113df57604001516001600160a01b0316156113cd57610900608052604051906103e8826114fb565b600182526020368184013760016103fe8361164a565b5260805190516040805163338c1f5160e01b81526001600160401b039092166004830152602482015282516044820181905290926001600160a01b0390921691839160648301916020019060005b8181106113b15750505091818060009403915afa90811561111757600091611147575b50610480602061048a92015161164a565b51518051906116e4565b901561113557600080546001600160a01b0319166001600160a01b0392909216919091179055600180558451156111235761050f60c06109028060a0526040880151906104fd602083519301519260405195869485938493631e879a6d60e11b8552604060048601526044850190611625565b83810360031901602485015290611625565b03915afa801561111757611068575b506001600160a01b031660c05260005b83518110156106c15760208160051b8501015160105490680100000000000000008210156106955760018201806010558210156106ab576010600052805180517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67292916001600160401b038211610695576105bd826105b28760011b870154611657565b8760011b87016116a8565b602090601f831160011461061857926105f8836001989796946020948a9760009261060d575b50508160011b916000199060031b1c19161790565b85851b8401555b015192821b0101550161052e565b015190508e806105e3565b908560011b850160005260206000209160005b601f198516811061067d575083602093600199989795938a9794938894601f19811610610664575b505050811b0185851b8401556105ff565b015160001960f88460031b161c191690558d8080610653565b9192602060018192868501518155019401920161062b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b50835160025560208401518460048210156110525760409160ff801960035416911617600355015191825192835160018060401b03811161069557610707600454611657565b601f8111611003575b506020601f8211600114610f94579080610745926020959697600092610f895750508160011b916000199060031b1c19161790565b6004555b015180519092906001600160401b03811161069557610769600554611657565b601f8111610f56575b506020601f8211600114610eec5781906107a4939495600092610bf95750508160011b916000199060031b1c19161790565b6005555b8051805160065560208101516007556040810151600880546001600160a01b0319166001600160a01b0392909216919091179055606001518051906001600160401b038211610695576107fc600954611657565b601f8111610eaf575b50602090601f8311600114610e3757918061083a9260209594600092610b305750508160011b916000199060031b1c19161790565b6009555b01519060018060401b0382511660018060401b0319600a541617600a55602082015180519068010000000000000000821161069557600b5482600b55808310610da6575b50600b60009081527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db992916020015b828210610cbd5760408601518051869088906001600160401b038111610695576108dc600c54611657565b601f8111610c6e575b506020601f8211600114610c04578190610917939495600092610bf95750508160011b916000199060031b1c19161790565b600c555b6060810151600d805460808401516001600160801b03199091166001600160401b039384161760409190911b6fffffffffffffffff00000000000000001617905560a0820151805191821161069557610975600e54611657565b601f8111610baa575b50602090601f8311600114610b3b5791806109b39260c09594600092610b305750508160011b916000199060031b1c19161790565b600e555b015180519091906001600160401b038111610695576109d7600f54611657565b601f8111610ad6575b50602092601f8211600114610a7057610a1292938291600092610a655750508160011b916000199060031b1c19161790565b600f555b60118054610100600160a81b03191660089290921b610100600160a81b0316919091179055604051612ac2908161187c82396080518161221b015260a05181611e07015260c051816107c40152f35b0151905084806105e3565b601f19821693600f60005260206000209160005b868110610abe5750836001959610610aa5575b505050811b01600f55610a16565b015160001960f88460031b161c19169055838080610a97565b91926020600181928685015181550194019201610a84565b600f600052610b20907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802601f840160051c81019160208510610b26575b601f0160051c0190611691565b836109e0565b9091508190610b13565b0151905086806105e3565b90600e60005260206000209160005b601f1985168110610b92575091839160019360c09695601f19811610610b79575b505050811b01600e556109b7565b015160001960f88460031b161c19169055858080610b6b565b91926020600181928685015181550194019201610b4a565b600e600052610bf3907fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd601f850160051c81019160208610610b2657601f0160051c0190611691565b8461097e565b0151905085806105e3565b600c60005260206000209060005b601f1984168110610c565750600193949583601f19811610610c3d575b505050811b01600c5561091b565b015160001960f88460031b161c19169055848080610c2f565b9091602060018192858a015181550193019101610c12565b600c600052610cb7907fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7601f840160051c81019160208510610b2657601f0160051c0190611691565b846108e5565b80518051906001600160401b03821161069557610ce482610cde8854611657565b886116a8565b602090601f8311600114610d365792610d1c83600195946020948796600092610d2b5750508160011b916000199060031b1c19161790565b87555b019401910190926108b1565b015190508c806105e3565b908660005260206000209160005b601f1985168110610d8e575083602093600196938796938794601f19811610610d75575b505050811b018755610d1f565b015160001960f88460031b161c191690558b8080610d68565b91926020600181928685015181550194019201610d44565b600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99081019083015b818110610de05750610882565b80610ded60019254611657565b80610dfa575b5001610dd3565b601f81118314610e105750600081555b87610df3565b600090828252610e2e601f60208420920160051c8201858301611691565b81835555610e0a565b6009600090815260008051602061433e833981519152929190601f198516905b818110610e975750916001939185602097969410610e7e575b505050811b0160095561083e565b015160001960f88460031b161c19169055858080610e70565b92936020600181928786015181550195019301610e57565b6009600052610ee69060008051602061433e833981519152601f850160051c81019160208610610b2657601f0160051c0190611691565b84610805565b600560005260206000209060005b601f1984168110610f3e5750600193949583601f19811610610f25575b505050811b016005556107a8565b015160001960f88460031b161c19169055848080610f17565b9091602060018192858a015181550193019101610efa565b610f839060056000526020600020601f840160051c81019160208510610b2657601f0160051c0190611691565b84610772565b0151905087806105e3565b600460005260206000209560005b601f1984168110610feb57509582916020959697600194601f19811610610fd2575b505050811b01600455610749565b015160001960f88460031b161c19169055868080610fc4565b82820151885560019097019660209283019201610fa2565b600460005261104c907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81019160208510610b2657601f0160051c0190611691565b85610710565b634e487b7160e01b600052602160045260246000fd5b60c03d60c011611110575b61107d818361154c565b60c082828101031261110b5760606040519161109883611516565b6110a1846115fa565b83526110af602085016115fa565b60208401526110c0604085016115fa565b60408401528301839003605f19011261110b5760609060a0604051936110e5856114e0565b6110f08482016115fa565b8552608081015160208601520151604084015201528561051e565b600080fd5b503d611073565b6040513d6000823e3d90fd5b60405163107d9ce760e31b8152600490fd5b6040516307456b9160e21b8152600490fd5b903d8082843e611157818461154c565b60208382810103126113ad578251926001600160401b0384116113a957604084820183830103126113a9576040519361118f856114fb565b818101516001600160401b0381116113a55760e0818385010185850103126113a557604051906111be82611531565b6111cb81848601016115fa565b82526111dd60208285870101016115fa565b60208301526111f260408285870101016115fa565b604083015260608184860101015160038110156113925760608301528383018101608001516001600160401b038111611392576112629161123e60c0928888019083888a010101611592565b608085015261125360a08287890101016115fa565b60a085015284860101016115fa565b60c0820152855281810160200151936001600160401b0385116113a257838301601f86848601010112156113a257848284010151926112a08461160e565b956112ae604051978861154c565b848752602087019386830160208760051b848487010101011161139e576020828285010101945b60208760051b848487010101018610611302575050505050602085019390935250610480915061046f9050565b85516001600160401b03811161139a576040858401850182018a870103601f19011261139a5760405190611335826114fb565b85840185018101602001516001600160401b038111611396579061136960409260208d8a0191848a8a8d0101010101611592565b8352858588010101015160038110156113925760208281019190915290825295860195016112d5565b8680fd5b8780fd5b8580fd5b8380fd5b80fd5b8480fd5b8280fd5b5080fd5b825160030b84528694506020938401939092019160010161044c565b604051630695a62360e51b8152600490fd5b604051636fc5f47160e01b8152600490fd5b60405163460be67160e11b8152600490fd5b6040516311a1e69760e01b8152600490fd5b60405163bcda548360e01b8152600490fd5b8151906001600160401b03821161110b5760408683018503601f19011261110b5760405191611455836114fb565b6101008782010151916001600160401b03831161110b5760209360408361148b8b88809881988d60e0019360e001010101611592565b83528a60e00101015183820152815201920191905061035d565b8151906001600160401b03821161110b5760208092916114d389838f95898e839860e0019401010101611592565b8152019201919050610236565b606081019081106001600160401b0382111761069557604052565b604081019081106001600160401b0382111761069557604052565b608081019081106001600160401b0382111761069557604052565b60e081019081106001600160401b0382111761069557604052565b601f909101601f19168101906001600160401b0382119082101761069557604052565b60005b8381106115825750506000910152565b8181015183820152602001611572565b81601f8201121561110b5780516001600160401b03811161069557604051926115c5601f8301601f19166020018561154c565b8184526020828401011161110b576115e3916020808501910161156f565b90565b51906001600160a01b038216820361110b57565b51906001600160401b038216820361110b57565b6001600160401b0381116106955760051b60200190565b9060209161163e8151809281855285808601910161156f565b601f01601f1916010190565b8051156106ab5760200190565b90600182811c92168015611687575b602083101461167157565b634e487b7160e01b600052602260045260246000fd5b91607f1691611666565b81811061169c575050565b60008155600101611691565b9190601f81116116b757505050565b6116e2926000526020600020906020601f840160051c83019310610b2657601f0160051c0190611691565b565b9061060f60f31b61ffff60f01b602084015116148060011b908082046002149015171561173f576028018060281161173f5781036117355761172591611755565b90916001600160a01b0390911690565b5050600090600090565b634e487b7160e01b600052601160045260246000fd5b919060209061060f60f31b61ffff60f01b60208601511614936001928560011b958087046002149015171561173f57929190600095935b82851061179e57505050505060019190565b909192939560ff6117b88160f81b848a8701015116611809565b1690600f82116117f957600481811b91808304601014901517156117e45750019584019392919061178c565b601190634e487b7160e01b6000525260246000fd5b5050505050509050600090600090565b60f81c602f811180611871575b1561182557602f190160ff1690565b6060811180611867575b1561183e576056190160ff1690565b604081118061185d575b15611857576036190160ff1690565b5060ff90565b5060478110611848565b506067811061182f565b50603a811061181656fe6080604052600436101561001257600080fd5b6000803560e01c9081631c9feaa5146100ba57508063229e81fb146100b557806342859ab3146100b05780635a509280146100ab57806362b61c8b146100a657806378b90337146100a1578063819ef8ba1461009c57806388328a6914610097578063b3d7ad48146100925763cad31c741461008d57600080fd5b611414565b6112ef565b6111b6565b6110d0565b610ce8565b610b10565b610a0b565b610643565b610582565b346100db57806003193601126100db5760ff60115416151560805260206080f35b80fd5b60009103126100e957565b600080fd5b90600182811c92168015610137575b602083101461010857565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916100fd565b60045460009291610151826100ee565b808252916020906001908181169081156101d05750600114610174575b50505050565b9293945060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000935b8585106101bd57505050602092500101903880808061016e565b80548585018401529382019381016101a3565b91505060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b0101903880808061016e565b60055460009291610224826100ee565b808252916020906001908181169081156101d057506001146102465750505050565b9293945060056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0926000935b85851061028f57505050602092500101903880808061016e565b8054858501840152938201938101610275565b600e54600092916102b2826100ee565b808252916020906001908181169081156101d057506001146102d45750505050565b92939450600e6000527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd926000935b85851061031d57505050602092500101903880808061016e565b8054858501840152938201938101610303565b600f5460009291610340826100ee565b808252916020906001908181169081156101d057506001146103625750505050565b92939450600f6000527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000935b8585106103ab57505050602092500101903880808061016e565b8054858501840152938201938101610391565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761040957604052565b6103be565b67ffffffffffffffff811161040957604052565b60a0810190811067ffffffffffffffff82111761040957604052565b6080810190811067ffffffffffffffff82111761040957604052565b60e0810190811067ffffffffffffffff82111761040957604052565b6060810190811067ffffffffffffffff82111761040957604052565b6020810190811067ffffffffffffffff82111761040957604052565b90601f601f19910116810190811067ffffffffffffffff82111761040957604052565b604051906104e9826104e2816102a2565b03836104ae565b565b604051906104e9826104e281610330565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004111561053557565b6104fc565b60005b83811061054d5750506000910152565b818101518382015260200161053d565b90601f19601f60209361057b8151809281875287808801910161053a565b0116010190565b346100e95760006003193601126100e95760025460ff600354166040908151906105ab826103ed565b82516105c1816105ba81610141565b03826104ae565b82528251906105d3826104e281610214565b602083019182528351948552600481101561053557849361063f9361060e9260208701526060828701525190606086015260a085019061055d565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084830301608085015261055d565b0390f35b346100e95760a06003193601126100e957600460026001541461097a5760026001556011549073ffffffffffffffffffffffffffffffffffffffff91828160081c1633036109515760ff16610929576106a161069d611db8565b1590565b610901576106f3906106b16114b6565b92604051937f62b61c8b0000000000000000000000000000000000000000000000000000000085528480600095869360843560643560243589358a87016115da565b0381305afa93841561087957839084956108da575b50610712906116c7565b61076e602060405161073c8161072e8985830160209181520190565b03601f1981018352826104ae565b604051809381927fcad31c740000000000000000000000000000000000000000000000000000000083528783016119c8565b038187305af18015610879576107b79185916108ab575b5060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00601154169115151617601155565b60115460ff16610882575b7f00000000000000000000000000000000000000000000000000000000000000001690813b1561087e57604080517faa733a4400000000000000000000000000000000000000000000000000000000815232928101928352602083018690529392849290918391859183910103925af1801561087957610860575b5060115460ff1661084d60018055565b6040805191151582526020820192909252f35b8061086d6108739261040e565b806100de565b3861083d565b611649565b8280fd5b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e8380a16107c2565b6108cd915060203d6020116108d3575b6108c581836104ae565b8101906117f3565b38610785565b503d6108bb565b61071295506108fb91503d8086833e6108f381836104ae565b81019061156c565b94610708565b6040517f741926a1000000000000000000000000000000000000000000000000000000008152fd5b6040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b506040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b6040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b908160809103126100e95790565b6020815273ffffffffffffffffffffffffffffffffffffffff80835116602083015260208301511660408201526040820151606082015260a06080610a026060850151838386015260c085019061055d565b93015191015290565b346100e95760206003193601126100e95760043567ffffffffffffffff81116100e957610a3f61063f9136906004016109a2565b610a47611aa5565b5073ffffffffffffffffffffffffffffffffffffffff90610aac826000541692604083013590610a7682611ad0565b610a836060850185611af8565b91909260405196610a9388610422565b8752166020860152602084013560408601523691611b49565b6060830152356080820152604051918291826109b0565b9181601f840112156100e95782359167ffffffffffffffff83116100e9576020808501948460051b0101116100e957565b929190610b0b60209160408652604086019061055d565b930152565b346100e95760c06003193601126100e95767ffffffffffffffff6084358181116100e957610b42903690600401610ac3565b60a4929192359182116100e957610ca8610ca3610cd194610b6a610cc19536906004016109a2565b93610c88610b8d610c81610b7c6114c9565b97610b92610b8d60208301356127cc565b6122c6565b610b9b8a611baf565b52610ba589611baf565b50610bb4610b8d6004356127cc565b610bbd8a611bc1565b52610bc789611bc1565b50610bd6610b8d6044356127cc565b610bdf8a611bd1565b52610be989611bd1565b50610bf8610b8d6064356127cc565b610c018a611be1565b52610c0b89611be1565b50610c1a610b8d6024356127cc565b610c238a611bf1565b52610c2d89611bf1565b50610c42610c3d60408301611aee565b612285565b610c4b8a611c01565b52610c5589611c01565b50610c63610b8d82356127cc565b610c6c8a611c11565b52610c7689611c11565b506060810190611af8565b3691611b49565b610c9186611c21565b52610c9b85611c21565b503691611c57565b61244c565b610cb182611c32565b52610cbb81611c32565b5061244c565b610ccc610b8d6126ed565b61257c565b805160208201209061063f60405192839283610af4565b346100e95760006003193601126100e9576020610d03611db8565b6040519015158152f35b60095460009291610d1d826100ee565b808252916020906001908181169081156101d05750600114610d3f5750505050565b9293945060096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af926000935b858510610d8857505050602092500101903880808061016e565b8054858501840152938201938101610d6e565b600c5460009291610dab826100ee565b808252916020906001908181169081156101d05750600114610dcd5750505050565b92939450600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7926000935b858510610e1657505050602092500101903880808061016e565b8054858501840152938201938101610dfc565b805460009392610e38826100ee565b91828252602093600191600181169081600014610ea05750600114610e5f575b5050505050565b90939495506000929192528360002092846000945b838610610e8c57505050500101903880808080610e58565b805485870183015294019385908201610e74565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b010191503880808080610e58565b604051906104e9826104e281610d9b565b67ffffffffffffffff81116104095760051b60200190565b600b5490610f1382610eee565b916040610f2360405194856104ae565b81845283602080910191600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9906000935b858510610f6757505050505050565b60018481928451610f7c816105ba818a610e29565b815201930194019391610f58565b90808251908181526020809101926020808460051b8301019501936000915b848310610fb95750505050505090565b9091929394958480610fd783601f1986600196030187528a5161055d565b9801930193019194939290610fa9565b61103860606110cd9493604084528051604085015260208101518285015273ffffffffffffffffffffffffffffffffffffffff60408201511660808501520151608060a084015260c083019061055d565b90602081830391015267ffffffffffffffff825116815260c06110bc611082611070602086015160e0602087015260e0860190610f8a565b6040860151858203604087015261055d565b60608581015167ffffffffffffffff169085015260808581015167ffffffffffffffff169085015260a085015184820360a086015261055d565b9201519060c081840391015261055d565b90565b346100e95760006003193601126100e957604080516110ee8161043e565b6006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416828201528151611127816105ba81610d0d565b606082015261063f82519261113b8461045a565b61119267ffffffffffffffff80600a54168652611156610f06565b6020870152611163610edd565b86840152600d5467ffffffffffffffff828216166060880152831c16608086019067ffffffffffffffff169052565b61119a6104d1565b60a08501526111a76104eb565b60c08501525192839283610fe7565b346100e9576000806003193601126100db5760ff60115416156112c557604051908082601254916111e6836100ee565b928383526020946001918660018216918260001461128457505060011461122a575b5050611216925003836104ae565b61063f60405192828493845283019061055d565b90859250601282527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34445b85831061126c57505061121693508201013880611208565b80548389018501528794508693909201918101611254565b915093506112169592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611208565b60046040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b346100e9576000806003193601126100db57611309611aa5565b50604051907f5a509280000000000000000000000000000000000000000000000000000000008252602060048301528082806113476024820161159d565b0381305afa908115610879578091611368575b6040518061063f84826109b0565b90503d8082843e61137981846104ae565b820160208382031261141057825167ffffffffffffffff9384821161140c57019260a08483031261087e57604051926113b184610422565b84516113bc81611ad0565b845260208501516113cc81611ad0565b60208501526040850151604085015260608501519182116100db5750926113fa60809261063f95830161152a565b6060840152015160808201523861135a565b8380fd5b5080fd5b346100e9576003196060813601126100e95760043567ffffffffffffffff918282116100e95760e09082360301126100e957602435918083116100e957366023840112156100e9578260040135928184116100e95736602485830101116100e9576044359182116100e95761063f936114a4936114976024943690600401610ac3565b9490930190600401612176565b60405190151581529081906020820190565b6040516114c281610492565b6000815290565b60405190610140820182811067ffffffffffffffff82111761040957604052600982528160005b61012081106114fd575050565b8060606020809385010152016114f0565b67ffffffffffffffff811161040957601f01601f191660200190565b81601f820112156100e95780516115408161150e565b9261154e60405194856104ae565b818452602082840101116100e9576110cd916020808501910161053a565b91906040838203126100e957825167ffffffffffffffff81116100e95760209161159791850161152a565b92015190565b60806110cd916006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416604082015281606082015201610d0d565b9293608094611609936110cd9793865260208601526040850152606084015260c08484015260c0830190610f8a565b9060a08183039101526006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416604082015281606082015201610d0d565b6040513d6000823e3d90fd5b601f8111611661575050565b60009060126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906020601f850160051c830194106116bd575b601f0160051c01915b8281106116b257505050565b8181556001016116a6565b909250829061169d565b90815167ffffffffffffffff8111610409576116ed816116e86012546100ee565b611655565b602080601f831160011461174d5750819061173d9394600092611742575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b601255565b01519050388061170b565b90601f1983169461178060126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344490565b926000905b8782106117db5750508360019596106117a4575b505050811b01601255565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611799565b80600185968294968601518155019501930190611785565b908160209103126100e9575180151581036100e95790565b80600b5480825260208092019160208260051b85010193600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9936000915b84831061185d5750505050505090565b90919293949584600161187a83601f19868496030187528a610e29565b980193019301919493929061184d565b8060105490818152602080910191600591808260051b86010194600094601086527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6729580925b8584106118e257505050505050505090565b9091929394959697601f19828203018452856040808352898b8692815490611909826100ee565b8091880152606091600194858216918260001461198b57505060011461194a575b5050015492820192909252909860020197969594600101930191906118d0565b909180945088528488209088915b81831061196d5750508501019183600161192a565b8496929491939550805486868a0101520192018d93918b9593611958565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168985015291151590911b87019091019350849050600161192a565b611a976110cd92606083526119fb606084016119ed600a5467ffffffffffffffff1690565b67ffffffffffffffff169052565b60e06080840152611a89611a12610140850161180b565b611a79611a497fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa092838882030160a0890152610d9b565b600d5467ffffffffffffffff80821660c08a015260409190911c1660e088015282878203016101008801526102a2565b9085820301610120860152610330565b90838203602085015261055d565b90604081830391015261188a565b60405190611ab282610422565b60006080838281528260208201528260408201526060808201520152565b73ffffffffffffffffffffffffffffffffffffffff8116036100e957565b356110cd81611ad0565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e9570180359067ffffffffffffffff82116100e9576020019181360383136100e957565b929192611b558261150e565b91611b6360405193846104ae565b8294818452818301116100e9578281602093846000960137010152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115611bbc5760200190565b611b80565b805160011015611bbc5760400190565b805160021015611bbc5760600190565b805160031015611bbc5760800190565b805160041015611bbc5760a00190565b805160051015611bbc5760c00190565b805160061015611bbc5760e00190565b805160071015611bbc576101000190565b805160081015611bbc576101200190565b8051821015611bbc5760209160051b010190565b92919092611c6484610eee565b91611c7260405193846104ae565b829480845260208094019060051b8301928284116100e95780915b848310611c9c57505050505050565b823567ffffffffffffffff81116100e957820184601f820112156100e9578691611ccc8683858095359101611b49565b815201920191611c8d565b67ffffffffffffffff8116036100e957565b8091039060c082126100e95760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa060405193611d258561043e565b8351611d3081611cd7565b85526020840151611d4081611cd7565b60208601526040840151611d5381611cd7565b604086015201126100e95760a060405191611d6d83610476565b6060810151611d7b81611cd7565b83526080810151602084015201516040820152606082015290565b6110cd9060408152611daa60408201610141565b906020818303910152610214565b6040517f3d0f34da00000000000000000000000000000000000000000000000000000000815260c08180611dee60048201611d96565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561087957600091611ea8575b5060035460ff16611e488161052b565b60018103611e6157506060015160400151600254111590565b611e6a8161052b565b611e7e576060015160400151600254101590565b60046040517f951a55bf000000000000000000000000000000000000000000000000000000008152fd5b611eca915060c03d60c011611ed0575b611ec281836104ae565b810190611ce9565b38611e38565b503d611eb8565b356110cd81611cd7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e9570180359067ffffffffffffffff82116100e957602001918160051b360383136100e957565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100e957016020813591019167ffffffffffffffff82116100e95781360383136100e957565b90918092808252602080920191808260051b8601019484600080925b858410611fd457505050505050505090565b9091929394959697601f1982820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18536030181121561140c57866001928682930190828061203a604061202d8680611f56565b9091808752860191611f35565b9301359101529a01980196959401929190611fc2565b9e9b999f9d9c9a989694918f969493906120859167ffffffffffffffff610140941689526020938060208b0152890191611f35565b956040818803910152818652602086019560208360051b82010196846000925b85841061213d5750505050505050946121088c9d60a06120f76104e99e9f986101209e9c986120e96121359f9d99612119996121269e8e6060818503910152611f35565b918b830360808d0152611fa6565b97019067ffffffffffffffff169052565b67ffffffffffffffff1660c08d0152565b8a830360e08c0152611f35565b91878303610100890152611f35565b930160019052565b9091929394959885806121658361215f8e601f198860019803018a5288611f56565b90611f35565b9b01940194019295949391906120a5565b909293919361218482611ed7565b926121926020840184611ee1565b9390926121a26040830183611af8565b919093606084016121b290611ed7565b916121bf60808601611ed7565b936121cd60a0870187611af8565b97909660c081016121dd91611af8565b9a90996040519e8f9e8f7f07d145e90000000000000000000000000000000000000000000000000000000081526004019e6122179f612050565b03817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a602094600091f19081156108795760009161226c575090565b6110cd915060203d6020116108d3576108c581836104ae565b6110cd906040519074140000000000000000000000000000000000000000186014820152603481016040526122c6565b908151811015611bbc570160200190565b90600091805192600193600181149081612434575b50156122e657509150565b81519360388510156123405750926110cd92937fff0000000000000000000000000000000000000000000000000000000000000061232b61232561260e565b936128bb565b60f81b16901a61233a82611baf565b5361257c565b8190806001915b612404575b505061235f61235a8261289f565b612640565b917fff0000000000000000000000000000000000000000000000000000000000000061239261238d846128bb565b6128ad565b8160f89160f81b16831a6123a586611baf565b5360015b848111156123c15750505050506110cd92935061257c565b80836123ea6123e46123de6123d96123ff968b6126b3565b6128e4565b8d61284f565b60ff1690565b841b16851a6123f982896122b5565b536126c0565b6123a9565b9091612410838861284f565b1561242e57612421612427916126c0565b92612888565b9080612347565b9161234c565b905015611bbc576080602083015160f81c10386122db565b6124559061297e565b9081516000603882106000146124ae5750916110cd91927fff0000000000000000000000000000000000000000000000000000000000000061249e61249861260e565b926128c9565b60f81b1660001a61233a82611baf565b916001925b6124bd848461284f565b156124da576124ce6124d4916126c0565b93612888565b926124b3565b9092509290926124ec61235a8261289f565b907fff0000000000000000000000000000000000000000000000000000000000000061251a61238d836128c9565b8160f89160f81b1660001a61252e85611baf565b5360015b8381111561254957505050506110cd92935061257c565b80836125676123e46125616123d9612577968a6126b3565b8c61284f565b841b1660001a6123f982886122b5565b612532565b6040518151808252909290830191602083810192818301828088015b8681106125e55750505080518094875182018852950194828087019201905b8281106125d6575050505091603f91601f199351011501011660405290565b815181529083019083016125b7565b8251815291810191849101612598565b60405190612602826103ed565b60208083523683820137565b6040519061261b826103ed565b6001825260203681840137565b60405161263481610492565b60008152906000368137565b9061264a8261150e565b61265760405191826104ae565b828152601f19612667829461150e565b0190602036910137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60200390602082116126ae57565b612671565b919082039182116126ae57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146126ae5760010190565b6126f56125f5565b90602091600260208201526000926000905b808210612783575b5061271c61235a826126a0565b9160005b835181101561277b5760019061276861274261273b866126c0565b95856122b5565b517fff000000000000000000000000000000000000000000000000000000000000001690565b871a61277482876122b5565b5301612720565b509193505050565b906127b961279461274283866122b5565b7fff000000000000000000000000000000000000000000000000000000000000001690565b6127c65760010190612707565b9061270f565b906127d56125f5565b60209260208201526000926000905b80821061282b575b506127f961235a826126a0565b9160005b835181101561277b5760019061281861274261273b866126c0565b871a61282482876122b5565b53016127fd565b9061283c61279461274283866122b5565b61284957600101906127e4565b906127ec565b8115612859570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b908160081b9180830461010014901517156126ae57565b90600182018092116126ae57565b90603782018092116126ae57565b90608082018092116126ae57565b9060c082018092116126ae57565b919082018092116126ae57565b601f81116126ae576101000a90565b156128fa57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f416e206974656d20696e20746865206c69737420746f20626520524c5020656e60448201527f636f646564206973206e756c6c2e0000000000000000000000000000000000006064820152fd5b805115612a235790600091825b81518410156129ca576129c26001916129b06129a78786611c43565b515115156128f3565b6129ba8685611c43565b5151906128d7565b93019261298b565b6129d691929350612640565b906020808301936000945b8351861015612a1b57612a13600191612a096129fd8988611c43565b51868151910183612a2c565b6129ba8887611c43565b9501946129e1565b509350505090565b506110cd612628565b92905b602093848410612a6457815181528481018091116126ae579381018091116126ae5791601f1981019081116126ae5791612a2f565b9290919350602003602081116126ae57612a7d906128e4565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116126ae57518251821691191617905256fea164736f6c6343000819000a6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7afa164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca83" + ], + "transaction": { + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "gas": "0x66287c", + "value": "0x0", + "input": "0xcdcb760a6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003ea0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000522460a034607357601f61520438819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607357516001600160a01b038116908190036073576001600055608052604051615175908161008f823960805181818160e901526103a60152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c90816306433b1b146100a45781630b0fdb3d14610055575080633dc48a341461005057637fddd6021461004b57600080fd5b610242565b610176565b346100a15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15760ff60406020926004358152600184522054166040519015158152f35b80fd5b346100a157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b600091031261011d57565b600080fd5b9181601f8401121561011d5782359167ffffffffffffffff831161011d576020808501948460051b01011161011d57565b6064359073ffffffffffffffffffffffffffffffffffffffff8216820361011d57565b3461011d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a08136011261011d576004359067ffffffffffffffff9081831161011d57606081843603011261011d576024359082821161011d57604090823603011261011d5760443591821161011d5761023e926101fd610217933690600401610122565b90610206610153565b9260843594600401906004016102db565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b3461011d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011d5760043573ffffffffffffffffffffffffffffffffffffffff80821680920361011d576102d26020926040516102ca816102bc8782019460243590869091604092825260208201520190565b03601f198101835282610647565b519020610b4c565b60405191168152f35b939294909160009160028354146105b9576002835560409586519182610311602082019232849091604092825260208201520190565b0392610325601f1994858101835282610647565b51902094610347610340876000526001602052604060002090565b5460ff1690565b6105905732867f4d26f9b035ac4dafb21ce257260243ad6adf7e105ac6517fe42bebde1d0828ca8780a361435e916103816020840161066a565b92808452610e0b602085013973ffffffffffffffffffffffffffffffffffffffff998a7f0000000000000000000000000000000000000000000000000000000000000000169889918b5197889560208701956103dc96610a0d565b0382810184526103ec9084610647565b8651928391602083016103fe91610b15565b61040791610b15565b0390810182526104179082610647565b6104219083610d1c565b9461042b83610b4c565b90808716908115928315610583575b50505061055257823b156100a15783517f4420e48600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86166004820152928390602490829084905af190811561054d576104e5926104ba92610534575b506000526001602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b5173ffffffffffffffffffffffffffffffffffffffff8216815233907f51cd0090f3c14be5310fb02efc5d7f8aa69cff235becdf1d944ee6c420b2deb690602090a2906105326001600055565b565b8061054161054792610612565b80610112565b386104a9565b610b40565b83517f8e6ae65f00000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b161415905038808061043a565b600488517f0ced3043000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161062657604052565b6105e3565b6040810190811067ffffffffffffffff82111761062657604052565b90601f601f19910116810190811067ffffffffffffffff82111761062657604052565b906105326040519283610647565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18236030181121561011d570190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561011d57016020813591019167ffffffffffffffff821161011d57813603831361011d57565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218236030181121561011d570190565b359067ffffffffffffffff8216820361011d57565b908281815260208091019360208360051b82010194846000925b85841061078d575050505050505090565b9091929394959685806107b583601f1986600196030188526107af8c886106aa565b906106fa565b99019401940192959493919061077c565b67ffffffffffffffff91826107da8361074d565b16815260208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181121561011d5782019260208435940190841161011d578360051b3603811361011d576108c261086761084c6108cd936108db9760e0602088015260e0870191610762565b61085960408701876106aa565b9086830360408801526106fa565b6108876108766060870161074d565b67ffffffffffffffff166060860152565b6108a76108966080870161074d565b67ffffffffffffffff166080860152565b6108b460a08601866106aa565b9085830360a08701526106fa565b9260c08101906106aa565b9160c08185039101526106fa565b90565b80357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818236030181121561011d57810191604081528235604082015260208301356060820152604083013573ffffffffffffffffffffffffffffffffffffffff811680910361011d576109756109646108db9561098093608086015260608101906106aa565b608060a086015260c08501916106fa565b92602081019061071b565b9060208184039101526107c6565b9082818152602080910193818360051b82010194846000925b8584106109b8575050505050505090565b90919293949596858082601f1985600195030187526109d78b87610678565b9082806109f660406109e986806106aa565b90918087528601916106fa565b9301359101529901940194019295949391906109a7565b9190969593949660a08352803560a0840152602081013593600485101561011d5761053296610acc610af994610abe610a55610ada9660809a60c08b01526040810190610678565b606060e08a0152610a8d610a828a6101006040610a7286806106aa565b92909301526101408d01916106fa565b9160208101906106aa565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008b8403016101208c01526106fa565b9087820360208901526108de565b91858303604087015261098e565b73ffffffffffffffffffffffffffffffffffffffff9097166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b9081519160005b838110610b2d575050016000815290565b8060208092840101518185015201610b1c565b6040513d6000823e3d90fd5b6040519060208201907fff0000000000000000000000000000000000000000000000000000000000000082523060601b602184015260358301527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605583015260558252608082019180831067ffffffffffffffff84111761062657827f010000000000000000000000000000000000000000000000000000000000000060b6610c79946108db9660405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610c5d8161062b565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051906040820182811067ffffffffffffffff82111761062657604052601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b3d15610d17573d9067ffffffffffffffff82116106265760405191610d0b6020601f19601f8401160184610647565b82523d6000602084013e565b606090565b9190610d26610c92565b92610d3081610b4c565b93843b610de0576020815191016000f573ffffffffffffffffffffffffffffffffffffffff811615610db65781600092918360208194519301915af1610d74610cdc565b50158015610dad575b610d8357565b60046040517f53de54b9000000000000000000000000000000000000000000000000000000008152fd5b50813b15610d7d565b60046040517fbbd2fe87000000000000000000000000000000000000000000000000000000008152fd5b60046040517fcd43efa1000000000000000000000000000000000000000000000000000000008152fdfe60e06040523461110b5761435e803803809161001c8260e061154c565b60e03960a0811261110b5760e0516001600160401b03811161110b5760e001906060828260e001031261110b5760405191610056836114e0565b805183526020810151600481101561110b5760208401526040810151906001600160401b03821161110b57016040818360e001031261110b576040519061009c826114fb565b80516001600160401b03811161110b576100bc908460e001908301611592565b82526020810151906001600160401b03821161110b576100e1918460e0019101611592565b60208201526040830152610100516001600160401b03811161110b5760e0016040818360e001031261110b576040519061011a826114fb565b80516001600160401b03811161110b5781016080818560e001031261110b576040519061014682611516565b8051825260208101516020830152610160604082016115e6565b60408301526060810151906001600160401b03821161110b57610188918660e0019101611592565b6060820152825260208101516001600160401b03811161110b5760e08183018560e001031261110b57604051916101be83611531565b6101c98282016115fa565b8352808201602001516001600160401b03811161110b578560e001601f828585010101121561110b578083830101516102018161160e565b9161020f604051938461154c565b818352602083018860e00160208460051b848989010101011161110b576020828787010101905b60208460051b8489890101010182106114a557505050506020840152808201604001516001600160401b03811161110b57610279908660e0019084840101611592565b604084015261028c6060838301016115fa565b606084015261029f6080838301016115fa565b608084015280820160a001516001600160401b03811161110b576102cb908660e0019084840101611592565b60a084015280820160c001516001600160401b03811161110b576102f5928660e001920101611592565b60c08201526020820152610120516001600160401b03811161110b5760e0830160ff8201121561110b578060e0015161032d8161160e565b9361033b604051958661154c565b8185526020850160e08201610100600585901b8601011161110b576101008401905b610100600585901b86010182106114275787878761037c6101406115e6565b906103886101606115e6565b602082015182516001600160a01b03851615611415576001600160a01b038316156114035760a082015151156113f15760c082015151156113df57604001516001600160a01b0316156113cd57610900608052604051906103e8826114fb565b600182526020368184013760016103fe8361164a565b5260805190516040805163338c1f5160e01b81526001600160401b039092166004830152602482015282516044820181905290926001600160a01b0390921691839160648301916020019060005b8181106113b15750505091818060009403915afa90811561111757600091611147575b50610480602061048a92015161164a565b51518051906116e4565b901561113557600080546001600160a01b0319166001600160a01b0392909216919091179055600180558451156111235761050f60c06109028060a0526040880151906104fd602083519301519260405195869485938493631e879a6d60e11b8552604060048601526044850190611625565b83810360031901602485015290611625565b03915afa801561111757611068575b506001600160a01b031660c05260005b83518110156106c15760208160051b8501015160105490680100000000000000008210156106955760018201806010558210156106ab576010600052805180517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67292916001600160401b038211610695576105bd826105b28760011b870154611657565b8760011b87016116a8565b602090601f831160011461061857926105f8836001989796946020948a9760009261060d575b50508160011b916000199060031b1c19161790565b85851b8401555b015192821b0101550161052e565b015190508e806105e3565b908560011b850160005260206000209160005b601f198516811061067d575083602093600199989795938a9794938894601f19811610610664575b505050811b0185851b8401556105ff565b015160001960f88460031b161c191690558d8080610653565b9192602060018192868501518155019401920161062b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b50835160025560208401518460048210156110525760409160ff801960035416911617600355015191825192835160018060401b03811161069557610707600454611657565b601f8111611003575b506020601f8211600114610f94579080610745926020959697600092610f895750508160011b916000199060031b1c19161790565b6004555b015180519092906001600160401b03811161069557610769600554611657565b601f8111610f56575b506020601f8211600114610eec5781906107a4939495600092610bf95750508160011b916000199060031b1c19161790565b6005555b8051805160065560208101516007556040810151600880546001600160a01b0319166001600160a01b0392909216919091179055606001518051906001600160401b038211610695576107fc600954611657565b601f8111610eaf575b50602090601f8311600114610e3757918061083a9260209594600092610b305750508160011b916000199060031b1c19161790565b6009555b01519060018060401b0382511660018060401b0319600a541617600a55602082015180519068010000000000000000821161069557600b5482600b55808310610da6575b50600b60009081527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db992916020015b828210610cbd5760408601518051869088906001600160401b038111610695576108dc600c54611657565b601f8111610c6e575b506020601f8211600114610c04578190610917939495600092610bf95750508160011b916000199060031b1c19161790565b600c555b6060810151600d805460808401516001600160801b03199091166001600160401b039384161760409190911b6fffffffffffffffff00000000000000001617905560a0820151805191821161069557610975600e54611657565b601f8111610baa575b50602090601f8311600114610b3b5791806109b39260c09594600092610b305750508160011b916000199060031b1c19161790565b600e555b015180519091906001600160401b038111610695576109d7600f54611657565b601f8111610ad6575b50602092601f8211600114610a7057610a1292938291600092610a655750508160011b916000199060031b1c19161790565b600f555b60118054610100600160a81b03191660089290921b610100600160a81b0316919091179055604051612ac2908161187c82396080518161221b015260a05181611e07015260c051816107c40152f35b0151905084806105e3565b601f19821693600f60005260206000209160005b868110610abe5750836001959610610aa5575b505050811b01600f55610a16565b015160001960f88460031b161c19169055838080610a97565b91926020600181928685015181550194019201610a84565b600f600052610b20907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802601f840160051c81019160208510610b26575b601f0160051c0190611691565b836109e0565b9091508190610b13565b0151905086806105e3565b90600e60005260206000209160005b601f1985168110610b92575091839160019360c09695601f19811610610b79575b505050811b01600e556109b7565b015160001960f88460031b161c19169055858080610b6b565b91926020600181928685015181550194019201610b4a565b600e600052610bf3907fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd601f850160051c81019160208610610b2657601f0160051c0190611691565b8461097e565b0151905085806105e3565b600c60005260206000209060005b601f1984168110610c565750600193949583601f19811610610c3d575b505050811b01600c5561091b565b015160001960f88460031b161c19169055848080610c2f565b9091602060018192858a015181550193019101610c12565b600c600052610cb7907fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7601f840160051c81019160208510610b2657601f0160051c0190611691565b846108e5565b80518051906001600160401b03821161069557610ce482610cde8854611657565b886116a8565b602090601f8311600114610d365792610d1c83600195946020948796600092610d2b5750508160011b916000199060031b1c19161790565b87555b019401910190926108b1565b015190508c806105e3565b908660005260206000209160005b601f1985168110610d8e575083602093600196938796938794601f19811610610d75575b505050811b018755610d1f565b015160001960f88460031b161c191690558b8080610d68565b91926020600181928685015181550194019201610d44565b600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99081019083015b818110610de05750610882565b80610ded60019254611657565b80610dfa575b5001610dd3565b601f81118314610e105750600081555b87610df3565b600090828252610e2e601f60208420920160051c8201858301611691565b81835555610e0a565b6009600090815260008051602061433e833981519152929190601f198516905b818110610e975750916001939185602097969410610e7e575b505050811b0160095561083e565b015160001960f88460031b161c19169055858080610e70565b92936020600181928786015181550195019301610e57565b6009600052610ee69060008051602061433e833981519152601f850160051c81019160208610610b2657601f0160051c0190611691565b84610805565b600560005260206000209060005b601f1984168110610f3e5750600193949583601f19811610610f25575b505050811b016005556107a8565b015160001960f88460031b161c19169055848080610f17565b9091602060018192858a015181550193019101610efa565b610f839060056000526020600020601f840160051c81019160208510610b2657601f0160051c0190611691565b84610772565b0151905087806105e3565b600460005260206000209560005b601f1984168110610feb57509582916020959697600194601f19811610610fd2575b505050811b01600455610749565b015160001960f88460031b161c19169055868080610fc4565b82820151885560019097019660209283019201610fa2565b600460005261104c907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81019160208510610b2657601f0160051c0190611691565b85610710565b634e487b7160e01b600052602160045260246000fd5b60c03d60c011611110575b61107d818361154c565b60c082828101031261110b5760606040519161109883611516565b6110a1846115fa565b83526110af602085016115fa565b60208401526110c0604085016115fa565b60408401528301839003605f19011261110b5760609060a0604051936110e5856114e0565b6110f08482016115fa565b8552608081015160208601520151604084015201528561051e565b600080fd5b503d611073565b6040513d6000823e3d90fd5b60405163107d9ce760e31b8152600490fd5b6040516307456b9160e21b8152600490fd5b903d8082843e611157818461154c565b60208382810103126113ad578251926001600160401b0384116113a957604084820183830103126113a9576040519361118f856114fb565b818101516001600160401b0381116113a55760e0818385010185850103126113a557604051906111be82611531565b6111cb81848601016115fa565b82526111dd60208285870101016115fa565b60208301526111f260408285870101016115fa565b604083015260608184860101015160038110156113925760608301528383018101608001516001600160401b038111611392576112629161123e60c0928888019083888a010101611592565b608085015261125360a08287890101016115fa565b60a085015284860101016115fa565b60c0820152855281810160200151936001600160401b0385116113a257838301601f86848601010112156113a257848284010151926112a08461160e565b956112ae604051978861154c565b848752602087019386830160208760051b848487010101011161139e576020828285010101945b60208760051b848487010101018610611302575050505050602085019390935250610480915061046f9050565b85516001600160401b03811161139a576040858401850182018a870103601f19011261139a5760405190611335826114fb565b85840185018101602001516001600160401b038111611396579061136960409260208d8a0191848a8a8d0101010101611592565b8352858588010101015160038110156113925760208281019190915290825295860195016112d5565b8680fd5b8780fd5b8580fd5b8380fd5b80fd5b8480fd5b8280fd5b5080fd5b825160030b84528694506020938401939092019160010161044c565b604051630695a62360e51b8152600490fd5b604051636fc5f47160e01b8152600490fd5b60405163460be67160e11b8152600490fd5b6040516311a1e69760e01b8152600490fd5b60405163bcda548360e01b8152600490fd5b8151906001600160401b03821161110b5760408683018503601f19011261110b5760405191611455836114fb565b6101008782010151916001600160401b03831161110b5760209360408361148b8b88809881988d60e0019360e001010101611592565b83528a60e00101015183820152815201920191905061035d565b8151906001600160401b03821161110b5760208092916114d389838f95898e839860e0019401010101611592565b8152019201919050610236565b606081019081106001600160401b0382111761069557604052565b604081019081106001600160401b0382111761069557604052565b608081019081106001600160401b0382111761069557604052565b60e081019081106001600160401b0382111761069557604052565b601f909101601f19168101906001600160401b0382119082101761069557604052565b60005b8381106115825750506000910152565b8181015183820152602001611572565b81601f8201121561110b5780516001600160401b03811161069557604051926115c5601f8301601f19166020018561154c565b8184526020828401011161110b576115e3916020808501910161156f565b90565b51906001600160a01b038216820361110b57565b51906001600160401b038216820361110b57565b6001600160401b0381116106955760051b60200190565b9060209161163e8151809281855285808601910161156f565b601f01601f1916010190565b8051156106ab5760200190565b90600182811c92168015611687575b602083101461167157565b634e487b7160e01b600052602260045260246000fd5b91607f1691611666565b81811061169c575050565b60008155600101611691565b9190601f81116116b757505050565b6116e2926000526020600020906020601f840160051c83019310610b2657601f0160051c0190611691565b565b9061060f60f31b61ffff60f01b602084015116148060011b908082046002149015171561173f576028018060281161173f5781036117355761172591611755565b90916001600160a01b0390911690565b5050600090600090565b634e487b7160e01b600052601160045260246000fd5b919060209061060f60f31b61ffff60f01b60208601511614936001928560011b958087046002149015171561173f57929190600095935b82851061179e57505050505060019190565b909192939560ff6117b88160f81b848a8701015116611809565b1690600f82116117f957600481811b91808304601014901517156117e45750019584019392919061178c565b601190634e487b7160e01b6000525260246000fd5b5050505050509050600090600090565b60f81c602f811180611871575b1561182557602f190160ff1690565b6060811180611867575b1561183e576056190160ff1690565b604081118061185d575b15611857576036190160ff1690565b5060ff90565b5060478110611848565b506067811061182f565b50603a811061181656fe6080604052600436101561001257600080fd5b6000803560e01c9081631c9feaa5146100ba57508063229e81fb146100b557806342859ab3146100b05780635a509280146100ab57806362b61c8b146100a657806378b90337146100a1578063819ef8ba1461009c57806388328a6914610097578063b3d7ad48146100925763cad31c741461008d57600080fd5b611414565b6112ef565b6111b6565b6110d0565b610ce8565b610b10565b610a0b565b610643565b610582565b346100db57806003193601126100db5760ff60115416151560805260206080f35b80fd5b60009103126100e957565b600080fd5b90600182811c92168015610137575b602083101461010857565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916100fd565b60045460009291610151826100ee565b808252916020906001908181169081156101d05750600114610174575b50505050565b9293945060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000935b8585106101bd57505050602092500101903880808061016e565b80548585018401529382019381016101a3565b91505060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b0101903880808061016e565b60055460009291610224826100ee565b808252916020906001908181169081156101d057506001146102465750505050565b9293945060056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0926000935b85851061028f57505050602092500101903880808061016e565b8054858501840152938201938101610275565b600e54600092916102b2826100ee565b808252916020906001908181169081156101d057506001146102d45750505050565b92939450600e6000527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd926000935b85851061031d57505050602092500101903880808061016e565b8054858501840152938201938101610303565b600f5460009291610340826100ee565b808252916020906001908181169081156101d057506001146103625750505050565b92939450600f6000527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000935b8585106103ab57505050602092500101903880808061016e565b8054858501840152938201938101610391565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761040957604052565b6103be565b67ffffffffffffffff811161040957604052565b60a0810190811067ffffffffffffffff82111761040957604052565b6080810190811067ffffffffffffffff82111761040957604052565b60e0810190811067ffffffffffffffff82111761040957604052565b6060810190811067ffffffffffffffff82111761040957604052565b6020810190811067ffffffffffffffff82111761040957604052565b90601f601f19910116810190811067ffffffffffffffff82111761040957604052565b604051906104e9826104e2816102a2565b03836104ae565b565b604051906104e9826104e281610330565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004111561053557565b6104fc565b60005b83811061054d5750506000910152565b818101518382015260200161053d565b90601f19601f60209361057b8151809281875287808801910161053a565b0116010190565b346100e95760006003193601126100e95760025460ff600354166040908151906105ab826103ed565b82516105c1816105ba81610141565b03826104ae565b82528251906105d3826104e281610214565b602083019182528351948552600481101561053557849361063f9361060e9260208701526060828701525190606086015260a085019061055d565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084830301608085015261055d565b0390f35b346100e95760a06003193601126100e957600460026001541461097a5760026001556011549073ffffffffffffffffffffffffffffffffffffffff91828160081c1633036109515760ff16610929576106a161069d611db8565b1590565b610901576106f3906106b16114b6565b92604051937f62b61c8b0000000000000000000000000000000000000000000000000000000085528480600095869360843560643560243589358a87016115da565b0381305afa93841561087957839084956108da575b50610712906116c7565b61076e602060405161073c8161072e8985830160209181520190565b03601f1981018352826104ae565b604051809381927fcad31c740000000000000000000000000000000000000000000000000000000083528783016119c8565b038187305af18015610879576107b79185916108ab575b5060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00601154169115151617601155565b60115460ff16610882575b7f00000000000000000000000000000000000000000000000000000000000000001690813b1561087e57604080517faa733a4400000000000000000000000000000000000000000000000000000000815232928101928352602083018690529392849290918391859183910103925af1801561087957610860575b5060115460ff1661084d60018055565b6040805191151582526020820192909252f35b8061086d6108739261040e565b806100de565b3861083d565b611649565b8280fd5b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e8380a16107c2565b6108cd915060203d6020116108d3575b6108c581836104ae565b8101906117f3565b38610785565b503d6108bb565b61071295506108fb91503d8086833e6108f381836104ae565b81019061156c565b94610708565b6040517f741926a1000000000000000000000000000000000000000000000000000000008152fd5b6040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b506040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b6040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b908160809103126100e95790565b6020815273ffffffffffffffffffffffffffffffffffffffff80835116602083015260208301511660408201526040820151606082015260a06080610a026060850151838386015260c085019061055d565b93015191015290565b346100e95760206003193601126100e95760043567ffffffffffffffff81116100e957610a3f61063f9136906004016109a2565b610a47611aa5565b5073ffffffffffffffffffffffffffffffffffffffff90610aac826000541692604083013590610a7682611ad0565b610a836060850185611af8565b91909260405196610a9388610422565b8752166020860152602084013560408601523691611b49565b6060830152356080820152604051918291826109b0565b9181601f840112156100e95782359167ffffffffffffffff83116100e9576020808501948460051b0101116100e957565b929190610b0b60209160408652604086019061055d565b930152565b346100e95760c06003193601126100e95767ffffffffffffffff6084358181116100e957610b42903690600401610ac3565b60a4929192359182116100e957610ca8610ca3610cd194610b6a610cc19536906004016109a2565b93610c88610b8d610c81610b7c6114c9565b97610b92610b8d60208301356127cc565b6122c6565b610b9b8a611baf565b52610ba589611baf565b50610bb4610b8d6004356127cc565b610bbd8a611bc1565b52610bc789611bc1565b50610bd6610b8d6044356127cc565b610bdf8a611bd1565b52610be989611bd1565b50610bf8610b8d6064356127cc565b610c018a611be1565b52610c0b89611be1565b50610c1a610b8d6024356127cc565b610c238a611bf1565b52610c2d89611bf1565b50610c42610c3d60408301611aee565b612285565b610c4b8a611c01565b52610c5589611c01565b50610c63610b8d82356127cc565b610c6c8a611c11565b52610c7689611c11565b506060810190611af8565b3691611b49565b610c9186611c21565b52610c9b85611c21565b503691611c57565b61244c565b610cb182611c32565b52610cbb81611c32565b5061244c565b610ccc610b8d6126ed565b61257c565b805160208201209061063f60405192839283610af4565b346100e95760006003193601126100e9576020610d03611db8565b6040519015158152f35b60095460009291610d1d826100ee565b808252916020906001908181169081156101d05750600114610d3f5750505050565b9293945060096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af926000935b858510610d8857505050602092500101903880808061016e565b8054858501840152938201938101610d6e565b600c5460009291610dab826100ee565b808252916020906001908181169081156101d05750600114610dcd5750505050565b92939450600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7926000935b858510610e1657505050602092500101903880808061016e565b8054858501840152938201938101610dfc565b805460009392610e38826100ee565b91828252602093600191600181169081600014610ea05750600114610e5f575b5050505050565b90939495506000929192528360002092846000945b838610610e8c57505050500101903880808080610e58565b805485870183015294019385908201610e74565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b010191503880808080610e58565b604051906104e9826104e281610d9b565b67ffffffffffffffff81116104095760051b60200190565b600b5490610f1382610eee565b916040610f2360405194856104ae565b81845283602080910191600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9906000935b858510610f6757505050505050565b60018481928451610f7c816105ba818a610e29565b815201930194019391610f58565b90808251908181526020809101926020808460051b8301019501936000915b848310610fb95750505050505090565b9091929394958480610fd783601f1986600196030187528a5161055d565b9801930193019194939290610fa9565b61103860606110cd9493604084528051604085015260208101518285015273ffffffffffffffffffffffffffffffffffffffff60408201511660808501520151608060a084015260c083019061055d565b90602081830391015267ffffffffffffffff825116815260c06110bc611082611070602086015160e0602087015260e0860190610f8a565b6040860151858203604087015261055d565b60608581015167ffffffffffffffff169085015260808581015167ffffffffffffffff169085015260a085015184820360a086015261055d565b9201519060c081840391015261055d565b90565b346100e95760006003193601126100e957604080516110ee8161043e565b6006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416828201528151611127816105ba81610d0d565b606082015261063f82519261113b8461045a565b61119267ffffffffffffffff80600a54168652611156610f06565b6020870152611163610edd565b86840152600d5467ffffffffffffffff828216166060880152831c16608086019067ffffffffffffffff169052565b61119a6104d1565b60a08501526111a76104eb565b60c08501525192839283610fe7565b346100e9576000806003193601126100db5760ff60115416156112c557604051908082601254916111e6836100ee565b928383526020946001918660018216918260001461128457505060011461122a575b5050611216925003836104ae565b61063f60405192828493845283019061055d565b90859250601282527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34445b85831061126c57505061121693508201013880611208565b80548389018501528794508693909201918101611254565b915093506112169592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611208565b60046040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b346100e9576000806003193601126100db57611309611aa5565b50604051907f5a509280000000000000000000000000000000000000000000000000000000008252602060048301528082806113476024820161159d565b0381305afa908115610879578091611368575b6040518061063f84826109b0565b90503d8082843e61137981846104ae565b820160208382031261141057825167ffffffffffffffff9384821161140c57019260a08483031261087e57604051926113b184610422565b84516113bc81611ad0565b845260208501516113cc81611ad0565b60208501526040850151604085015260608501519182116100db5750926113fa60809261063f95830161152a565b6060840152015160808201523861135a565b8380fd5b5080fd5b346100e9576003196060813601126100e95760043567ffffffffffffffff918282116100e95760e09082360301126100e957602435918083116100e957366023840112156100e9578260040135928184116100e95736602485830101116100e9576044359182116100e95761063f936114a4936114976024943690600401610ac3565b9490930190600401612176565b60405190151581529081906020820190565b6040516114c281610492565b6000815290565b60405190610140820182811067ffffffffffffffff82111761040957604052600982528160005b61012081106114fd575050565b8060606020809385010152016114f0565b67ffffffffffffffff811161040957601f01601f191660200190565b81601f820112156100e95780516115408161150e565b9261154e60405194856104ae565b818452602082840101116100e9576110cd916020808501910161053a565b91906040838203126100e957825167ffffffffffffffff81116100e95760209161159791850161152a565b92015190565b60806110cd916006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416604082015281606082015201610d0d565b9293608094611609936110cd9793865260208601526040850152606084015260c08484015260c0830190610f8a565b9060a08183039101526006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416604082015281606082015201610d0d565b6040513d6000823e3d90fd5b601f8111611661575050565b60009060126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906020601f850160051c830194106116bd575b601f0160051c01915b8281106116b257505050565b8181556001016116a6565b909250829061169d565b90815167ffffffffffffffff8111610409576116ed816116e86012546100ee565b611655565b602080601f831160011461174d5750819061173d9394600092611742575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b601255565b01519050388061170b565b90601f1983169461178060126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344490565b926000905b8782106117db5750508360019596106117a4575b505050811b01601255565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611799565b80600185968294968601518155019501930190611785565b908160209103126100e9575180151581036100e95790565b80600b5480825260208092019160208260051b85010193600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9936000915b84831061185d5750505050505090565b90919293949584600161187a83601f19868496030187528a610e29565b980193019301919493929061184d565b8060105490818152602080910191600591808260051b86010194600094601086527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6729580925b8584106118e257505050505050505090565b9091929394959697601f19828203018452856040808352898b8692815490611909826100ee565b8091880152606091600194858216918260001461198b57505060011461194a575b5050015492820192909252909860020197969594600101930191906118d0565b909180945088528488209088915b81831061196d5750508501019183600161192a565b8496929491939550805486868a0101520192018d93918b9593611958565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168985015291151590911b87019091019350849050600161192a565b611a976110cd92606083526119fb606084016119ed600a5467ffffffffffffffff1690565b67ffffffffffffffff169052565b60e06080840152611a89611a12610140850161180b565b611a79611a497fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa092838882030160a0890152610d9b565b600d5467ffffffffffffffff80821660c08a015260409190911c1660e088015282878203016101008801526102a2565b9085820301610120860152610330565b90838203602085015261055d565b90604081830391015261188a565b60405190611ab282610422565b60006080838281528260208201528260408201526060808201520152565b73ffffffffffffffffffffffffffffffffffffffff8116036100e957565b356110cd81611ad0565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e9570180359067ffffffffffffffff82116100e9576020019181360383136100e957565b929192611b558261150e565b91611b6360405193846104ae565b8294818452818301116100e9578281602093846000960137010152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115611bbc5760200190565b611b80565b805160011015611bbc5760400190565b805160021015611bbc5760600190565b805160031015611bbc5760800190565b805160041015611bbc5760a00190565b805160051015611bbc5760c00190565b805160061015611bbc5760e00190565b805160071015611bbc576101000190565b805160081015611bbc576101200190565b8051821015611bbc5760209160051b010190565b92919092611c6484610eee565b91611c7260405193846104ae565b829480845260208094019060051b8301928284116100e95780915b848310611c9c57505050505050565b823567ffffffffffffffff81116100e957820184601f820112156100e9578691611ccc8683858095359101611b49565b815201920191611c8d565b67ffffffffffffffff8116036100e957565b8091039060c082126100e95760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa060405193611d258561043e565b8351611d3081611cd7565b85526020840151611d4081611cd7565b60208601526040840151611d5381611cd7565b604086015201126100e95760a060405191611d6d83610476565b6060810151611d7b81611cd7565b83526080810151602084015201516040820152606082015290565b6110cd9060408152611daa60408201610141565b906020818303910152610214565b6040517f3d0f34da00000000000000000000000000000000000000000000000000000000815260c08180611dee60048201611d96565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561087957600091611ea8575b5060035460ff16611e488161052b565b60018103611e6157506060015160400151600254111590565b611e6a8161052b565b611e7e576060015160400151600254101590565b60046040517f951a55bf000000000000000000000000000000000000000000000000000000008152fd5b611eca915060c03d60c011611ed0575b611ec281836104ae565b810190611ce9565b38611e38565b503d611eb8565b356110cd81611cd7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e9570180359067ffffffffffffffff82116100e957602001918160051b360383136100e957565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100e957016020813591019167ffffffffffffffff82116100e95781360383136100e957565b90918092808252602080920191808260051b8601019484600080925b858410611fd457505050505050505090565b9091929394959697601f1982820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18536030181121561140c57866001928682930190828061203a604061202d8680611f56565b9091808752860191611f35565b9301359101529a01980196959401929190611fc2565b9e9b999f9d9c9a989694918f969493906120859167ffffffffffffffff610140941689526020938060208b0152890191611f35565b956040818803910152818652602086019560208360051b82010196846000925b85841061213d5750505050505050946121088c9d60a06120f76104e99e9f986101209e9c986120e96121359f9d99612119996121269e8e6060818503910152611f35565b918b830360808d0152611fa6565b97019067ffffffffffffffff169052565b67ffffffffffffffff1660c08d0152565b8a830360e08c0152611f35565b91878303610100890152611f35565b930160019052565b9091929394959885806121658361215f8e601f198860019803018a5288611f56565b90611f35565b9b01940194019295949391906120a5565b909293919361218482611ed7565b926121926020840184611ee1565b9390926121a26040830183611af8565b919093606084016121b290611ed7565b916121bf60808601611ed7565b936121cd60a0870187611af8565b97909660c081016121dd91611af8565b9a90996040519e8f9e8f7f07d145e90000000000000000000000000000000000000000000000000000000081526004019e6122179f612050565b03817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a602094600091f19081156108795760009161226c575090565b6110cd915060203d6020116108d3576108c581836104ae565b6110cd906040519074140000000000000000000000000000000000000000186014820152603481016040526122c6565b908151811015611bbc570160200190565b90600091805192600193600181149081612434575b50156122e657509150565b81519360388510156123405750926110cd92937fff0000000000000000000000000000000000000000000000000000000000000061232b61232561260e565b936128bb565b60f81b16901a61233a82611baf565b5361257c565b8190806001915b612404575b505061235f61235a8261289f565b612640565b917fff0000000000000000000000000000000000000000000000000000000000000061239261238d846128bb565b6128ad565b8160f89160f81b16831a6123a586611baf565b5360015b848111156123c15750505050506110cd92935061257c565b80836123ea6123e46123de6123d96123ff968b6126b3565b6128e4565b8d61284f565b60ff1690565b841b16851a6123f982896122b5565b536126c0565b6123a9565b9091612410838861284f565b1561242e57612421612427916126c0565b92612888565b9080612347565b9161234c565b905015611bbc576080602083015160f81c10386122db565b6124559061297e565b9081516000603882106000146124ae5750916110cd91927fff0000000000000000000000000000000000000000000000000000000000000061249e61249861260e565b926128c9565b60f81b1660001a61233a82611baf565b916001925b6124bd848461284f565b156124da576124ce6124d4916126c0565b93612888565b926124b3565b9092509290926124ec61235a8261289f565b907fff0000000000000000000000000000000000000000000000000000000000000061251a61238d836128c9565b8160f89160f81b1660001a61252e85611baf565b5360015b8381111561254957505050506110cd92935061257c565b80836125676123e46125616123d9612577968a6126b3565b8c61284f565b841b1660001a6123f982886122b5565b612532565b6040518151808252909290830191602083810192818301828088015b8681106125e55750505080518094875182018852950194828087019201905b8281106125d6575050505091603f91601f199351011501011660405290565b815181529083019083016125b7565b8251815291810191849101612598565b60405190612602826103ed565b60208083523683820137565b6040519061261b826103ed565b6001825260203681840137565b60405161263481610492565b60008152906000368137565b9061264a8261150e565b61265760405191826104ae565b828152601f19612667829461150e565b0190602036910137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60200390602082116126ae57565b612671565b919082039182116126ae57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146126ae5760010190565b6126f56125f5565b90602091600260208201526000926000905b808210612783575b5061271c61235a826126a0565b9160005b835181101561277b5760019061276861274261273b866126c0565b95856122b5565b517fff000000000000000000000000000000000000000000000000000000000000001690565b871a61277482876122b5565b5301612720565b509193505050565b906127b961279461274283866122b5565b7fff000000000000000000000000000000000000000000000000000000000000001690565b6127c65760010190612707565b9061270f565b906127d56125f5565b60209260208201526000926000905b80821061282b575b506127f961235a826126a0565b9160005b835181101561277b5760019061281861274261273b866126c0565b871a61282482876122b5565b53016127fd565b9061283c61279461274283866122b5565b61284957600101906127e4565b906127ec565b8115612859570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b908160081b9180830461010014901517156126ae57565b90600182018092116126ae57565b90603782018092116126ae57565b90608082018092116126ae57565b9060c082018092116126ae57565b919082018092116126ae57565b601f81116126ae576101000a90565b156128fa57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f416e206974656d20696e20746865206c69737420746f20626520524c5020656e60448201527f636f646564206973206e756c6c2e0000000000000000000000000000000000006064820152fd5b805115612a235790600091825b81518410156129ca576129c26001916129b06129a78786611c43565b515115156128f3565b6129ba8685611c43565b5151906128d7565b93019261298b565b6129d691929350612640565b906020808301936000945b8351861015612a1b57612a13600191612a096129fd8988611c43565b51868151910183612a2c565b6129ba8887611c43565b9501946129e1565b509350505090565b506110cd612628565b92905b602093848410612a6457815181528481018091116126ae579381018091116126ae5791601f1981019081116126ae5791612a2f565b9290919350602003602081116126ae57612a7d906128e4565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116126ae57518251821691191617905256fea164736f6c6343000819000a6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7afa164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca8300000000000000000000000000000000000000000000000000000000", + "nonce": "0x42", + "chainId": "0x3039" + }, + "additionalContracts": [ + { + "transactionType": "CREATE2", + "address": "0xa779126c3314385e9b0041072ea6a89d295fd195", + "initCode": "0x60a034607357601f61520438819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607357516001600160a01b038116908190036073576001600055608052604051615175908161008f823960805181818160e901526103a60152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c90816306433b1b146100a45781630b0fdb3d14610055575080633dc48a341461005057637fddd6021461004b57600080fd5b610242565b610176565b346100a15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15760ff60406020926004358152600184522054166040519015158152f35b80fd5b346100a157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b600091031261011d57565b600080fd5b9181601f8401121561011d5782359167ffffffffffffffff831161011d576020808501948460051b01011161011d57565b6064359073ffffffffffffffffffffffffffffffffffffffff8216820361011d57565b3461011d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a08136011261011d576004359067ffffffffffffffff9081831161011d57606081843603011261011d576024359082821161011d57604090823603011261011d5760443591821161011d5761023e926101fd610217933690600401610122565b90610206610153565b9260843594600401906004016102db565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b3461011d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011d5760043573ffffffffffffffffffffffffffffffffffffffff80821680920361011d576102d26020926040516102ca816102bc8782019460243590869091604092825260208201520190565b03601f198101835282610647565b519020610b4c565b60405191168152f35b939294909160009160028354146105b9576002835560409586519182610311602082019232849091604092825260208201520190565b0392610325601f1994858101835282610647565b51902094610347610340876000526001602052604060002090565b5460ff1690565b6105905732867f4d26f9b035ac4dafb21ce257260243ad6adf7e105ac6517fe42bebde1d0828ca8780a361435e916103816020840161066a565b92808452610e0b602085013973ffffffffffffffffffffffffffffffffffffffff998a7f0000000000000000000000000000000000000000000000000000000000000000169889918b5197889560208701956103dc96610a0d565b0382810184526103ec9084610647565b8651928391602083016103fe91610b15565b61040791610b15565b0390810182526104179082610647565b6104219083610d1c565b9461042b83610b4c565b90808716908115928315610583575b50505061055257823b156100a15783517f4420e48600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86166004820152928390602490829084905af190811561054d576104e5926104ba92610534575b506000526001602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b5173ffffffffffffffffffffffffffffffffffffffff8216815233907f51cd0090f3c14be5310fb02efc5d7f8aa69cff235becdf1d944ee6c420b2deb690602090a2906105326001600055565b565b8061054161054792610612565b80610112565b386104a9565b610b40565b83517f8e6ae65f00000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b161415905038808061043a565b600488517f0ced3043000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161062657604052565b6105e3565b6040810190811067ffffffffffffffff82111761062657604052565b90601f601f19910116810190811067ffffffffffffffff82111761062657604052565b906105326040519283610647565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18236030181121561011d570190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561011d57016020813591019167ffffffffffffffff821161011d57813603831361011d57565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218236030181121561011d570190565b359067ffffffffffffffff8216820361011d57565b908281815260208091019360208360051b82010194846000925b85841061078d575050505050505090565b9091929394959685806107b583601f1986600196030188526107af8c886106aa565b906106fa565b99019401940192959493919061077c565b67ffffffffffffffff91826107da8361074d565b16815260208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181121561011d5782019260208435940190841161011d578360051b3603811361011d576108c261086761084c6108cd936108db9760e0602088015260e0870191610762565b61085960408701876106aa565b9086830360408801526106fa565b6108876108766060870161074d565b67ffffffffffffffff166060860152565b6108a76108966080870161074d565b67ffffffffffffffff166080860152565b6108b460a08601866106aa565b9085830360a08701526106fa565b9260c08101906106aa565b9160c08185039101526106fa565b90565b80357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818236030181121561011d57810191604081528235604082015260208301356060820152604083013573ffffffffffffffffffffffffffffffffffffffff811680910361011d576109756109646108db9561098093608086015260608101906106aa565b608060a086015260c08501916106fa565b92602081019061071b565b9060208184039101526107c6565b9082818152602080910193818360051b82010194846000925b8584106109b8575050505050505090565b90919293949596858082601f1985600195030187526109d78b87610678565b9082806109f660406109e986806106aa565b90918087528601916106fa565b9301359101529901940194019295949391906109a7565b9190969593949660a08352803560a0840152602081013593600485101561011d5761053296610acc610af994610abe610a55610ada9660809a60c08b01526040810190610678565b606060e08a0152610a8d610a828a6101006040610a7286806106aa565b92909301526101408d01916106fa565b9160208101906106aa565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008b8403016101208c01526106fa565b9087820360208901526108de565b91858303604087015261098e565b73ffffffffffffffffffffffffffffffffffffffff9097166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b9081519160005b838110610b2d575050016000815290565b8060208092840101518185015201610b1c565b6040513d6000823e3d90fd5b6040519060208201907fff0000000000000000000000000000000000000000000000000000000000000082523060601b602184015260358301527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605583015260558252608082019180831067ffffffffffffffff84111761062657827f010000000000000000000000000000000000000000000000000000000000000060b6610c79946108db9660405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610c5d8161062b565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051906040820182811067ffffffffffffffff82111761062657604052601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b3d15610d17573d9067ffffffffffffffff82116106265760405191610d0b6020601f19601f8401160184610647565b82523d6000602084013e565b606090565b9190610d26610c92565b92610d3081610b4c565b93843b610de0576020815191016000f573ffffffffffffffffffffffffffffffffffffffff811615610db65781600092918360208194519301915af1610d74610cdc565b50158015610dad575b610d8357565b60046040517f53de54b9000000000000000000000000000000000000000000000000000000008152fd5b50813b15610d7d565b60046040517fbbd2fe87000000000000000000000000000000000000000000000000000000008152fd5b60046040517fcd43efa1000000000000000000000000000000000000000000000000000000008152fdfe60e06040523461110b5761435e803803809161001c8260e061154c565b60e03960a0811261110b5760e0516001600160401b03811161110b5760e001906060828260e001031261110b5760405191610056836114e0565b805183526020810151600481101561110b5760208401526040810151906001600160401b03821161110b57016040818360e001031261110b576040519061009c826114fb565b80516001600160401b03811161110b576100bc908460e001908301611592565b82526020810151906001600160401b03821161110b576100e1918460e0019101611592565b60208201526040830152610100516001600160401b03811161110b5760e0016040818360e001031261110b576040519061011a826114fb565b80516001600160401b03811161110b5781016080818560e001031261110b576040519061014682611516565b8051825260208101516020830152610160604082016115e6565b60408301526060810151906001600160401b03821161110b57610188918660e0019101611592565b6060820152825260208101516001600160401b03811161110b5760e08183018560e001031261110b57604051916101be83611531565b6101c98282016115fa565b8352808201602001516001600160401b03811161110b578560e001601f828585010101121561110b578083830101516102018161160e565b9161020f604051938461154c565b818352602083018860e00160208460051b848989010101011161110b576020828787010101905b60208460051b8489890101010182106114a557505050506020840152808201604001516001600160401b03811161110b57610279908660e0019084840101611592565b604084015261028c6060838301016115fa565b606084015261029f6080838301016115fa565b608084015280820160a001516001600160401b03811161110b576102cb908660e0019084840101611592565b60a084015280820160c001516001600160401b03811161110b576102f5928660e001920101611592565b60c08201526020820152610120516001600160401b03811161110b5760e0830160ff8201121561110b578060e0015161032d8161160e565b9361033b604051958661154c565b8185526020850160e08201610100600585901b8601011161110b576101008401905b610100600585901b86010182106114275787878761037c6101406115e6565b906103886101606115e6565b602082015182516001600160a01b03851615611415576001600160a01b038316156114035760a082015151156113f15760c082015151156113df57604001516001600160a01b0316156113cd57610900608052604051906103e8826114fb565b600182526020368184013760016103fe8361164a565b5260805190516040805163338c1f5160e01b81526001600160401b039092166004830152602482015282516044820181905290926001600160a01b0390921691839160648301916020019060005b8181106113b15750505091818060009403915afa90811561111757600091611147575b50610480602061048a92015161164a565b51518051906116e4565b901561113557600080546001600160a01b0319166001600160a01b0392909216919091179055600180558451156111235761050f60c06109028060a0526040880151906104fd602083519301519260405195869485938493631e879a6d60e11b8552604060048601526044850190611625565b83810360031901602485015290611625565b03915afa801561111757611068575b506001600160a01b031660c05260005b83518110156106c15760208160051b8501015160105490680100000000000000008210156106955760018201806010558210156106ab576010600052805180517f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67292916001600160401b038211610695576105bd826105b28760011b870154611657565b8760011b87016116a8565b602090601f831160011461061857926105f8836001989796946020948a9760009261060d575b50508160011b916000199060031b1c19161790565b85851b8401555b015192821b0101550161052e565b015190508e806105e3565b908560011b850160005260206000209160005b601f198516811061067d575083602093600199989795938a9794938894601f19811610610664575b505050811b0185851b8401556105ff565b015160001960f88460031b161c191690558d8080610653565b9192602060018192868501518155019401920161062b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b50835160025560208401518460048210156110525760409160ff801960035416911617600355015191825192835160018060401b03811161069557610707600454611657565b601f8111611003575b506020601f8211600114610f94579080610745926020959697600092610f895750508160011b916000199060031b1c19161790565b6004555b015180519092906001600160401b03811161069557610769600554611657565b601f8111610f56575b506020601f8211600114610eec5781906107a4939495600092610bf95750508160011b916000199060031b1c19161790565b6005555b8051805160065560208101516007556040810151600880546001600160a01b0319166001600160a01b0392909216919091179055606001518051906001600160401b038211610695576107fc600954611657565b601f8111610eaf575b50602090601f8311600114610e3757918061083a9260209594600092610b305750508160011b916000199060031b1c19161790565b6009555b01519060018060401b0382511660018060401b0319600a541617600a55602082015180519068010000000000000000821161069557600b5482600b55808310610da6575b50600b60009081527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db992916020015b828210610cbd5760408601518051869088906001600160401b038111610695576108dc600c54611657565b601f8111610c6e575b506020601f8211600114610c04578190610917939495600092610bf95750508160011b916000199060031b1c19161790565b600c555b6060810151600d805460808401516001600160801b03199091166001600160401b039384161760409190911b6fffffffffffffffff00000000000000001617905560a0820151805191821161069557610975600e54611657565b601f8111610baa575b50602090601f8311600114610b3b5791806109b39260c09594600092610b305750508160011b916000199060031b1c19161790565b600e555b015180519091906001600160401b038111610695576109d7600f54611657565b601f8111610ad6575b50602092601f8211600114610a7057610a1292938291600092610a655750508160011b916000199060031b1c19161790565b600f555b60118054610100600160a81b03191660089290921b610100600160a81b0316919091179055604051612ac2908161187c82396080518161221b015260a05181611e07015260c051816107c40152f35b0151905084806105e3565b601f19821693600f60005260206000209160005b868110610abe5750836001959610610aa5575b505050811b01600f55610a16565b015160001960f88460031b161c19169055838080610a97565b91926020600181928685015181550194019201610a84565b600f600052610b20907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802601f840160051c81019160208510610b26575b601f0160051c0190611691565b836109e0565b9091508190610b13565b0151905086806105e3565b90600e60005260206000209160005b601f1985168110610b92575091839160019360c09695601f19811610610b79575b505050811b01600e556109b7565b015160001960f88460031b161c19169055858080610b6b565b91926020600181928685015181550194019201610b4a565b600e600052610bf3907fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd601f850160051c81019160208610610b2657601f0160051c0190611691565b8461097e565b0151905085806105e3565b600c60005260206000209060005b601f1984168110610c565750600193949583601f19811610610c3d575b505050811b01600c5561091b565b015160001960f88460031b161c19169055848080610c2f565b9091602060018192858a015181550193019101610c12565b600c600052610cb7907fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7601f840160051c81019160208510610b2657601f0160051c0190611691565b846108e5565b80518051906001600160401b03821161069557610ce482610cde8854611657565b886116a8565b602090601f8311600114610d365792610d1c83600195946020948796600092610d2b5750508160011b916000199060031b1c19161790565b87555b019401910190926108b1565b015190508c806105e3565b908660005260206000209160005b601f1985168110610d8e575083602093600196938796938794601f19811610610d75575b505050811b018755610d1f565b015160001960f88460031b161c191690558b8080610d68565b91926020600181928685015181550194019201610d44565b600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99081019083015b818110610de05750610882565b80610ded60019254611657565b80610dfa575b5001610dd3565b601f81118314610e105750600081555b87610df3565b600090828252610e2e601f60208420920160051c8201858301611691565b81835555610e0a565b6009600090815260008051602061433e833981519152929190601f198516905b818110610e975750916001939185602097969410610e7e575b505050811b0160095561083e565b015160001960f88460031b161c19169055858080610e70565b92936020600181928786015181550195019301610e57565b6009600052610ee69060008051602061433e833981519152601f850160051c81019160208610610b2657601f0160051c0190611691565b84610805565b600560005260206000209060005b601f1984168110610f3e5750600193949583601f19811610610f25575b505050811b016005556107a8565b015160001960f88460031b161c19169055848080610f17565b9091602060018192858a015181550193019101610efa565b610f839060056000526020600020601f840160051c81019160208510610b2657601f0160051c0190611691565b84610772565b0151905087806105e3565b600460005260206000209560005b601f1984168110610feb57509582916020959697600194601f19811610610fd2575b505050811b01600455610749565b015160001960f88460031b161c19169055868080610fc4565b82820151885560019097019660209283019201610fa2565b600460005261104c907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81019160208510610b2657601f0160051c0190611691565b85610710565b634e487b7160e01b600052602160045260246000fd5b60c03d60c011611110575b61107d818361154c565b60c082828101031261110b5760606040519161109883611516565b6110a1846115fa565b83526110af602085016115fa565b60208401526110c0604085016115fa565b60408401528301839003605f19011261110b5760609060a0604051936110e5856114e0565b6110f08482016115fa565b8552608081015160208601520151604084015201528561051e565b600080fd5b503d611073565b6040513d6000823e3d90fd5b60405163107d9ce760e31b8152600490fd5b6040516307456b9160e21b8152600490fd5b903d8082843e611157818461154c565b60208382810103126113ad578251926001600160401b0384116113a957604084820183830103126113a9576040519361118f856114fb565b818101516001600160401b0381116113a55760e0818385010185850103126113a557604051906111be82611531565b6111cb81848601016115fa565b82526111dd60208285870101016115fa565b60208301526111f260408285870101016115fa565b604083015260608184860101015160038110156113925760608301528383018101608001516001600160401b038111611392576112629161123e60c0928888019083888a010101611592565b608085015261125360a08287890101016115fa565b60a085015284860101016115fa565b60c0820152855281810160200151936001600160401b0385116113a257838301601f86848601010112156113a257848284010151926112a08461160e565b956112ae604051978861154c565b848752602087019386830160208760051b848487010101011161139e576020828285010101945b60208760051b848487010101018610611302575050505050602085019390935250610480915061046f9050565b85516001600160401b03811161139a576040858401850182018a870103601f19011261139a5760405190611335826114fb565b85840185018101602001516001600160401b038111611396579061136960409260208d8a0191848a8a8d0101010101611592565b8352858588010101015160038110156113925760208281019190915290825295860195016112d5565b8680fd5b8780fd5b8580fd5b8380fd5b80fd5b8480fd5b8280fd5b5080fd5b825160030b84528694506020938401939092019160010161044c565b604051630695a62360e51b8152600490fd5b604051636fc5f47160e01b8152600490fd5b60405163460be67160e11b8152600490fd5b6040516311a1e69760e01b8152600490fd5b60405163bcda548360e01b8152600490fd5b8151906001600160401b03821161110b5760408683018503601f19011261110b5760405191611455836114fb565b6101008782010151916001600160401b03831161110b5760209360408361148b8b88809881988d60e0019360e001010101611592565b83528a60e00101015183820152815201920191905061035d565b8151906001600160401b03821161110b5760208092916114d389838f95898e839860e0019401010101611592565b8152019201919050610236565b606081019081106001600160401b0382111761069557604052565b604081019081106001600160401b0382111761069557604052565b608081019081106001600160401b0382111761069557604052565b60e081019081106001600160401b0382111761069557604052565b601f909101601f19168101906001600160401b0382119082101761069557604052565b60005b8381106115825750506000910152565b8181015183820152602001611572565b81601f8201121561110b5780516001600160401b03811161069557604051926115c5601f8301601f19166020018561154c565b8184526020828401011161110b576115e3916020808501910161156f565b90565b51906001600160a01b038216820361110b57565b51906001600160401b038216820361110b57565b6001600160401b0381116106955760051b60200190565b9060209161163e8151809281855285808601910161156f565b601f01601f1916010190565b8051156106ab5760200190565b90600182811c92168015611687575b602083101461167157565b634e487b7160e01b600052602260045260246000fd5b91607f1691611666565b81811061169c575050565b60008155600101611691565b9190601f81116116b757505050565b6116e2926000526020600020906020601f840160051c83019310610b2657601f0160051c0190611691565b565b9061060f60f31b61ffff60f01b602084015116148060011b908082046002149015171561173f576028018060281161173f5781036117355761172591611755565b90916001600160a01b0390911690565b5050600090600090565b634e487b7160e01b600052601160045260246000fd5b919060209061060f60f31b61ffff60f01b60208601511614936001928560011b958087046002149015171561173f57929190600095935b82851061179e57505050505060019190565b909192939560ff6117b88160f81b848a8701015116611809565b1690600f82116117f957600481811b91808304601014901517156117e45750019584019392919061178c565b601190634e487b7160e01b6000525260246000fd5b5050505050509050600090600090565b60f81c602f811180611871575b1561182557602f190160ff1690565b6060811180611867575b1561183e576056190160ff1690565b604081118061185d575b15611857576036190160ff1690565b5060ff90565b5060478110611848565b506067811061182f565b50603a811061181656fe6080604052600436101561001257600080fd5b6000803560e01c9081631c9feaa5146100ba57508063229e81fb146100b557806342859ab3146100b05780635a509280146100ab57806362b61c8b146100a657806378b90337146100a1578063819ef8ba1461009c57806388328a6914610097578063b3d7ad48146100925763cad31c741461008d57600080fd5b611414565b6112ef565b6111b6565b6110d0565b610ce8565b610b10565b610a0b565b610643565b610582565b346100db57806003193601126100db5760ff60115416151560805260206080f35b80fd5b60009103126100e957565b600080fd5b90600182811c92168015610137575b602083101461010857565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916100fd565b60045460009291610151826100ee565b808252916020906001908181169081156101d05750600114610174575b50505050565b9293945060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000935b8585106101bd57505050602092500101903880808061016e565b80548585018401529382019381016101a3565b91505060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b0101903880808061016e565b60055460009291610224826100ee565b808252916020906001908181169081156101d057506001146102465750505050565b9293945060056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0926000935b85851061028f57505050602092500101903880808061016e565b8054858501840152938201938101610275565b600e54600092916102b2826100ee565b808252916020906001908181169081156101d057506001146102d45750505050565b92939450600e6000527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd926000935b85851061031d57505050602092500101903880808061016e565b8054858501840152938201938101610303565b600f5460009291610340826100ee565b808252916020906001908181169081156101d057506001146103625750505050565b92939450600f6000527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000935b8585106103ab57505050602092500101903880808061016e565b8054858501840152938201938101610391565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761040957604052565b6103be565b67ffffffffffffffff811161040957604052565b60a0810190811067ffffffffffffffff82111761040957604052565b6080810190811067ffffffffffffffff82111761040957604052565b60e0810190811067ffffffffffffffff82111761040957604052565b6060810190811067ffffffffffffffff82111761040957604052565b6020810190811067ffffffffffffffff82111761040957604052565b90601f601f19910116810190811067ffffffffffffffff82111761040957604052565b604051906104e9826104e2816102a2565b03836104ae565b565b604051906104e9826104e281610330565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004111561053557565b6104fc565b60005b83811061054d5750506000910152565b818101518382015260200161053d565b90601f19601f60209361057b8151809281875287808801910161053a565b0116010190565b346100e95760006003193601126100e95760025460ff600354166040908151906105ab826103ed565b82516105c1816105ba81610141565b03826104ae565b82528251906105d3826104e281610214565b602083019182528351948552600481101561053557849361063f9361060e9260208701526060828701525190606086015260a085019061055d565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa084830301608085015261055d565b0390f35b346100e95760a06003193601126100e957600460026001541461097a5760026001556011549073ffffffffffffffffffffffffffffffffffffffff91828160081c1633036109515760ff16610929576106a161069d611db8565b1590565b610901576106f3906106b16114b6565b92604051937f62b61c8b0000000000000000000000000000000000000000000000000000000085528480600095869360843560643560243589358a87016115da565b0381305afa93841561087957839084956108da575b50610712906116c7565b61076e602060405161073c8161072e8985830160209181520190565b03601f1981018352826104ae565b604051809381927fcad31c740000000000000000000000000000000000000000000000000000000083528783016119c8565b038187305af18015610879576107b79185916108ab575b5060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00601154169115151617601155565b60115460ff16610882575b7f00000000000000000000000000000000000000000000000000000000000000001690813b1561087e57604080517faa733a4400000000000000000000000000000000000000000000000000000000815232928101928352602083018690529392849290918391859183910103925af1801561087957610860575b5060115460ff1661084d60018055565b6040805191151582526020820192909252f35b8061086d6108739261040e565b806100de565b3861083d565b611649565b8280fd5b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e8380a16107c2565b6108cd915060203d6020116108d3575b6108c581836104ae565b8101906117f3565b38610785565b503d6108bb565b61071295506108fb91503d8086833e6108f381836104ae565b81019061156c565b94610708565b6040517f741926a1000000000000000000000000000000000000000000000000000000008152fd5b6040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b506040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b6040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b908160809103126100e95790565b6020815273ffffffffffffffffffffffffffffffffffffffff80835116602083015260208301511660408201526040820151606082015260a06080610a026060850151838386015260c085019061055d565b93015191015290565b346100e95760206003193601126100e95760043567ffffffffffffffff81116100e957610a3f61063f9136906004016109a2565b610a47611aa5565b5073ffffffffffffffffffffffffffffffffffffffff90610aac826000541692604083013590610a7682611ad0565b610a836060850185611af8565b91909260405196610a9388610422565b8752166020860152602084013560408601523691611b49565b6060830152356080820152604051918291826109b0565b9181601f840112156100e95782359167ffffffffffffffff83116100e9576020808501948460051b0101116100e957565b929190610b0b60209160408652604086019061055d565b930152565b346100e95760c06003193601126100e95767ffffffffffffffff6084358181116100e957610b42903690600401610ac3565b60a4929192359182116100e957610ca8610ca3610cd194610b6a610cc19536906004016109a2565b93610c88610b8d610c81610b7c6114c9565b97610b92610b8d60208301356127cc565b6122c6565b610b9b8a611baf565b52610ba589611baf565b50610bb4610b8d6004356127cc565b610bbd8a611bc1565b52610bc789611bc1565b50610bd6610b8d6044356127cc565b610bdf8a611bd1565b52610be989611bd1565b50610bf8610b8d6064356127cc565b610c018a611be1565b52610c0b89611be1565b50610c1a610b8d6024356127cc565b610c238a611bf1565b52610c2d89611bf1565b50610c42610c3d60408301611aee565b612285565b610c4b8a611c01565b52610c5589611c01565b50610c63610b8d82356127cc565b610c6c8a611c11565b52610c7689611c11565b506060810190611af8565b3691611b49565b610c9186611c21565b52610c9b85611c21565b503691611c57565b61244c565b610cb182611c32565b52610cbb81611c32565b5061244c565b610ccc610b8d6126ed565b61257c565b805160208201209061063f60405192839283610af4565b346100e95760006003193601126100e9576020610d03611db8565b6040519015158152f35b60095460009291610d1d826100ee565b808252916020906001908181169081156101d05750600114610d3f5750505050565b9293945060096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af926000935b858510610d8857505050602092500101903880808061016e565b8054858501840152938201938101610d6e565b600c5460009291610dab826100ee565b808252916020906001908181169081156101d05750600114610dcd5750505050565b92939450600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7926000935b858510610e1657505050602092500101903880808061016e565b8054858501840152938201938101610dfc565b805460009392610e38826100ee565b91828252602093600191600181169081600014610ea05750600114610e5f575b5050505050565b90939495506000929192528360002092846000945b838610610e8c57505050500101903880808080610e58565b805485870183015294019385908201610e74565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b010191503880808080610e58565b604051906104e9826104e281610d9b565b67ffffffffffffffff81116104095760051b60200190565b600b5490610f1382610eee565b916040610f2360405194856104ae565b81845283602080910191600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9906000935b858510610f6757505050505050565b60018481928451610f7c816105ba818a610e29565b815201930194019391610f58565b90808251908181526020809101926020808460051b8301019501936000915b848310610fb95750505050505090565b9091929394958480610fd783601f1986600196030187528a5161055d565b9801930193019194939290610fa9565b61103860606110cd9493604084528051604085015260208101518285015273ffffffffffffffffffffffffffffffffffffffff60408201511660808501520151608060a084015260c083019061055d565b90602081830391015267ffffffffffffffff825116815260c06110bc611082611070602086015160e0602087015260e0860190610f8a565b6040860151858203604087015261055d565b60608581015167ffffffffffffffff169085015260808581015167ffffffffffffffff169085015260a085015184820360a086015261055d565b9201519060c081840391015261055d565b90565b346100e95760006003193601126100e957604080516110ee8161043e565b6006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416828201528151611127816105ba81610d0d565b606082015261063f82519261113b8461045a565b61119267ffffffffffffffff80600a54168652611156610f06565b6020870152611163610edd565b86840152600d5467ffffffffffffffff828216166060880152831c16608086019067ffffffffffffffff169052565b61119a6104d1565b60a08501526111a76104eb565b60c08501525192839283610fe7565b346100e9576000806003193601126100db5760ff60115416156112c557604051908082601254916111e6836100ee565b928383526020946001918660018216918260001461128457505060011461122a575b5050611216925003836104ae565b61063f60405192828493845283019061055d565b90859250601282527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34445b85831061126c57505061121693508201013880611208565b80548389018501528794508693909201918101611254565b915093506112169592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611208565b60046040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b346100e9576000806003193601126100db57611309611aa5565b50604051907f5a509280000000000000000000000000000000000000000000000000000000008252602060048301528082806113476024820161159d565b0381305afa908115610879578091611368575b6040518061063f84826109b0565b90503d8082843e61137981846104ae565b820160208382031261141057825167ffffffffffffffff9384821161140c57019260a08483031261087e57604051926113b184610422565b84516113bc81611ad0565b845260208501516113cc81611ad0565b60208501526040850151604085015260608501519182116100db5750926113fa60809261063f95830161152a565b6060840152015160808201523861135a565b8380fd5b5080fd5b346100e9576003196060813601126100e95760043567ffffffffffffffff918282116100e95760e09082360301126100e957602435918083116100e957366023840112156100e9578260040135928184116100e95736602485830101116100e9576044359182116100e95761063f936114a4936114976024943690600401610ac3565b9490930190600401612176565b60405190151581529081906020820190565b6040516114c281610492565b6000815290565b60405190610140820182811067ffffffffffffffff82111761040957604052600982528160005b61012081106114fd575050565b8060606020809385010152016114f0565b67ffffffffffffffff811161040957601f01601f191660200190565b81601f820112156100e95780516115408161150e565b9261154e60405194856104ae565b818452602082840101116100e9576110cd916020808501910161053a565b91906040838203126100e957825167ffffffffffffffff81116100e95760209161159791850161152a565b92015190565b60806110cd916006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416604082015281606082015201610d0d565b9293608094611609936110cd9793865260208601526040850152606084015260c08484015260c0830190610f8a565b9060a08183039101526006548152600754602082015273ffffffffffffffffffffffffffffffffffffffff60085416604082015281606082015201610d0d565b6040513d6000823e3d90fd5b601f8111611661575050565b60009060126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444906020601f850160051c830194106116bd575b601f0160051c01915b8281106116b257505050565b8181556001016116a6565b909250829061169d565b90815167ffffffffffffffff8111610409576116ed816116e86012546100ee565b611655565b602080601f831160011461174d5750819061173d9394600092611742575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b601255565b01519050388061170b565b90601f1983169461178060126000527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344490565b926000905b8782106117db5750508360019596106117a4575b505050811b01601255565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611799565b80600185968294968601518155019501930190611785565b908160209103126100e9575180151581036100e95790565b80600b5480825260208092019160208260051b85010193600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9936000915b84831061185d5750505050505090565b90919293949584600161187a83601f19868496030187528a610e29565b980193019301919493929061184d565b8060105490818152602080910191600591808260051b86010194600094601086527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6729580925b8584106118e257505050505050505090565b9091929394959697601f19828203018452856040808352898b8692815490611909826100ee565b8091880152606091600194858216918260001461198b57505060011461194a575b5050015492820192909252909860020197969594600101930191906118d0565b909180945088528488209088915b81831061196d5750508501019183600161192a565b8496929491939550805486868a0101520192018d93918b9593611958565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168985015291151590911b87019091019350849050600161192a565b611a976110cd92606083526119fb606084016119ed600a5467ffffffffffffffff1690565b67ffffffffffffffff169052565b60e06080840152611a89611a12610140850161180b565b611a79611a497fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa092838882030160a0890152610d9b565b600d5467ffffffffffffffff80821660c08a015260409190911c1660e088015282878203016101008801526102a2565b9085820301610120860152610330565b90838203602085015261055d565b90604081830391015261188a565b60405190611ab282610422565b60006080838281528260208201528260408201526060808201520152565b73ffffffffffffffffffffffffffffffffffffffff8116036100e957565b356110cd81611ad0565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e9570180359067ffffffffffffffff82116100e9576020019181360383136100e957565b929192611b558261150e565b91611b6360405193846104ae565b8294818452818301116100e9578281602093846000960137010152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115611bbc5760200190565b611b80565b805160011015611bbc5760400190565b805160021015611bbc5760600190565b805160031015611bbc5760800190565b805160041015611bbc5760a00190565b805160051015611bbc5760c00190565b805160061015611bbc5760e00190565b805160071015611bbc576101000190565b805160081015611bbc576101200190565b8051821015611bbc5760209160051b010190565b92919092611c6484610eee565b91611c7260405193846104ae565b829480845260208094019060051b8301928284116100e95780915b848310611c9c57505050505050565b823567ffffffffffffffff81116100e957820184601f820112156100e9578691611ccc8683858095359101611b49565b815201920191611c8d565b67ffffffffffffffff8116036100e957565b8091039060c082126100e95760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa060405193611d258561043e565b8351611d3081611cd7565b85526020840151611d4081611cd7565b60208601526040840151611d5381611cd7565b604086015201126100e95760a060405191611d6d83610476565b6060810151611d7b81611cd7565b83526080810151602084015201516040820152606082015290565b6110cd9060408152611daa60408201610141565b906020818303910152610214565b6040517f3d0f34da00000000000000000000000000000000000000000000000000000000815260c08180611dee60048201611d96565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561087957600091611ea8575b5060035460ff16611e488161052b565b60018103611e6157506060015160400151600254111590565b611e6a8161052b565b611e7e576060015160400151600254101590565b60046040517f951a55bf000000000000000000000000000000000000000000000000000000008152fd5b611eca915060c03d60c011611ed0575b611ec281836104ae565b810190611ce9565b38611e38565b503d611eb8565b356110cd81611cd7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e9570180359067ffffffffffffffff82116100e957602001918160051b360383136100e957565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100e957016020813591019167ffffffffffffffff82116100e95781360383136100e957565b90918092808252602080920191808260051b8601019484600080925b858410611fd457505050505050505090565b9091929394959697601f1982820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18536030181121561140c57866001928682930190828061203a604061202d8680611f56565b9091808752860191611f35565b9301359101529a01980196959401929190611fc2565b9e9b999f9d9c9a989694918f969493906120859167ffffffffffffffff610140941689526020938060208b0152890191611f35565b956040818803910152818652602086019560208360051b82010196846000925b85841061213d5750505050505050946121088c9d60a06120f76104e99e9f986101209e9c986120e96121359f9d99612119996121269e8e6060818503910152611f35565b918b830360808d0152611fa6565b97019067ffffffffffffffff169052565b67ffffffffffffffff1660c08d0152565b8a830360e08c0152611f35565b91878303610100890152611f35565b930160019052565b9091929394959885806121658361215f8e601f198860019803018a5288611f56565b90611f35565b9b01940194019295949391906120a5565b909293919361218482611ed7565b926121926020840184611ee1565b9390926121a26040830183611af8565b919093606084016121b290611ed7565b916121bf60808601611ed7565b936121cd60a0870187611af8565b97909660c081016121dd91611af8565b9a90996040519e8f9e8f7f07d145e90000000000000000000000000000000000000000000000000000000081526004019e6122179f612050565b03817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a602094600091f19081156108795760009161226c575090565b6110cd915060203d6020116108d3576108c581836104ae565b6110cd906040519074140000000000000000000000000000000000000000186014820152603481016040526122c6565b908151811015611bbc570160200190565b90600091805192600193600181149081612434575b50156122e657509150565b81519360388510156123405750926110cd92937fff0000000000000000000000000000000000000000000000000000000000000061232b61232561260e565b936128bb565b60f81b16901a61233a82611baf565b5361257c565b8190806001915b612404575b505061235f61235a8261289f565b612640565b917fff0000000000000000000000000000000000000000000000000000000000000061239261238d846128bb565b6128ad565b8160f89160f81b16831a6123a586611baf565b5360015b848111156123c15750505050506110cd92935061257c565b80836123ea6123e46123de6123d96123ff968b6126b3565b6128e4565b8d61284f565b60ff1690565b841b16851a6123f982896122b5565b536126c0565b6123a9565b9091612410838861284f565b1561242e57612421612427916126c0565b92612888565b9080612347565b9161234c565b905015611bbc576080602083015160f81c10386122db565b6124559061297e565b9081516000603882106000146124ae5750916110cd91927fff0000000000000000000000000000000000000000000000000000000000000061249e61249861260e565b926128c9565b60f81b1660001a61233a82611baf565b916001925b6124bd848461284f565b156124da576124ce6124d4916126c0565b93612888565b926124b3565b9092509290926124ec61235a8261289f565b907fff0000000000000000000000000000000000000000000000000000000000000061251a61238d836128c9565b8160f89160f81b1660001a61252e85611baf565b5360015b8381111561254957505050506110cd92935061257c565b80836125676123e46125616123d9612577968a6126b3565b8c61284f565b841b1660001a6123f982886122b5565b612532565b6040518151808252909290830191602083810192818301828088015b8681106125e55750505080518094875182018852950194828087019201905b8281106125d6575050505091603f91601f199351011501011660405290565b815181529083019083016125b7565b8251815291810191849101612598565b60405190612602826103ed565b60208083523683820137565b6040519061261b826103ed565b6001825260203681840137565b60405161263481610492565b60008152906000368137565b9061264a8261150e565b61265760405191826104ae565b828152601f19612667829461150e565b0190602036910137565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60200390602082116126ae57565b612671565b919082039182116126ae57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146126ae5760010190565b6126f56125f5565b90602091600260208201526000926000905b808210612783575b5061271c61235a826126a0565b9160005b835181101561277b5760019061276861274261273b866126c0565b95856122b5565b517fff000000000000000000000000000000000000000000000000000000000000001690565b871a61277482876122b5565b5301612720565b509193505050565b906127b961279461274283866122b5565b7fff000000000000000000000000000000000000000000000000000000000000001690565b6127c65760010190612707565b9061270f565b906127d56125f5565b60209260208201526000926000905b80821061282b575b506127f961235a826126a0565b9160005b835181101561277b5760019061281861274261273b866126c0565b871a61282482876122b5565b53016127fd565b9061283c61279461274283866122b5565b61284957600101906127e4565b906127ec565b8115612859570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b908160081b9180830461010014901517156126ae57565b90600182018092116126ae57565b90603782018092116126ae57565b90608082018092116126ae57565b9060c082018092116126ae57565b919082018092116126ae57565b601f81116126ae576101000a90565b156128fa57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f416e206974656d20696e20746865206c69737420746f20626520524c5020656e60448201527f636f646564206973206e756c6c2e0000000000000000000000000000000000006064820152fd5b805115612a235790600091825b81518410156129ca576129c26001916129b06129a78786611c43565b515115156128f3565b6129ba8685611c43565b5151906128d7565b93019261298b565b6129d691929350612640565b906020808301936000945b8351861015612a1b57612a13600191612a096129fd8988611c43565b51868151910183612a2c565b6129ba8887611c43565b9501946129e1565b509350505090565b506110cd612628565b92905b602093848410612a6457815181528481018091116126ae579381018091116126ae5791601f1981019081116126ae5791612a2f565b9290919350602003602081116126ae57612a7d906128e4565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116126ae57518251821691191617905256fea164736f6c6343000819000a6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7afa164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca83" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0x8e0be03a943558f7822446da997c035ee27bdad3f88a391c2e2223c4632244fb", + "transactionType": "CALL", + "contractName": "Create2", + "contractAddress": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "function": "deploy(bytes32,bytes)", + "arguments": [ + "0x6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003ea", + "0x60a034607357601f615cf138819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607357516001600160a01b038116908190036073576001600055608052604051615c62908161008f823960805181818160e9015261042d0152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c90816306433b1b146100a45781630b0fdb3d14610055575080637fddd602146100505763b60bda491461004b57600080fd5b61020f565b610145565b346100a15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15760ff60406020926004358152600184522054166040519015158152f35b80fd5b346100a157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b600091031261011d57565b600080fd5b6064359073ffffffffffffffffffffffffffffffffffffffff8216820361011d57565b3461011d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011d5760043573ffffffffffffffffffffffffffffffffffffffff80821680920361011d576101d56020926040516101cd816101bf8782019460243590869091604092825260208201520190565b03601f19810183528261033f565b519020610b6e565b60405191168152f35b9181601f8401121561011d5782359167ffffffffffffffff831161011d576020808501948460051b01011161011d57565b3461011d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a08136011261011d576004359067ffffffffffffffff9081831161011d57608081843603011261011d576024359082821161011d57604090823603011261011d5760443591821161011d576102d7926102966102b09336906004016101de565b9061029f610122565b926084359460040190600401610362565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161031e57604052565b6102db565b6040810190811067ffffffffffffffff82111761031e57604052565b90601f601f19910116810190811067ffffffffffffffff82111761031e57604052565b93929490916000916002835414610640576002835560409586519182610398602082019232849091604092825260208201520190565b03926103ac601f199485810183528261033f565b519020946103ce6103c7876000526001602052604060002090565b5460ff1690565b6106175732867f4d26f9b035ac4dafb21ce257260243ad6adf7e105ac6517fe42bebde1d0828ca8780a3614e29916104086020840161066a565b92808452610e2d602085013973ffffffffffffffffffffffffffffffffffffffff998a7f0000000000000000000000000000000000000000000000000000000000000000169889918b51978895602087019561046396610a48565b038281018452610473908461033f565b86519283916020830161048591610b37565b61048e91610b37565b03908101825261049e908261033f565b6104a89083610d3e565b946104b283610b6e565b9080871690811592831561060a575b5050506105d957823b156100a15783517f4420e48600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86166004820152928390602490829084905af19081156105d45761056c92610541926105bb575b506000526001602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b5173ffffffffffffffffffffffffffffffffffffffff8216815233907ffb2d8b84e2e1acdcdbad3ce10c5a03d9f07b3f9f2e4a6d818a1a6a43610ac3b990602090a2906105b96001600055565b565b806105c86105ce9261030a565b80610112565b38610530565b610b62565b83517f8e6ae65f00000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b16141590503880806104c1565b600488517f0ced3043000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b906105b9604051928361033f565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18236030181121561011d570190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561011d57016020813591019167ffffffffffffffff821161011d57813603831361011d57565b601f8260209493601f19938186528686013760008582860101520116010190565b6107569161074861073d61072f84806106aa565b6040855260408501916106fa565b9260208101906106aa565b9160208185039101526106fa565b90565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218236030181121561011d570190565b359067ffffffffffffffff8216820361011d57565b908281815260208091019360208360051b82010194846000925b8584106107cb575050505050505090565b9091929394959685806107f383601f1986600196030188526107ed8c886106aa565b906106fa565b9901940194019295949391906107ba565b67ffffffffffffffff91826108188361078b565b16815260208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181121561011d5782019260208435940190841161011d578360051b3603811361011d576109006108a561088a61090b936107569760e0602088015260e08701916107a0565b61089760408701876106aa565b9086830360408801526106fa565b6108c56108b46060870161078b565b67ffffffffffffffff166060860152565b6108e56108d46080870161078b565b67ffffffffffffffff166080860152565b6108f260a08601866106aa565b9085830360a08701526106fa565b9260c08101906106aa565b9160c08185039101526106fa565b80357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818236030181121561011d57810191604081528235604082015260208301356060820152604083013573ffffffffffffffffffffffffffffffffffffffff811680910361011d576109b061099f610756956109bb93608086015260608101906106aa565b608060a086015260c08501916106fa565b926020810190610759565b906020818403910152610804565b9082818152602080910193818360051b82010194846000925b8584106109f3575050505050505090565b90919293949596858082601f198560019503018752610a128b87610678565b908280610a316040610a2486806106aa565b90918087528601916106fa565b9301359101529901940194019295949391906109e2565b91909496959360a08352610ab0610a74610a628880610678565b608060a087015261012086019061071b565b610a816020890189610678565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608683030160c087015261071b565b93604087013591600483101561011d57610aee608096610b1b9560606105b99b610afc9760e08b015201356101008901528782036020890152610919565b9185830360408701526109c9565b73ffffffffffffffffffffffffffffffffffffffff9097166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b9081519160005b838110610b4f575050016000815290565b8060208092840101518185015201610b3e565b6040513d6000823e3d90fd5b6040519060208201907fff0000000000000000000000000000000000000000000000000000000000000082523060601b602184015260358301527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605583015260558252608082019180831067ffffffffffffffff84111761031e57827f010000000000000000000000000000000000000000000000000000000000000060b6610c9b946107569660405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610c7f81610323565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051906040820182811067ffffffffffffffff82111761031e57604052601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b3d15610d39573d9067ffffffffffffffff821161031e5760405191610d2d6020601f19601f840116018461033f565b82523d6000602084013e565b606090565b9190610d48610cb4565b92610d5281610b6e565b93843b610e02576020815191016000f573ffffffffffffffffffffffffffffffffffffffff811615610dd85781600092918360208194519301915af1610d96610cfe565b50158015610dcf575b610da557565b60046040517f53de54b9000000000000000000000000000000000000000000000000000000008152fd5b50813b15610d9f565b60046040517fbbd2fe87000000000000000000000000000000000000000000000000000000008152fd5b60046040517fcd43efa1000000000000000000000000000000000000000000000000000000008152fdfe6101006040523461145957614e29803803809161001e826101006118c6565b6101003960a0811261145957610100516001600160401b03811161145957610100019060808282610100010312611459576040519161005c83611875565b80516001600160401b0381116114595761007d908361010001908301611960565b835260208101516001600160401b038111611459576100a3908361010001908301611960565b6020840152604081015190600482101561145957604084019190915260609081015190830152610120516001600160401b03811161145957610100016040818361010001031261145957604051906100fa82611890565b80516001600160401b03811161145957810160808185610100010312611459576040519061012782611875565b8051825260208101516020830152610141604082016119bc565b60408301526060810151906001600160401b0382116114595761016a918661010001910161190c565b6060820152825260208101516001600160401b0381116114595760e08183018561010001031261145957604051916101a1836118ab565b6101ac8282016119d0565b8352808201602001516001600160401b038111611459578561010001601f8285850101011215611459578083830101516101e5816119e4565b916101f360405193846118c6565b81835260208301886101000160208460051b8489890101010111611459576020828787010101905b60208460051b84898901010101821061183957505050506020840152808201604001516001600160401b0381116114595761025f908661010001908484010161190c565b60408401526102726060838301016119d0565b60608401526102856080838301016119d0565b608084015280820160a001516001600160401b038111611459576102b2908661010001908484010161190c565b60a084015280820160c001516001600160401b038111611459576102dd92866101000192010161190c565b60c08201526020820152610140516001600160401b03811161145957610100830161011f8201121561145957806101000151610318816119e4565b9361032660405195866118c6565b81855260208501926101008201610120600585901b83010111611459576101208101935b610120600585901b83010185106117c0578787876103696101606119bc565b926103756101806119bc565b602083015183516001600160a01b038716156117ae576001600160a01b0383161561179c5760a0820151511561178a5760c0820151511561177857604001516001600160a01b03161561176657610900608052604051906103d582611890565b600182526020368184013760016103eb836119fb565b5260805190516040805163338c1f5160e01b81526001600160401b039092166004830152602482015282516044820181905290926001600160a01b0390921691839160648301916020019060005b81811061174a5750505091818060009403915afa908115611466576000916114e0575b5061046d60206104779201516119fb565b5151805190611aca565b90156114ce57600080546001600160a01b0319166001600160a01b039290921691909117905561090260a05261090360c0526040516001600160401b0360608201908111908211176107d257606081016040526002815260005b604081106114bd57506020830151516104e9826119fb565b526104f3816119fb565b50602080840151015161050582611a08565b5261050f81611a08565b5060405161051c81611890565b6001815260646020820152606084810151604051939184018085116001600160401b03909111176107d2576060840160405283526020830152604082015260018060a01b0360c05116906040519060208083015260c08201908051604084015260208101519160806060850152825180915260e0840190602060e08260051b8701019401916000905b8282106114925750505050604001516000608084015b6002821061147257505050819003601f1981018252600092602092610628926105e490826118c6565b604051948580948193630b1e6daf60e31b83526040600484015260096044840152681c1c9a58d95c1c995960ba1b6064840152608060248401526084830190611a18565b03925af190811561146657600091611427575b50601180546001600160401b0319166001600160401b03929092169190911790556001600160a01b031660e05260005b83518110156107fe5760208160051b8501015160125490680100000000000000008210156107d25760018201806012558210156107e8576012600052805180517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492916001600160401b0382116107d2576106fa826106ef8760011b870154611a3d565b8760011b8701611a8e565b602090601f83116001146107555792610735836001989796946020948a9760009261074a575b50508160011b916000199060031b1c19161790565b85851b8401555b015192821b0101550161066b565b015190508e80610720565b908560011b850160005260206000209160005b601f19851681106107ba575083602093600199989795938a9794938894601f198116106107a1575b505050811b0185851b84015561073c565b015160001960f88460031b161c191690558d8080610790565b91926020600181928685015181550194019201610768565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b508051805180518692916001600160401b0382116107d257610821600154611a3d565b601f81116113d8575b50602090601f831160011461136957918061085f92602095946000926111e65750508160011b916000199060031b1c19161790565b6001555b015180519093906001600160401b0381116107d257610883600254611a3d565b601f811161131a575b506020601f82116001146112af5781906108bf93949596600092610d5c5750508160011b916000199060031b1c19161790565b6002555b602083015180518051906001600160401b0382116107d2576108e6600354611a3d565b601f8111611260575b50602090601f83116001146111f157918061092492602095946000926111e65750508160011b916000199060031b1c19161790565b6003555b015180519093906001600160401b0381116107d257610948600454611a3d565b601f8111611197575b506020601f821160011461112c57819061098493949596600092610d5c5750508160011b916000199060031b1c19161790565b6004555b60408101519060048210156111165760609160ff8019600554169116176005550151600655606081518051600755602081015160085560018060a01b0360408201511660018060a01b03196009541617600955015180519060018060401b0382116107d2576109f8600a54611a3d565b601f81116110d9575b50602090601f8311600114611061579180610a369260209594600092610d5c5750508160011b916000199060031b1c19161790565b600a555b01519060018060401b0382511660018060401b0319600b541617600b5560208201518051906801000000000000000082116107d257600c5482600c55808310610fd0575b50600c60009081527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c792916020015b828210610ee95760408601518051869088906001600160401b0381116107d257610ad8600d54611a3d565b601f8111610e9a575b506020601f8211600114610e30578190610b13939495600092610e255750508160011b916000199060031b1c19161790565b600d555b6060810151600e805460808401516001600160801b03199091166001600160401b039384161760409190911b6fffffffffffffffff00000000000000001617905560a082015180519182116107d257610b71600f54611a3d565b601f8111610dd6575b50602090601f8311600114610d67579180610baf9260c09594600092610d5c5750508160011b916000199060031b1c19161790565b600f555b015180519091906001600160401b0381116107d257610bd3601054611a3d565b601f8111610d02575b50602092601f8211600114610c9c57610c0e92938291600092610c915750508160011b916000199060031b1c19161790565b6010555b60138054610100600160a81b03191660089290921b610100600160a81b031691909117905542620151808101908110610c7b576015556040516131bd9081611c4c8239608051816127b1015260a05181612371015260c051816122c5015260e0518161091e0152f35b634e487b7160e01b600052601160045260246000fd5b015190508480610720565b601f19821693601060005260206000209160005b868110610cea5750836001959610610cd1575b505050811b01601055610c12565b015160001960f88460031b161c19169055838080610cc3565b91926020600181928685015181550194019201610cb0565b6010600052610d4c907f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672601f840160051c81019160208510610d52575b601f0160051c0190611a77565b83610bdc565b9091508190610d3f565b015190508680610720565b90600f60005260206000209160005b601f1985168110610dbe575091839160019360c09695601f19811610610da5575b505050811b01600f55610bb3565b015160001960f88460031b161c19169055858080610d97565b91926020600181928685015181550194019201610d76565b600f600052610e1f907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802601f850160051c81019160208610610d5257601f0160051c0190611a77565b84610b7a565b015190508580610720565b600d60005260206000209060005b601f1984168110610e825750600193949583601f19811610610e69575b505050811b01600d55610b17565b015160001960f88460031b161c19169055848080610e5b565b9091602060018192858a015181550193019101610e3e565b600d600052610ee3907fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5601f840160051c81019160208510610d5257601f0160051c0190611a77565b84610ae1565b80518051906001600160401b0382116107d257610f1082610f0a8854611a3d565b88611a8e565b602090601f8311600114610f625792610f4883600195946020948796600092610f575750508160011b916000199060031b1c19161790565b87555b01940191019092610aad565b015190508c80610720565b90601f198316918760005260206000209260005b818110610fb85750936020936001969387969383889510610f9f575b505050811b018755610f4b565b015160001960f88460031b161c191690558b8080610f92565b92936020600181928786015181550195019301610f76565b600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c79081019083015b81811061100a5750610a7e565b8061101760019254611a3d565b80611024575b5001610ffd565b601f8111831461103a5750600081555b8761101d565b600090828252611058601f60208420920160051c8201858301611a77565b81835555611034565b600a6000908152600080516020614e09833981519152929190601f198516905b8181106110c157509160019391856020979694106110a8575b505050811b01600a55610a3a565b015160001960f88460031b161c1916905585808061109a565b92936020600181928786015181550195019301611081565b600a60005261111090600080516020614e09833981519152601f850160051c81019160208610610d5257601f0160051c0190611a77565b84610a01565b634e487b7160e01b600052602160045260246000fd5b600460005260206000209060005b601f198416811061117f575060019394959683601f19811610611166575b505050811b01600455610988565b015160001960f88460031b161c19169055858080611158565b9091602060018192858b01518155019301910161113a565b60046000526111e0907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81019160208510610d5257601f0160051c0190611a77565b85610951565b015190508880610720565b90600360005260206000209160005b601f1985168110611248575091839160019360209695601f1981161061122f575b505050811b01600355610928565b015160001960f88460031b161c19169055878080611221565b91926020600181928685015181550194019201611200565b60036000526112a9907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f850160051c81019160208610610d5257601f0160051c0190611a77565b866108ef565b600260005260206000209060005b601f1984168110611302575060019394959683601f198116106112e9575b505050811b016002556108c3565b015160001960f88460031b161c191690558580806112db565b9091602060018192858b0151815501930191016112bd565b6002600052611363907f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f840160051c81019160208510610d5257601f0160051c0190611a77565b8561088c565b90600160005260206000209160005b601f19851681106113c0575091839160019360209695601f198116106113a7575b505050811b01600155610863565b015160001960f88460031b161c19169055878080611399565b91926020600181928685015181550194019201611378565b6001600052611421907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f850160051c81019160208610610d5257601f0160051c0190611a77565b8661082a565b90506020813d60201161145e575b81611442602093836118c6565b8101031261145957611453906119d0565b8661063b565b600080fd5b3d9150611435565b6040513d6000823e3d90fd5b82516001600160401b0316815260209283019260019290920191016105bb565b909192946020806114af60019360df198b82030186528951611a18565b9701920192019092916105a5565b8060606020809385010152016104d1565b6040516307456b9160e21b8152600490fd5b903d8082843e6114f081846118c6565b6020838281010312611746578251926001600160401b0384116117425760408482018383010312611742576040519361152885611890565b818101516001600160401b03811161173e5760e08183850101858501031261173e5760405190611557826118ab565b61156481848601016119d0565b825261157660208285870101016119d0565b602083015261158b60408285870101016119d0565b6040830152606081848601010151600381101561172b5760608301528383018101608001516001600160401b03811161172b576115fb916115d760c0928888019083888a01010161190c565b60808501526115ec60a08287890101016119d0565b60a085015284860101016119d0565b60c0820152855281810160200151936001600160401b03851161173b57838301601f868486010101121561173b5784828401015192611639846119e4565b9561164760405197886118c6565b848752602087019386830160208760051b8484870101010111611737576020828285010101945b60208760051b84848701010101861061169b57505050505060208501939093525061046d915061045c9050565b85516001600160401b038111611733576040858401850182018a870103601f19011261173357604051906116ce82611890565b85840185018101602001516001600160401b03811161172f579061170260409260208d8a0191848a8a8d010101010161190c565b83528585880101010151600381101561172b57602082810191909152908252958601950161166e565b8680fd5b8780fd5b8580fd5b8380fd5b80fd5b8480fd5b8280fd5b5080fd5b825160030b845286945060209384019390920191600101610439565b604051630695a62360e51b8152600490fd5b604051636fc5f47160e01b8152600490fd5b60405163460be67160e11b8152600490fd5b6040516311a1e69760e01b8152600490fd5b60405163bcda548360e01b8152600490fd5b84516001600160401b038111611459578201610100810191906040908503601f19011261145957604051916117f483611890565b6020810151916001600160401b0383116114595760209360408594936118248695868b610100019184010161190c565b8352015183820152815201950194905061034a565b8151906001600160401b03821161145957602080929161186889838f95898e839861010001940101010161190c565b815201920191905061021b565b608081019081106001600160401b038211176107d257604052565b604081019081106001600160401b038211176107d257604052565b60e081019081106001600160401b038211176107d257604052565b601f909101601f19168101906001600160401b038211908210176107d257604052565b60005b8381106118fc5750506000910152565b81810151838201526020016118ec565b81601f820112156114595780516001600160401b0381116107d2576040519261193f601f8301601f1916602001856118c6565b818452602082840101116114595761195d91602080850191016118e9565b90565b9190604083820312611459576040519061197982611890565b8351919384926001600160401b039290838111611459578161199c91840161190c565b84526020820151928311611459576020926119b7920161190c565b910152565b51906001600160a01b038216820361145957565b51906001600160401b038216820361145957565b6001600160401b0381116107d25760051b60200190565b8051156107e85760200190565b8051600110156107e85760400190565b90602091611a31815180928185528580860191016118e9565b601f01601f1916010190565b90600182811c92168015611a6d575b6020831014611a5757565b634e487b7160e01b600052602260045260246000fd5b91607f1691611a4c565b818110611a82575050565b60008155600101611a77565b9190601f8111611a9d57505050565b611ac8926000526020600020906020601f840160051c83019310610d5257601f0160051c0190611a77565b565b9061060f60f31b61ffff60f01b602084015116148060011b9080820460021490151715610c7b5760280180602811610c7b578103611b1b57611b0b91611b25565b90916001600160a01b0390911690565b5050600090600090565b919060209061060f60f31b61ffff60f01b60208601511614936001928560011b9580870460021490151715610c7b57929190600095935b828510611b6e57505050505060019190565b909192939560ff611b888160f81b848a8701015116611bd9565b1690600f8211611bc957600481811b9180830460101490151715611bb457500195840193929190611b5c565b601190634e487b7160e01b6000525260246000fd5b5050505050509050600090600090565b60f81c602f811180611c41575b15611bf557602f190160ff1690565b6060811180611c37575b15611c0e576056190160ff1690565b6040811180611c2d575b15611c27576036190160ff1690565b5060ff90565b5060478110611c18565b5060678110611bff565b50603a8110611be656fe6080604052600436101561001257600080fd5b60003560e01c80631c9feaa5146100d7578063229e81fb146100d257806342859ab3146100cd5780635a509280146100c857806362b61c8b146100c357806378b90337146100be578063819ef8ba146100b957806388328a69146100b4578063b3d7ad48146100af578063cad31c74146100aa578063cbe61e59146100a55763d47e4eeb146100a057600080fd5b61165d565b611635565b611593565b61146e565b611350565b61126a565b610e15565b610c3d565b610b38565b6107ca565b61072c565b6100ec565b60009103126100e757565b600080fd5b346100e75760006003193601126100e757602060ff601354166040519015158152f35b90600182811c92168015610158575b602083101461012957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161011e565b600f54600092916101728261010f565b808252916020906001908181169081156101f15750600114610195575b50505050565b92939450600f6000527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000935b8585106101de57505050602092500101903880808061018f565b80548585018401529382019381016101c4565b915050602094955060ff1991509291921683830152151560051b0101903880808061018f565b601054600092916102278261010f565b808252916020906001908181169081156101f157506001146102495750505050565b9293945060106000527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672926000935b85851061029257505050602092500101903880808061018f565b8054858501840152938201938101610278565b600454600092916102b58261010f565b808252916020906001908181169081156101f157506001146102d75750505050565b9293945060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000935b85851061032057505050602092500101903880808061018f565b8054858501840152938201938101610306565b906000916001906001546103468161010f565b80835292602091600181169081156101f157506001146103665750505050565b9293945060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6926000935b8585106103af57505050602092500101903880808061018f565b8054858501840152938201938101610395565b600254600092916103d28261010f565b808252916020906001908181169081156101f157506001146103f45750505050565b9293945060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace926000935b85851061043d57505050602092500101903880808061018f565b8054858501840152938201938101610423565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761049b57604052565b610450565b67ffffffffffffffff811161049b57604052565b60a0810190811067ffffffffffffffff82111761049b57604052565b6080810190811067ffffffffffffffff82111761049b57604052565b60e0810190811067ffffffffffffffff82111761049b57604052565b6060810190811067ffffffffffffffff82111761049b57604052565b6020810190811067ffffffffffffffff82111761049b57604052565b90601f601f19910116810190811067ffffffffffffffff82111761049b57604052565b6040519061057b8261057481610162565b0383610540565b565b6040519061057b8261057481610217565b6040519061059b8261047f565b60405160035483916000816105af8461010f565b91828252602094600190866001821691826000146106595750506001146105fc575b506105de92500382610540565b8252604051916105f8836105f1816102a5565b0384610540565b0152565b85915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b8583106106415750506105de9350820101386105d1565b8054838801850152869450879390920191810161062a565b60ff1916858201526105de95151560051b85010192503891506105d19050565b60005b83811061068c5750506000910152565b818101518382015260200161067c565b90601f19601f6020936106ba81518092818752878088019101610679565b0116010190565b6106eb9160206106da835160408452604084019061069c565b92015190602081840391015261069c565b90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004111561072757565b6106ee565b346100e75760006003193601126100e7576040516107498161047f565b6040516107608161075981610333565b0382610540565b815260405161077281610759816103c2565b602082015261077f61058e565b60ff60055416906107b0600654916107a2604051956080875260808701906106c1565b9085820360208701526106c1565b906004831015610727578392604084015260608301520390f35b346100e75760a06003193601126100e75760046013549073ffffffffffffffffffffffffffffffffffffffff91828160081c163303610aa65760ff16610a7e57610819610815612247565b1590565b610a565761086b90610829611679565b92604051937f62b61c8b0000000000000000000000000000000000000000000000000000000085528480600095869360843560643560243589358a87016117aa565b0381305afa9384156109ce5783908495610a2f575b5061088a90611897565b6108e660206040516108b4816108a68985830160209181520190565b03601f198101835282610540565b604051809381927fcad31c74000000000000000000000000000000000000000000000000000000008352878301611b7a565b038187305af180156109ce57610911918591610a00575b5060ff60ff19601354169115151617601355565b60135460ff166109d7575b7f00000000000000000000000000000000000000000000000000000000000000001690813b156109d357604080517faa733a4400000000000000000000000000000000000000000000000000000000815232928101928352602083018690529392849290918391859183910103925af180156109ce576109b5575b5060135460ff166040805191151582526020820192909252f35b0390f35b806109c26109c8926104a0565b806100dc565b38610997565b611819565b8280fd5b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e8380a161091c565b610a22915060203d602011610a28575b610a1a8183610540565b8101906119c3565b386108fd565b503d610a10565b61088a9550610a5091503d8086833e610a488183610540565b81019061173c565b94610880565b6040517f741926a1000000000000000000000000000000000000000000000000000000008152fd5b6040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b506040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b908160809103126100e75790565b6020815273ffffffffffffffffffffffffffffffffffffffff80835116602083015260208301511660408201526040820151606082015260a06080610b2f6060850151838386015260c085019061069c565b93015191015290565b346100e75760206003193601126100e75760043567ffffffffffffffff81116100e757610b6c6109b1913690600401610acf565b610b74611c57565b5073ffffffffffffffffffffffffffffffffffffffff90610bd9826000541692604083013590610ba382611c82565b610bb06060850185611caa565b91909260405196610bc0886104b4565b8752166020860152602084013560408601523691611cfb565b606083015235608082015260405191829182610add565b9181601f840112156100e75782359167ffffffffffffffff83116100e7576020808501948460051b0101116100e757565b929190610c3860209160408652604086019061069c565b930152565b346100e75760c06003193601126100e75767ffffffffffffffff6084358181116100e757610c6f903690600401610bf0565b60a4929192359182116100e757610dd5610dd0610dfe94610c97610dee953690600401610acf565b93610db5610cba610dae610ca961168c565b97610cbf610cba6020830135612f17565b61285c565b610cc88a611d61565b52610cd289611d61565b50610ce1610cba600435612f17565b610cea8a611d73565b52610cf489611d73565b50610d03610cba604435612f17565b610d0c8a611d83565b52610d1689611d83565b50610d25610cba606435612f17565b610d2e8a611d93565b52610d3889611d93565b50610d47610cba602435612f17565b610d508a611da3565b52610d5a89611da3565b50610d6f610d6a60408301611ca0565b61281b565b610d788a611db3565b52610d8289611db3565b50610d90610cba8235612f17565b610d998a611dc3565b52610da389611dc3565b506060810190611caa565b3691611cfb565b610dbe86611dd3565b52610dc885611dd3565b503691611e09565b6129e2565b610dde82611de4565b52610de881611de4565b506129e2565b610df9610cba612e38565b612b12565b80516020820120906109b160405192839283610c21565b346100e75760006003193601126100e7576020610e30612247565b6040519015158152f35b600a5460009291610e4a8261010f565b808252916020906001908181169081156101f15750600114610e6c5750505050565b92939450600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8926000935b858510610eb557505050602092500101903880808061018f565b8054858501840152938201938101610e9b565b600d5460009291610ed88261010f565b808252916020906001908181169081156101f15750600114610efa5750505050565b92939450600d6000527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5926000935b858510610f4357505050602092500101903880808061018f565b8054858501840152938201938101610f29565b600a5460009291610f668261010f565b808252916020906001908181169081156101f15750600114610f885750505050565b92939450600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8926000935b858510610fd157505050602092500101903880808061018f565b8054858501840152938201938101610fb7565b805460009392610ff38261010f565b9182825260209360019160018116908160001461105b575060011461101a575b5050505050565b90939495506000929192528360002092846000945b83861061104757505050500101903880808080611013565b80548587018301529401938590820161102f565b60ff19168685015250505090151560051b010191503880808080611013565b6040519061057b8261057481610ec8565b67ffffffffffffffff811161049b5760051b60200190565b600c54906110b08261108b565b9160406110c06040519485610540565b81845283602080910191600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7906000935b85851061110457505050505050565b6001848192845161111981610759818a610fe4565b8152019301940193916110f5565b90808251908181526020809101926020808460051b8301019501936000915b8483106111565750505050505090565b909192939495848061117483601f1986600196030187528a5161069c565b9801930193019194939290611146565b6111d560606106eb9493604084528051604085015260208101518285015273ffffffffffffffffffffffffffffffffffffffff60408201511660808501520151608060a084015260c083019061069c565b90602081830391015267ffffffffffffffff825116815260c061125961121f61120d602086015160e0602087015260e0860190611127565b6040860151858203604087015261069c565b60608581015167ffffffffffffffff169085015260808581015167ffffffffffffffff169085015260a085015184820360a086015261069c565b9201519060c081840391015261069c565b346100e75760006003193601126100e75760408051611288816104d0565b6007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff600954168282015281516112c18161075981610e3a565b60608201526109b18251926112d5846104ec565b61132c67ffffffffffffffff80600b541686526112f06110a3565b60208701526112fd61107a565b86840152600e5467ffffffffffffffff828216166060880152831c16608086019067ffffffffffffffff169052565b611334610563565b60a085015261134161057d565b60c08501525192839283611184565b346100e75760008060031936011261146b5760ff601354161561144157604051908082601454916113808361010f565b928383526020946001918660018216918260001461141e5750506001146113c4575b50506113b092500383610540565b6109b160405192828493845283019061069c565b90859250601482527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec5b8583106114065750506113b0935082010138806113a2565b805483890185015287945086939092019181016113ee565b915093506113b095925060ff1991501682840152151560051b82010138806113a2565b60046040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b80fd5b346100e75760008060031936011261146b57611488611c57565b50604051907f5a509280000000000000000000000000000000000000000000000000000000008252602060048301528082806114c66024820161176d565b0381305afa9081156109ce5780916114e7575b604051806109b18482610add565b90503d8082843e6114f88184610540565b820160208382031261158f57825167ffffffffffffffff9384821161158b57019260a0848303126109d35760405192611530846104b4565b845161153b81611c82565b8452602085015161154b81611c82565b602085015260408501516040850152606085015191821161146b5750926115796080926109b1958301611722565b606084015201516080820152386114d9565b8380fd5b5080fd5b346100e7576003196060813601126100e75760043567ffffffffffffffff918282116100e75760e09082360301126100e757602435918083116100e757366023840112156100e7578260040135928184116100e75736602485830101116100e7576044359182116100e7576109b193611623936116166024943690600401610bf0565b949093019060040161270c565b60405190151581529081906020820190565b346100e75760006003193601126100e757602067ffffffffffffffff60115416604051908152f35b346100e75760006003193601126100e757602060405160108152f35b60405161168581610524565b6000815290565b60405190610140820182811067ffffffffffffffff82111761049b57604052600982528160005b61012081106116c0575050565b8060606020809385010152016116b3565b67ffffffffffffffff811161049b57601f01601f191660200190565b909291926116fa816116d1565b916117086040519384610540565b8294828452828201116100e757602061057b930190610679565b9080601f830112156100e75781516106eb926020016116ed565b91906040838203126100e757825167ffffffffffffffff81116100e757602091611767918501611722565b92015190565b60806106eb916007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff60095416604082015281606082015201610f56565b92936080946117d9936106eb9793865260208601526040850152606084015260c08484015260c0830190611127565b9060a08183039101526007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff60095416604082015281606082015201610f56565b6040513d6000823e3d90fd5b601f8111611831575050565b60009060146000527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec906020601f850160051c8301941061188d575b601f0160051c01915b82811061188257505050565b818155600101611876565b909250829061186d565b90815167ffffffffffffffff811161049b576118bd816118b860145461010f565b611825565b602080601f831160011461191d5750819061190d9394600092611912575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b601455565b0151905038806118db565b90601f1983169461195060146000527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec90565b926000905b8782106119ab575050836001959610611974575b505050811b01601455565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611969565b80600185968294968601518155019501930190611955565b908160209103126100e7575180151581036100e75790565b80600c5480825260208092019160208260051b85010193600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7936000915b848310611a2d5750505050505090565b909192939495846001611a4a83601f19868496030187528a610fe4565b9801930193019194939290611a1d565b8060125490818152602080910191600591808260051b86010194600094601286527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34449580925b858410611ab257505050505050505090565b9091929394959697601f19828203018452856040808352898b8692815490611ad98261010f565b80918801526060916001948582169182600014611b5b575050600114611b1a575b505001549282019290925290986002019796959460010193019190611aa0565b909180945088528488209088915b818310611b3d57505085010191836001611afa565b8496929491939550805486868a0101520192018d93918b9593611b28565b60ff19168985015291151590911b870190910193508490506001611afa565b611c496106eb9260608352611bad60608401611b9f600b5467ffffffffffffffff1690565b67ffffffffffffffff169052565b60e06080840152611c3b611bc461014085016119db565b611c2b611bfb7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa092838882030160a0890152610ec8565b600e5467ffffffffffffffff80821660c08a015260409190911c1660e08801528287820301610100880152610162565b9085820301610120860152610217565b90838203602085015261069c565b906040818303910152611a5a565b60405190611c64826104b4565b60006080838281528260208201528260408201526060808201520152565b73ffffffffffffffffffffffffffffffffffffffff8116036100e757565b356106eb81611c82565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e7570180359067ffffffffffffffff82116100e7576020019181360383136100e757565b929192611d07826116d1565b91611d156040519384610540565b8294818452818301116100e7578281602093846000960137010152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115611d6e5760200190565b611d32565b805160011015611d6e5760400190565b805160021015611d6e5760600190565b805160031015611d6e5760800190565b805160041015611d6e5760a00190565b805160051015611d6e5760c00190565b805160061015611d6e5760e00190565b805160071015611d6e576101000190565b805160081015611d6e576101200190565b8051821015611d6e5760209160051b010190565b92919092611e168461108b565b91611e246040519384610540565b829480845260208094019060051b8301928284116100e75780915b848310611e4e57505050505050565b823567ffffffffffffffff81116100e757820184601f820112156100e7578691611e7e8683858095359101611cfb565b815201920191611e3f565b67ffffffffffffffff8116036100e757565b9080601f830112156100e757815191602091611eb68461108b565b93604091611ec76040519687610540565b818652848087019260051b850101938185116100e757858101925b858410611ef3575050505050505090565b83519067ffffffffffffffff918281116100e757830160609081601f1982880301126100e757875193611f2585610508565b8a820151611f3281611e89565b8552888201519081116100e757868b611f4d92840101611722565b8a85015201519060038210156100e757828993928885940152815201930192611ee2565b91906060838203126100e75760405190611f8a82610508565b81938051611f9781611e89565b835260208101519167ffffffffffffffff928381116100e75781611fbc918401611722565b602085015260408201519283116100e757604092611fda9201611722565b910152565b9060209081838203126100e757825167ffffffffffffffff938482116100e757019282848303126100e75760409182519461201986610524565b8051908382116100e75701916060838303126100e75783519461203b86610508565b83518281116100e75784016080818503126100e75785519061205c826104d0565b805161206781611e89565b82528281015161207681611c82565b83830152868101518481116100e757810185601f820112156100e7578581856120a1935191016116ed565b878301526060810151908482116100e7576120be91869101611722565b60608201528652808401518281116100e757836120dc918601611e9b565b90860152838301519081116100e7576120f59201611f71565b90820152815290565b60209081818403126100e75780519067ffffffffffffffff82116100e757019180601f840112156100e75782516121348161108b565b936121426040519586610540565b818552838086019260051b8201019283116100e7578301905b828210612169575050505090565b8151815290830190830161215b565b8091039060c082126100e75760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0604051936121b4856104d0565b83516121bf81611e89565b855260208401516121cf81611e89565b602086015260408401516121e281611e89565b604086015201126100e75760a0604051916121fc83610508565b606081015161220a81611e89565b83526080810151602084015201516040820152606082015290565b6106eb906040815261223960408201610333565b9060208183039101526103c2565b60155442116124685773ffffffffffffffffffffffffffffffffffffffff6122c0600061227d60115467ffffffffffffffff1690565b6040517f012d56e000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015291829081906024820190565b0381857f0000000000000000000000000000000000000000000000000000000000000000165afa80156109ce57604091600091612445575b5051015167ffffffffffffffff612317825167ffffffffffffffff1690565b161561243e576020612334910151602080825183010191016120fe565b9060c060405180927f3d0f34da000000000000000000000000000000000000000000000000000000008252818061236d60048201612225565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa80156109ce576106eb9261240392600092612409575b50806123cb6123c46123bd6123d094611d61565b5192611d73565b5191612be4565b612c13565b6123fd6123f06040806060860151015194015167ffffffffffffffff1690565b67ffffffffffffffff1690565b91612c67565b90612cd1565b6123d09192506124309060c03d60c011612437575b6124288183610540565b810190612178565b91906123a9565b503d61241e565b5050600090565b61246291503d806000833e61245a8183610540565b810190611fdf565b386122f8565b600090565b356106eb81611e89565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e7570180359067ffffffffffffffff82116100e757602001918160051b360383136100e757565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100e757016020813591019167ffffffffffffffff82116100e75781360383136100e757565b90918092808252602080920191808260051b8601019484600080925b85841061256a57505050505050505090565b9091929394959697601f1982820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18536030181121561158b5786600192868293019082806125d060406125c386806124ec565b90918087528601916124cb565b9301359101529a01980196959401929190612558565b9e9b999f9d9c9a989694918f9694939061261b9167ffffffffffffffff610140941689526020938060208b01528901916124cb565b956040818803910152818652602086019560208360051b82010196846000925b8584106126d357505050505050509461269e8c9d60a061268d61057b9e9f986101209e9c9861267f6126cb9f9d996126af996126bc9e8e60608185039101526124cb565b918b830360808d015261253c565b97019067ffffffffffffffff169052565b67ffffffffffffffff1660c08d0152565b8a830360e08c01526124cb565b918783036101008901526124cb565b930160019052565b9091929394959885806126fb836126f58e601f198860019803018a52886124ec565b906124cb565b9b019401940192959493919061263b565b909293919361271a8261246d565b926127286020840184612477565b9390926127386040830183611caa565b919093606084016127489061246d565b916127556080860161246d565b9361276360a0870187611caa565b97909660c0810161277391611caa565b9a90996040519e8f9e8f7f07d145e90000000000000000000000000000000000000000000000000000000081526004019e6127ad9f6125e6565b03817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a602094600091f19081156109ce57600091612802575090565b6106eb915060203d602011610a2857610a1a8183610540565b6106eb9060405190741400000000000000000000000000000000000000001860148201526034810160405261285c565b908151811015611d6e570160200190565b906000918051926001936001811490816129ca575b501561287c57509150565b81519360388510156128d65750926106eb92937fff000000000000000000000000000000000000000000000000000000000000006128c16128bb612da8565b93612fb6565b60f81b16901a6128d082611d61565b53612b12565b8190806001915b61299a575b50506128f56128f082612f9a565b612dda565b917fff0000000000000000000000000000000000000000000000000000000000000061292861292384612fb6565b612fa8565b8160f89160f81b16831a61293b86611d61565b5360015b848111156129575750505050506106eb929350612b12565b808361298061297a61297461296f612995968b612c5a565b612fdf565b8d612c13565b60ff1690565b841b16851a61298f828961284b565b53612e0b565b61293f565b90916129a68388612c13565b156129c4576129b76129bd91612e0b565b92612bcd565b90806128dd565b916128e2565b905015611d6e576080602083015160f81c1038612871565b6129eb90613079565b908151600060388210600014612a445750916106eb91927fff00000000000000000000000000000000000000000000000000000000000000612a34612a2e612da8565b92612fc4565b60f81b1660001a6128d082611d61565b916001925b612a538484612c13565b15612a7057612a64612a6a91612e0b565b93612bcd565b92612a49565b909250929092612a826128f082612f9a565b907fff00000000000000000000000000000000000000000000000000000000000000612ab061292383612fc4565b8160f89160f81b1660001a612ac485611d61565b5360015b83811115612adf57505050506106eb929350612b12565b8083612afd61297a612af761296f612b0d968a612c5a565b8c612c13565b841b1660001a61298f828861284b565b612ac8565b6040518151808252909290830191602083810192818301828088015b868110612b7b5750505080518094875182018852950194828087019201905b828110612b6c575050505091603f91601f199351011501011660405290565b81518152908301908301612b4d565b8251815291810191849101612b2e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b604d8111612bc857600a0a90565b612b8b565b908160081b918083046101001490151715612bc857565b90662386f26fc1000091828102928184041490151715612bc857565b81810292918115918404141715612bc857565b8115612c1d570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6020039060208211612bc857565b91908203918211612bc857565b909291906010821115612cc957815b820390828211612bc857612c8c612c9292612bba565b90612c00565b927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08201918211612bc857612c8c6106eb92612bba565b601091612c76565b60ff6005541691612ce18361071d565b600183149283612d84575b8315612d61575b8315612d3d575b8315612d12575b505050612d0d57600090565b600190565b600291929350612d218161071d565b149182612d33575b5050388080612d01565b1090503880612d29565b9250612d488361071d565b6003831480612d58575b92612cfa565b50808211612d52565b9250612d6c8361071d565b821580612d7a575b92612cf3565b5080821115612d74565b818310159350612cec565b60405190612d9c8261047f565b60208083523683820137565b60405190612db58261047f565b6001825260203681840137565b604051612dce81610524565b60008152906000368137565b90612de4826116d1565b612df16040519182610540565b828152601f19612e0182946116d1565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612bc85760010190565b612e40612d8f565b90602091600260208201526000926000905b808210612ece575b50612e676128f082612c4c565b9160005b8351811015612ec657600190612eb3612e8d612e8686612e0b565b958561284b565b517fff000000000000000000000000000000000000000000000000000000000000001690565b871a612ebf828761284b565b5301612e6b565b509193505050565b90612f04612edf612e8d838661284b565b7fff000000000000000000000000000000000000000000000000000000000000001690565b612f115760010190612e52565b90612e5a565b90612f20612d8f565b60209260208201526000926000905b808210612f76575b50612f446128f082612c4c565b9160005b8351811015612ec657600190612f63612e8d612e8686612e0b565b871a612f6f828761284b565b5301612f48565b90612f87612edf612e8d838661284b565b612f945760010190612f2f565b90612f37565b9060018201809211612bc857565b9060378201809211612bc857565b9060808201809211612bc857565b9060c08201809211612bc857565b91908201809211612bc857565b601f8111612bc8576101000a90565b15612ff557565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f416e206974656d20696e20746865206c69737420746f20626520524c5020656e60448201527f636f646564206973206e756c6c2e0000000000000000000000000000000000006064820152fd5b80511561311e5790600091825b81518410156130c5576130bd6001916130ab6130a28786611df5565b51511515612fee565b6130b58685611df5565b515190612fd2565b930192613086565b6130d191929350612dda565b906020808301936000945b83518610156131165761310e6001916131046130f88988611df5565b51868151910183613127565b6130b58887611df5565b9501946130dc565b509350505090565b506106eb612dc2565b92905b60209384841061315f5781518152848101809111612bc857938101809111612bc85791601f198101908111612bc8579161312a565b929091935060200360208111612bc85761317890612fdf565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211612bc857518251821691191617905256fea164736f6c6343000819000ac65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8a164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca83" + ], + "transaction": { + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "gas": "0x6d3d16", + "value": "0x0", + "input": "0xcdcb760a6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003ea00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000005d1160a034607357601f615cf138819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607357516001600160a01b038116908190036073576001600055608052604051615c62908161008f823960805181818160e9015261042d0152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c90816306433b1b146100a45781630b0fdb3d14610055575080637fddd602146100505763b60bda491461004b57600080fd5b61020f565b610145565b346100a15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15760ff60406020926004358152600184522054166040519015158152f35b80fd5b346100a157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b600091031261011d57565b600080fd5b6064359073ffffffffffffffffffffffffffffffffffffffff8216820361011d57565b3461011d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011d5760043573ffffffffffffffffffffffffffffffffffffffff80821680920361011d576101d56020926040516101cd816101bf8782019460243590869091604092825260208201520190565b03601f19810183528261033f565b519020610b6e565b60405191168152f35b9181601f8401121561011d5782359167ffffffffffffffff831161011d576020808501948460051b01011161011d57565b3461011d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a08136011261011d576004359067ffffffffffffffff9081831161011d57608081843603011261011d576024359082821161011d57604090823603011261011d5760443591821161011d576102d7926102966102b09336906004016101de565b9061029f610122565b926084359460040190600401610362565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161031e57604052565b6102db565b6040810190811067ffffffffffffffff82111761031e57604052565b90601f601f19910116810190811067ffffffffffffffff82111761031e57604052565b93929490916000916002835414610640576002835560409586519182610398602082019232849091604092825260208201520190565b03926103ac601f199485810183528261033f565b519020946103ce6103c7876000526001602052604060002090565b5460ff1690565b6106175732867f4d26f9b035ac4dafb21ce257260243ad6adf7e105ac6517fe42bebde1d0828ca8780a3614e29916104086020840161066a565b92808452610e2d602085013973ffffffffffffffffffffffffffffffffffffffff998a7f0000000000000000000000000000000000000000000000000000000000000000169889918b51978895602087019561046396610a48565b038281018452610473908461033f565b86519283916020830161048591610b37565b61048e91610b37565b03908101825261049e908261033f565b6104a89083610d3e565b946104b283610b6e565b9080871690811592831561060a575b5050506105d957823b156100a15783517f4420e48600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86166004820152928390602490829084905af19081156105d45761056c92610541926105bb575b506000526001602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b5173ffffffffffffffffffffffffffffffffffffffff8216815233907ffb2d8b84e2e1acdcdbad3ce10c5a03d9f07b3f9f2e4a6d818a1a6a43610ac3b990602090a2906105b96001600055565b565b806105c86105ce9261030a565b80610112565b38610530565b610b62565b83517f8e6ae65f00000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b16141590503880806104c1565b600488517f0ced3043000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b906105b9604051928361033f565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18236030181121561011d570190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561011d57016020813591019167ffffffffffffffff821161011d57813603831361011d57565b601f8260209493601f19938186528686013760008582860101520116010190565b6107569161074861073d61072f84806106aa565b6040855260408501916106fa565b9260208101906106aa565b9160208185039101526106fa565b90565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218236030181121561011d570190565b359067ffffffffffffffff8216820361011d57565b908281815260208091019360208360051b82010194846000925b8584106107cb575050505050505090565b9091929394959685806107f383601f1986600196030188526107ed8c886106aa565b906106fa565b9901940194019295949391906107ba565b67ffffffffffffffff91826108188361078b565b16815260208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181121561011d5782019260208435940190841161011d578360051b3603811361011d576109006108a561088a61090b936107569760e0602088015260e08701916107a0565b61089760408701876106aa565b9086830360408801526106fa565b6108c56108b46060870161078b565b67ffffffffffffffff166060860152565b6108e56108d46080870161078b565b67ffffffffffffffff166080860152565b6108f260a08601866106aa565b9085830360a08701526106fa565b9260c08101906106aa565b9160c08185039101526106fa565b80357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818236030181121561011d57810191604081528235604082015260208301356060820152604083013573ffffffffffffffffffffffffffffffffffffffff811680910361011d576109b061099f610756956109bb93608086015260608101906106aa565b608060a086015260c08501916106fa565b926020810190610759565b906020818403910152610804565b9082818152602080910193818360051b82010194846000925b8584106109f3575050505050505090565b90919293949596858082601f198560019503018752610a128b87610678565b908280610a316040610a2486806106aa565b90918087528601916106fa565b9301359101529901940194019295949391906109e2565b91909496959360a08352610ab0610a74610a628880610678565b608060a087015261012086019061071b565b610a816020890189610678565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608683030160c087015261071b565b93604087013591600483101561011d57610aee608096610b1b9560606105b99b610afc9760e08b015201356101008901528782036020890152610919565b9185830360408701526109c9565b73ffffffffffffffffffffffffffffffffffffffff9097166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b9081519160005b838110610b4f575050016000815290565b8060208092840101518185015201610b3e565b6040513d6000823e3d90fd5b6040519060208201907fff0000000000000000000000000000000000000000000000000000000000000082523060601b602184015260358301527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605583015260558252608082019180831067ffffffffffffffff84111761031e57827f010000000000000000000000000000000000000000000000000000000000000060b6610c9b946107569660405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610c7f81610323565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051906040820182811067ffffffffffffffff82111761031e57604052601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b3d15610d39573d9067ffffffffffffffff821161031e5760405191610d2d6020601f19601f840116018461033f565b82523d6000602084013e565b606090565b9190610d48610cb4565b92610d5281610b6e565b93843b610e02576020815191016000f573ffffffffffffffffffffffffffffffffffffffff811615610dd85781600092918360208194519301915af1610d96610cfe565b50158015610dcf575b610da557565b60046040517f53de54b9000000000000000000000000000000000000000000000000000000008152fd5b50813b15610d9f565b60046040517fbbd2fe87000000000000000000000000000000000000000000000000000000008152fd5b60046040517fcd43efa1000000000000000000000000000000000000000000000000000000008152fdfe6101006040523461145957614e29803803809161001e826101006118c6565b6101003960a0811261145957610100516001600160401b03811161145957610100019060808282610100010312611459576040519161005c83611875565b80516001600160401b0381116114595761007d908361010001908301611960565b835260208101516001600160401b038111611459576100a3908361010001908301611960565b6020840152604081015190600482101561145957604084019190915260609081015190830152610120516001600160401b03811161145957610100016040818361010001031261145957604051906100fa82611890565b80516001600160401b03811161145957810160808185610100010312611459576040519061012782611875565b8051825260208101516020830152610141604082016119bc565b60408301526060810151906001600160401b0382116114595761016a918661010001910161190c565b6060820152825260208101516001600160401b0381116114595760e08183018561010001031261145957604051916101a1836118ab565b6101ac8282016119d0565b8352808201602001516001600160401b038111611459578561010001601f8285850101011215611459578083830101516101e5816119e4565b916101f360405193846118c6565b81835260208301886101000160208460051b8489890101010111611459576020828787010101905b60208460051b84898901010101821061183957505050506020840152808201604001516001600160401b0381116114595761025f908661010001908484010161190c565b60408401526102726060838301016119d0565b60608401526102856080838301016119d0565b608084015280820160a001516001600160401b038111611459576102b2908661010001908484010161190c565b60a084015280820160c001516001600160401b038111611459576102dd92866101000192010161190c565b60c08201526020820152610140516001600160401b03811161145957610100830161011f8201121561145957806101000151610318816119e4565b9361032660405195866118c6565b81855260208501926101008201610120600585901b83010111611459576101208101935b610120600585901b83010185106117c0578787876103696101606119bc565b926103756101806119bc565b602083015183516001600160a01b038716156117ae576001600160a01b0383161561179c5760a0820151511561178a5760c0820151511561177857604001516001600160a01b03161561176657610900608052604051906103d582611890565b600182526020368184013760016103eb836119fb565b5260805190516040805163338c1f5160e01b81526001600160401b039092166004830152602482015282516044820181905290926001600160a01b0390921691839160648301916020019060005b81811061174a5750505091818060009403915afa908115611466576000916114e0575b5061046d60206104779201516119fb565b5151805190611aca565b90156114ce57600080546001600160a01b0319166001600160a01b039290921691909117905561090260a05261090360c0526040516001600160401b0360608201908111908211176107d257606081016040526002815260005b604081106114bd57506020830151516104e9826119fb565b526104f3816119fb565b50602080840151015161050582611a08565b5261050f81611a08565b5060405161051c81611890565b6001815260646020820152606084810151604051939184018085116001600160401b03909111176107d2576060840160405283526020830152604082015260018060a01b0360c05116906040519060208083015260c08201908051604084015260208101519160806060850152825180915260e0840190602060e08260051b8701019401916000905b8282106114925750505050604001516000608084015b6002821061147257505050819003601f1981018252600092602092610628926105e490826118c6565b604051948580948193630b1e6daf60e31b83526040600484015260096044840152681c1c9a58d95c1c995960ba1b6064840152608060248401526084830190611a18565b03925af190811561146657600091611427575b50601180546001600160401b0319166001600160401b03929092169190911790556001600160a01b031660e05260005b83518110156107fe5760208160051b8501015160125490680100000000000000008210156107d25760018201806012558210156107e8576012600052805180517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492916001600160401b0382116107d2576106fa826106ef8760011b870154611a3d565b8760011b8701611a8e565b602090601f83116001146107555792610735836001989796946020948a9760009261074a575b50508160011b916000199060031b1c19161790565b85851b8401555b015192821b0101550161066b565b015190508e80610720565b908560011b850160005260206000209160005b601f19851681106107ba575083602093600199989795938a9794938894601f198116106107a1575b505050811b0185851b84015561073c565b015160001960f88460031b161c191690558d8080610790565b91926020600181928685015181550194019201610768565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b508051805180518692916001600160401b0382116107d257610821600154611a3d565b601f81116113d8575b50602090601f831160011461136957918061085f92602095946000926111e65750508160011b916000199060031b1c19161790565b6001555b015180519093906001600160401b0381116107d257610883600254611a3d565b601f811161131a575b506020601f82116001146112af5781906108bf93949596600092610d5c5750508160011b916000199060031b1c19161790565b6002555b602083015180518051906001600160401b0382116107d2576108e6600354611a3d565b601f8111611260575b50602090601f83116001146111f157918061092492602095946000926111e65750508160011b916000199060031b1c19161790565b6003555b015180519093906001600160401b0381116107d257610948600454611a3d565b601f8111611197575b506020601f821160011461112c57819061098493949596600092610d5c5750508160011b916000199060031b1c19161790565b6004555b60408101519060048210156111165760609160ff8019600554169116176005550151600655606081518051600755602081015160085560018060a01b0360408201511660018060a01b03196009541617600955015180519060018060401b0382116107d2576109f8600a54611a3d565b601f81116110d9575b50602090601f8311600114611061579180610a369260209594600092610d5c5750508160011b916000199060031b1c19161790565b600a555b01519060018060401b0382511660018060401b0319600b541617600b5560208201518051906801000000000000000082116107d257600c5482600c55808310610fd0575b50600c60009081527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c792916020015b828210610ee95760408601518051869088906001600160401b0381116107d257610ad8600d54611a3d565b601f8111610e9a575b506020601f8211600114610e30578190610b13939495600092610e255750508160011b916000199060031b1c19161790565b600d555b6060810151600e805460808401516001600160801b03199091166001600160401b039384161760409190911b6fffffffffffffffff00000000000000001617905560a082015180519182116107d257610b71600f54611a3d565b601f8111610dd6575b50602090601f8311600114610d67579180610baf9260c09594600092610d5c5750508160011b916000199060031b1c19161790565b600f555b015180519091906001600160401b0381116107d257610bd3601054611a3d565b601f8111610d02575b50602092601f8211600114610c9c57610c0e92938291600092610c915750508160011b916000199060031b1c19161790565b6010555b60138054610100600160a81b03191660089290921b610100600160a81b031691909117905542620151808101908110610c7b576015556040516131bd9081611c4c8239608051816127b1015260a05181612371015260c051816122c5015260e0518161091e0152f35b634e487b7160e01b600052601160045260246000fd5b015190508480610720565b601f19821693601060005260206000209160005b868110610cea5750836001959610610cd1575b505050811b01601055610c12565b015160001960f88460031b161c19169055838080610cc3565b91926020600181928685015181550194019201610cb0565b6010600052610d4c907f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672601f840160051c81019160208510610d52575b601f0160051c0190611a77565b83610bdc565b9091508190610d3f565b015190508680610720565b90600f60005260206000209160005b601f1985168110610dbe575091839160019360c09695601f19811610610da5575b505050811b01600f55610bb3565b015160001960f88460031b161c19169055858080610d97565b91926020600181928685015181550194019201610d76565b600f600052610e1f907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802601f850160051c81019160208610610d5257601f0160051c0190611a77565b84610b7a565b015190508580610720565b600d60005260206000209060005b601f1984168110610e825750600193949583601f19811610610e69575b505050811b01600d55610b17565b015160001960f88460031b161c19169055848080610e5b565b9091602060018192858a015181550193019101610e3e565b600d600052610ee3907fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5601f840160051c81019160208510610d5257601f0160051c0190611a77565b84610ae1565b80518051906001600160401b0382116107d257610f1082610f0a8854611a3d565b88611a8e565b602090601f8311600114610f625792610f4883600195946020948796600092610f575750508160011b916000199060031b1c19161790565b87555b01940191019092610aad565b015190508c80610720565b90601f198316918760005260206000209260005b818110610fb85750936020936001969387969383889510610f9f575b505050811b018755610f4b565b015160001960f88460031b161c191690558b8080610f92565b92936020600181928786015181550195019301610f76565b600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c79081019083015b81811061100a5750610a7e565b8061101760019254611a3d565b80611024575b5001610ffd565b601f8111831461103a5750600081555b8761101d565b600090828252611058601f60208420920160051c8201858301611a77565b81835555611034565b600a6000908152600080516020614e09833981519152929190601f198516905b8181106110c157509160019391856020979694106110a8575b505050811b01600a55610a3a565b015160001960f88460031b161c1916905585808061109a565b92936020600181928786015181550195019301611081565b600a60005261111090600080516020614e09833981519152601f850160051c81019160208610610d5257601f0160051c0190611a77565b84610a01565b634e487b7160e01b600052602160045260246000fd5b600460005260206000209060005b601f198416811061117f575060019394959683601f19811610611166575b505050811b01600455610988565b015160001960f88460031b161c19169055858080611158565b9091602060018192858b01518155019301910161113a565b60046000526111e0907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81019160208510610d5257601f0160051c0190611a77565b85610951565b015190508880610720565b90600360005260206000209160005b601f1985168110611248575091839160019360209695601f1981161061122f575b505050811b01600355610928565b015160001960f88460031b161c19169055878080611221565b91926020600181928685015181550194019201611200565b60036000526112a9907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f850160051c81019160208610610d5257601f0160051c0190611a77565b866108ef565b600260005260206000209060005b601f1984168110611302575060019394959683601f198116106112e9575b505050811b016002556108c3565b015160001960f88460031b161c191690558580806112db565b9091602060018192858b0151815501930191016112bd565b6002600052611363907f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f840160051c81019160208510610d5257601f0160051c0190611a77565b8561088c565b90600160005260206000209160005b601f19851681106113c0575091839160019360209695601f198116106113a7575b505050811b01600155610863565b015160001960f88460031b161c19169055878080611399565b91926020600181928685015181550194019201611378565b6001600052611421907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f850160051c81019160208610610d5257601f0160051c0190611a77565b8661082a565b90506020813d60201161145e575b81611442602093836118c6565b8101031261145957611453906119d0565b8661063b565b600080fd5b3d9150611435565b6040513d6000823e3d90fd5b82516001600160401b0316815260209283019260019290920191016105bb565b909192946020806114af60019360df198b82030186528951611a18565b9701920192019092916105a5565b8060606020809385010152016104d1565b6040516307456b9160e21b8152600490fd5b903d8082843e6114f081846118c6565b6020838281010312611746578251926001600160401b0384116117425760408482018383010312611742576040519361152885611890565b818101516001600160401b03811161173e5760e08183850101858501031261173e5760405190611557826118ab565b61156481848601016119d0565b825261157660208285870101016119d0565b602083015261158b60408285870101016119d0565b6040830152606081848601010151600381101561172b5760608301528383018101608001516001600160401b03811161172b576115fb916115d760c0928888019083888a01010161190c565b60808501526115ec60a08287890101016119d0565b60a085015284860101016119d0565b60c0820152855281810160200151936001600160401b03851161173b57838301601f868486010101121561173b5784828401015192611639846119e4565b9561164760405197886118c6565b848752602087019386830160208760051b8484870101010111611737576020828285010101945b60208760051b84848701010101861061169b57505050505060208501939093525061046d915061045c9050565b85516001600160401b038111611733576040858401850182018a870103601f19011261173357604051906116ce82611890565b85840185018101602001516001600160401b03811161172f579061170260409260208d8a0191848a8a8d010101010161190c565b83528585880101010151600381101561172b57602082810191909152908252958601950161166e565b8680fd5b8780fd5b8580fd5b8380fd5b80fd5b8480fd5b8280fd5b5080fd5b825160030b845286945060209384019390920191600101610439565b604051630695a62360e51b8152600490fd5b604051636fc5f47160e01b8152600490fd5b60405163460be67160e11b8152600490fd5b6040516311a1e69760e01b8152600490fd5b60405163bcda548360e01b8152600490fd5b84516001600160401b038111611459578201610100810191906040908503601f19011261145957604051916117f483611890565b6020810151916001600160401b0383116114595760209360408594936118248695868b610100019184010161190c565b8352015183820152815201950194905061034a565b8151906001600160401b03821161145957602080929161186889838f95898e839861010001940101010161190c565b815201920191905061021b565b608081019081106001600160401b038211176107d257604052565b604081019081106001600160401b038211176107d257604052565b60e081019081106001600160401b038211176107d257604052565b601f909101601f19168101906001600160401b038211908210176107d257604052565b60005b8381106118fc5750506000910152565b81810151838201526020016118ec565b81601f820112156114595780516001600160401b0381116107d2576040519261193f601f8301601f1916602001856118c6565b818452602082840101116114595761195d91602080850191016118e9565b90565b9190604083820312611459576040519061197982611890565b8351919384926001600160401b039290838111611459578161199c91840161190c565b84526020820151928311611459576020926119b7920161190c565b910152565b51906001600160a01b038216820361145957565b51906001600160401b038216820361145957565b6001600160401b0381116107d25760051b60200190565b8051156107e85760200190565b8051600110156107e85760400190565b90602091611a31815180928185528580860191016118e9565b601f01601f1916010190565b90600182811c92168015611a6d575b6020831014611a5757565b634e487b7160e01b600052602260045260246000fd5b91607f1691611a4c565b818110611a82575050565b60008155600101611a77565b9190601f8111611a9d57505050565b611ac8926000526020600020906020601f840160051c83019310610d5257601f0160051c0190611a77565b565b9061060f60f31b61ffff60f01b602084015116148060011b9080820460021490151715610c7b5760280180602811610c7b578103611b1b57611b0b91611b25565b90916001600160a01b0390911690565b5050600090600090565b919060209061060f60f31b61ffff60f01b60208601511614936001928560011b9580870460021490151715610c7b57929190600095935b828510611b6e57505050505060019190565b909192939560ff611b888160f81b848a8701015116611bd9565b1690600f8211611bc957600481811b9180830460101490151715611bb457500195840193929190611b5c565b601190634e487b7160e01b6000525260246000fd5b5050505050509050600090600090565b60f81c602f811180611c41575b15611bf557602f190160ff1690565b6060811180611c37575b15611c0e576056190160ff1690565b6040811180611c2d575b15611c27576036190160ff1690565b5060ff90565b5060478110611c18565b5060678110611bff565b50603a8110611be656fe6080604052600436101561001257600080fd5b60003560e01c80631c9feaa5146100d7578063229e81fb146100d257806342859ab3146100cd5780635a509280146100c857806362b61c8b146100c357806378b90337146100be578063819ef8ba146100b957806388328a69146100b4578063b3d7ad48146100af578063cad31c74146100aa578063cbe61e59146100a55763d47e4eeb146100a057600080fd5b61165d565b611635565b611593565b61146e565b611350565b61126a565b610e15565b610c3d565b610b38565b6107ca565b61072c565b6100ec565b60009103126100e757565b600080fd5b346100e75760006003193601126100e757602060ff601354166040519015158152f35b90600182811c92168015610158575b602083101461012957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161011e565b600f54600092916101728261010f565b808252916020906001908181169081156101f15750600114610195575b50505050565b92939450600f6000527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000935b8585106101de57505050602092500101903880808061018f565b80548585018401529382019381016101c4565b915050602094955060ff1991509291921683830152151560051b0101903880808061018f565b601054600092916102278261010f565b808252916020906001908181169081156101f157506001146102495750505050565b9293945060106000527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672926000935b85851061029257505050602092500101903880808061018f565b8054858501840152938201938101610278565b600454600092916102b58261010f565b808252916020906001908181169081156101f157506001146102d75750505050565b9293945060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000935b85851061032057505050602092500101903880808061018f565b8054858501840152938201938101610306565b906000916001906001546103468161010f565b80835292602091600181169081156101f157506001146103665750505050565b9293945060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6926000935b8585106103af57505050602092500101903880808061018f565b8054858501840152938201938101610395565b600254600092916103d28261010f565b808252916020906001908181169081156101f157506001146103f45750505050565b9293945060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace926000935b85851061043d57505050602092500101903880808061018f565b8054858501840152938201938101610423565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761049b57604052565b610450565b67ffffffffffffffff811161049b57604052565b60a0810190811067ffffffffffffffff82111761049b57604052565b6080810190811067ffffffffffffffff82111761049b57604052565b60e0810190811067ffffffffffffffff82111761049b57604052565b6060810190811067ffffffffffffffff82111761049b57604052565b6020810190811067ffffffffffffffff82111761049b57604052565b90601f601f19910116810190811067ffffffffffffffff82111761049b57604052565b6040519061057b8261057481610162565b0383610540565b565b6040519061057b8261057481610217565b6040519061059b8261047f565b60405160035483916000816105af8461010f565b91828252602094600190866001821691826000146106595750506001146105fc575b506105de92500382610540565b8252604051916105f8836105f1816102a5565b0384610540565b0152565b85915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b8583106106415750506105de9350820101386105d1565b8054838801850152869450879390920191810161062a565b60ff1916858201526105de95151560051b85010192503891506105d19050565b60005b83811061068c5750506000910152565b818101518382015260200161067c565b90601f19601f6020936106ba81518092818752878088019101610679565b0116010190565b6106eb9160206106da835160408452604084019061069c565b92015190602081840391015261069c565b90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004111561072757565b6106ee565b346100e75760006003193601126100e7576040516107498161047f565b6040516107608161075981610333565b0382610540565b815260405161077281610759816103c2565b602082015261077f61058e565b60ff60055416906107b0600654916107a2604051956080875260808701906106c1565b9085820360208701526106c1565b906004831015610727578392604084015260608301520390f35b346100e75760a06003193601126100e75760046013549073ffffffffffffffffffffffffffffffffffffffff91828160081c163303610aa65760ff16610a7e57610819610815612247565b1590565b610a565761086b90610829611679565b92604051937f62b61c8b0000000000000000000000000000000000000000000000000000000085528480600095869360843560643560243589358a87016117aa565b0381305afa9384156109ce5783908495610a2f575b5061088a90611897565b6108e660206040516108b4816108a68985830160209181520190565b03601f198101835282610540565b604051809381927fcad31c74000000000000000000000000000000000000000000000000000000008352878301611b7a565b038187305af180156109ce57610911918591610a00575b5060ff60ff19601354169115151617601355565b60135460ff166109d7575b7f00000000000000000000000000000000000000000000000000000000000000001690813b156109d357604080517faa733a4400000000000000000000000000000000000000000000000000000000815232928101928352602083018690529392849290918391859183910103925af180156109ce576109b5575b5060135460ff166040805191151582526020820192909252f35b0390f35b806109c26109c8926104a0565b806100dc565b38610997565b611819565b8280fd5b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e8380a161091c565b610a22915060203d602011610a28575b610a1a8183610540565b8101906119c3565b386108fd565b503d610a10565b61088a9550610a5091503d8086833e610a488183610540565b81019061173c565b94610880565b6040517f741926a1000000000000000000000000000000000000000000000000000000008152fd5b6040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b506040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b908160809103126100e75790565b6020815273ffffffffffffffffffffffffffffffffffffffff80835116602083015260208301511660408201526040820151606082015260a06080610b2f6060850151838386015260c085019061069c565b93015191015290565b346100e75760206003193601126100e75760043567ffffffffffffffff81116100e757610b6c6109b1913690600401610acf565b610b74611c57565b5073ffffffffffffffffffffffffffffffffffffffff90610bd9826000541692604083013590610ba382611c82565b610bb06060850185611caa565b91909260405196610bc0886104b4565b8752166020860152602084013560408601523691611cfb565b606083015235608082015260405191829182610add565b9181601f840112156100e75782359167ffffffffffffffff83116100e7576020808501948460051b0101116100e757565b929190610c3860209160408652604086019061069c565b930152565b346100e75760c06003193601126100e75767ffffffffffffffff6084358181116100e757610c6f903690600401610bf0565b60a4929192359182116100e757610dd5610dd0610dfe94610c97610dee953690600401610acf565b93610db5610cba610dae610ca961168c565b97610cbf610cba6020830135612f17565b61285c565b610cc88a611d61565b52610cd289611d61565b50610ce1610cba600435612f17565b610cea8a611d73565b52610cf489611d73565b50610d03610cba604435612f17565b610d0c8a611d83565b52610d1689611d83565b50610d25610cba606435612f17565b610d2e8a611d93565b52610d3889611d93565b50610d47610cba602435612f17565b610d508a611da3565b52610d5a89611da3565b50610d6f610d6a60408301611ca0565b61281b565b610d788a611db3565b52610d8289611db3565b50610d90610cba8235612f17565b610d998a611dc3565b52610da389611dc3565b506060810190611caa565b3691611cfb565b610dbe86611dd3565b52610dc885611dd3565b503691611e09565b6129e2565b610dde82611de4565b52610de881611de4565b506129e2565b610df9610cba612e38565b612b12565b80516020820120906109b160405192839283610c21565b346100e75760006003193601126100e7576020610e30612247565b6040519015158152f35b600a5460009291610e4a8261010f565b808252916020906001908181169081156101f15750600114610e6c5750505050565b92939450600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8926000935b858510610eb557505050602092500101903880808061018f565b8054858501840152938201938101610e9b565b600d5460009291610ed88261010f565b808252916020906001908181169081156101f15750600114610efa5750505050565b92939450600d6000527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5926000935b858510610f4357505050602092500101903880808061018f565b8054858501840152938201938101610f29565b600a5460009291610f668261010f565b808252916020906001908181169081156101f15750600114610f885750505050565b92939450600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8926000935b858510610fd157505050602092500101903880808061018f565b8054858501840152938201938101610fb7565b805460009392610ff38261010f565b9182825260209360019160018116908160001461105b575060011461101a575b5050505050565b90939495506000929192528360002092846000945b83861061104757505050500101903880808080611013565b80548587018301529401938590820161102f565b60ff19168685015250505090151560051b010191503880808080611013565b6040519061057b8261057481610ec8565b67ffffffffffffffff811161049b5760051b60200190565b600c54906110b08261108b565b9160406110c06040519485610540565b81845283602080910191600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7906000935b85851061110457505050505050565b6001848192845161111981610759818a610fe4565b8152019301940193916110f5565b90808251908181526020809101926020808460051b8301019501936000915b8483106111565750505050505090565b909192939495848061117483601f1986600196030187528a5161069c565b9801930193019194939290611146565b6111d560606106eb9493604084528051604085015260208101518285015273ffffffffffffffffffffffffffffffffffffffff60408201511660808501520151608060a084015260c083019061069c565b90602081830391015267ffffffffffffffff825116815260c061125961121f61120d602086015160e0602087015260e0860190611127565b6040860151858203604087015261069c565b60608581015167ffffffffffffffff169085015260808581015167ffffffffffffffff169085015260a085015184820360a086015261069c565b9201519060c081840391015261069c565b346100e75760006003193601126100e75760408051611288816104d0565b6007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff600954168282015281516112c18161075981610e3a565b60608201526109b18251926112d5846104ec565b61132c67ffffffffffffffff80600b541686526112f06110a3565b60208701526112fd61107a565b86840152600e5467ffffffffffffffff828216166060880152831c16608086019067ffffffffffffffff169052565b611334610563565b60a085015261134161057d565b60c08501525192839283611184565b346100e75760008060031936011261146b5760ff601354161561144157604051908082601454916113808361010f565b928383526020946001918660018216918260001461141e5750506001146113c4575b50506113b092500383610540565b6109b160405192828493845283019061069c565b90859250601482527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec5b8583106114065750506113b0935082010138806113a2565b805483890185015287945086939092019181016113ee565b915093506113b095925060ff1991501682840152151560051b82010138806113a2565b60046040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b80fd5b346100e75760008060031936011261146b57611488611c57565b50604051907f5a509280000000000000000000000000000000000000000000000000000000008252602060048301528082806114c66024820161176d565b0381305afa9081156109ce5780916114e7575b604051806109b18482610add565b90503d8082843e6114f88184610540565b820160208382031261158f57825167ffffffffffffffff9384821161158b57019260a0848303126109d35760405192611530846104b4565b845161153b81611c82565b8452602085015161154b81611c82565b602085015260408501516040850152606085015191821161146b5750926115796080926109b1958301611722565b606084015201516080820152386114d9565b8380fd5b5080fd5b346100e7576003196060813601126100e75760043567ffffffffffffffff918282116100e75760e09082360301126100e757602435918083116100e757366023840112156100e7578260040135928184116100e75736602485830101116100e7576044359182116100e7576109b193611623936116166024943690600401610bf0565b949093019060040161270c565b60405190151581529081906020820190565b346100e75760006003193601126100e757602067ffffffffffffffff60115416604051908152f35b346100e75760006003193601126100e757602060405160108152f35b60405161168581610524565b6000815290565b60405190610140820182811067ffffffffffffffff82111761049b57604052600982528160005b61012081106116c0575050565b8060606020809385010152016116b3565b67ffffffffffffffff811161049b57601f01601f191660200190565b909291926116fa816116d1565b916117086040519384610540565b8294828452828201116100e757602061057b930190610679565b9080601f830112156100e75781516106eb926020016116ed565b91906040838203126100e757825167ffffffffffffffff81116100e757602091611767918501611722565b92015190565b60806106eb916007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff60095416604082015281606082015201610f56565b92936080946117d9936106eb9793865260208601526040850152606084015260c08484015260c0830190611127565b9060a08183039101526007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff60095416604082015281606082015201610f56565b6040513d6000823e3d90fd5b601f8111611831575050565b60009060146000527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec906020601f850160051c8301941061188d575b601f0160051c01915b82811061188257505050565b818155600101611876565b909250829061186d565b90815167ffffffffffffffff811161049b576118bd816118b860145461010f565b611825565b602080601f831160011461191d5750819061190d9394600092611912575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b601455565b0151905038806118db565b90601f1983169461195060146000527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec90565b926000905b8782106119ab575050836001959610611974575b505050811b01601455565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611969565b80600185968294968601518155019501930190611955565b908160209103126100e7575180151581036100e75790565b80600c5480825260208092019160208260051b85010193600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7936000915b848310611a2d5750505050505090565b909192939495846001611a4a83601f19868496030187528a610fe4565b9801930193019194939290611a1d565b8060125490818152602080910191600591808260051b86010194600094601286527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34449580925b858410611ab257505050505050505090565b9091929394959697601f19828203018452856040808352898b8692815490611ad98261010f565b80918801526060916001948582169182600014611b5b575050600114611b1a575b505001549282019290925290986002019796959460010193019190611aa0565b909180945088528488209088915b818310611b3d57505085010191836001611afa565b8496929491939550805486868a0101520192018d93918b9593611b28565b60ff19168985015291151590911b870190910193508490506001611afa565b611c496106eb9260608352611bad60608401611b9f600b5467ffffffffffffffff1690565b67ffffffffffffffff169052565b60e06080840152611c3b611bc461014085016119db565b611c2b611bfb7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa092838882030160a0890152610ec8565b600e5467ffffffffffffffff80821660c08a015260409190911c1660e08801528287820301610100880152610162565b9085820301610120860152610217565b90838203602085015261069c565b906040818303910152611a5a565b60405190611c64826104b4565b60006080838281528260208201528260408201526060808201520152565b73ffffffffffffffffffffffffffffffffffffffff8116036100e757565b356106eb81611c82565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e7570180359067ffffffffffffffff82116100e7576020019181360383136100e757565b929192611d07826116d1565b91611d156040519384610540565b8294818452818301116100e7578281602093846000960137010152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115611d6e5760200190565b611d32565b805160011015611d6e5760400190565b805160021015611d6e5760600190565b805160031015611d6e5760800190565b805160041015611d6e5760a00190565b805160051015611d6e5760c00190565b805160061015611d6e5760e00190565b805160071015611d6e576101000190565b805160081015611d6e576101200190565b8051821015611d6e5760209160051b010190565b92919092611e168461108b565b91611e246040519384610540565b829480845260208094019060051b8301928284116100e75780915b848310611e4e57505050505050565b823567ffffffffffffffff81116100e757820184601f820112156100e7578691611e7e8683858095359101611cfb565b815201920191611e3f565b67ffffffffffffffff8116036100e757565b9080601f830112156100e757815191602091611eb68461108b565b93604091611ec76040519687610540565b818652848087019260051b850101938185116100e757858101925b858410611ef3575050505050505090565b83519067ffffffffffffffff918281116100e757830160609081601f1982880301126100e757875193611f2585610508565b8a820151611f3281611e89565b8552888201519081116100e757868b611f4d92840101611722565b8a85015201519060038210156100e757828993928885940152815201930192611ee2565b91906060838203126100e75760405190611f8a82610508565b81938051611f9781611e89565b835260208101519167ffffffffffffffff928381116100e75781611fbc918401611722565b602085015260408201519283116100e757604092611fda9201611722565b910152565b9060209081838203126100e757825167ffffffffffffffff938482116100e757019282848303126100e75760409182519461201986610524565b8051908382116100e75701916060838303126100e75783519461203b86610508565b83518281116100e75784016080818503126100e75785519061205c826104d0565b805161206781611e89565b82528281015161207681611c82565b83830152868101518481116100e757810185601f820112156100e7578581856120a1935191016116ed565b878301526060810151908482116100e7576120be91869101611722565b60608201528652808401518281116100e757836120dc918601611e9b565b90860152838301519081116100e7576120f59201611f71565b90820152815290565b60209081818403126100e75780519067ffffffffffffffff82116100e757019180601f840112156100e75782516121348161108b565b936121426040519586610540565b818552838086019260051b8201019283116100e7578301905b828210612169575050505090565b8151815290830190830161215b565b8091039060c082126100e75760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0604051936121b4856104d0565b83516121bf81611e89565b855260208401516121cf81611e89565b602086015260408401516121e281611e89565b604086015201126100e75760a0604051916121fc83610508565b606081015161220a81611e89565b83526080810151602084015201516040820152606082015290565b6106eb906040815261223960408201610333565b9060208183039101526103c2565b60155442116124685773ffffffffffffffffffffffffffffffffffffffff6122c0600061227d60115467ffffffffffffffff1690565b6040517f012d56e000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015291829081906024820190565b0381857f0000000000000000000000000000000000000000000000000000000000000000165afa80156109ce57604091600091612445575b5051015167ffffffffffffffff612317825167ffffffffffffffff1690565b161561243e576020612334910151602080825183010191016120fe565b9060c060405180927f3d0f34da000000000000000000000000000000000000000000000000000000008252818061236d60048201612225565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa80156109ce576106eb9261240392600092612409575b50806123cb6123c46123bd6123d094611d61565b5192611d73565b5191612be4565b612c13565b6123fd6123f06040806060860151015194015167ffffffffffffffff1690565b67ffffffffffffffff1690565b91612c67565b90612cd1565b6123d09192506124309060c03d60c011612437575b6124288183610540565b810190612178565b91906123a9565b503d61241e565b5050600090565b61246291503d806000833e61245a8183610540565b810190611fdf565b386122f8565b600090565b356106eb81611e89565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e7570180359067ffffffffffffffff82116100e757602001918160051b360383136100e757565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100e757016020813591019167ffffffffffffffff82116100e75781360383136100e757565b90918092808252602080920191808260051b8601019484600080925b85841061256a57505050505050505090565b9091929394959697601f1982820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18536030181121561158b5786600192868293019082806125d060406125c386806124ec565b90918087528601916124cb565b9301359101529a01980196959401929190612558565b9e9b999f9d9c9a989694918f9694939061261b9167ffffffffffffffff610140941689526020938060208b01528901916124cb565b956040818803910152818652602086019560208360051b82010196846000925b8584106126d357505050505050509461269e8c9d60a061268d61057b9e9f986101209e9c9861267f6126cb9f9d996126af996126bc9e8e60608185039101526124cb565b918b830360808d015261253c565b97019067ffffffffffffffff169052565b67ffffffffffffffff1660c08d0152565b8a830360e08c01526124cb565b918783036101008901526124cb565b930160019052565b9091929394959885806126fb836126f58e601f198860019803018a52886124ec565b906124cb565b9b019401940192959493919061263b565b909293919361271a8261246d565b926127286020840184612477565b9390926127386040830183611caa565b919093606084016127489061246d565b916127556080860161246d565b9361276360a0870187611caa565b97909660c0810161277391611caa565b9a90996040519e8f9e8f7f07d145e90000000000000000000000000000000000000000000000000000000081526004019e6127ad9f6125e6565b03817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a602094600091f19081156109ce57600091612802575090565b6106eb915060203d602011610a2857610a1a8183610540565b6106eb9060405190741400000000000000000000000000000000000000001860148201526034810160405261285c565b908151811015611d6e570160200190565b906000918051926001936001811490816129ca575b501561287c57509150565b81519360388510156128d65750926106eb92937fff000000000000000000000000000000000000000000000000000000000000006128c16128bb612da8565b93612fb6565b60f81b16901a6128d082611d61565b53612b12565b8190806001915b61299a575b50506128f56128f082612f9a565b612dda565b917fff0000000000000000000000000000000000000000000000000000000000000061292861292384612fb6565b612fa8565b8160f89160f81b16831a61293b86611d61565b5360015b848111156129575750505050506106eb929350612b12565b808361298061297a61297461296f612995968b612c5a565b612fdf565b8d612c13565b60ff1690565b841b16851a61298f828961284b565b53612e0b565b61293f565b90916129a68388612c13565b156129c4576129b76129bd91612e0b565b92612bcd565b90806128dd565b916128e2565b905015611d6e576080602083015160f81c1038612871565b6129eb90613079565b908151600060388210600014612a445750916106eb91927fff00000000000000000000000000000000000000000000000000000000000000612a34612a2e612da8565b92612fc4565b60f81b1660001a6128d082611d61565b916001925b612a538484612c13565b15612a7057612a64612a6a91612e0b565b93612bcd565b92612a49565b909250929092612a826128f082612f9a565b907fff00000000000000000000000000000000000000000000000000000000000000612ab061292383612fc4565b8160f89160f81b1660001a612ac485611d61565b5360015b83811115612adf57505050506106eb929350612b12565b8083612afd61297a612af761296f612b0d968a612c5a565b8c612c13565b841b1660001a61298f828861284b565b612ac8565b6040518151808252909290830191602083810192818301828088015b868110612b7b5750505080518094875182018852950194828087019201905b828110612b6c575050505091603f91601f199351011501011660405290565b81518152908301908301612b4d565b8251815291810191849101612b2e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b604d8111612bc857600a0a90565b612b8b565b908160081b918083046101001490151715612bc857565b90662386f26fc1000091828102928184041490151715612bc857565b81810292918115918404141715612bc857565b8115612c1d570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6020039060208211612bc857565b91908203918211612bc857565b909291906010821115612cc957815b820390828211612bc857612c8c612c9292612bba565b90612c00565b927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08201918211612bc857612c8c6106eb92612bba565b601091612c76565b60ff6005541691612ce18361071d565b600183149283612d84575b8315612d61575b8315612d3d575b8315612d12575b505050612d0d57600090565b600190565b600291929350612d218161071d565b149182612d33575b5050388080612d01565b1090503880612d29565b9250612d488361071d565b6003831480612d58575b92612cfa565b50808211612d52565b9250612d6c8361071d565b821580612d7a575b92612cf3565b5080821115612d74565b818310159350612cec565b60405190612d9c8261047f565b60208083523683820137565b60405190612db58261047f565b6001825260203681840137565b604051612dce81610524565b60008152906000368137565b90612de4826116d1565b612df16040519182610540565b828152601f19612e0182946116d1565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612bc85760010190565b612e40612d8f565b90602091600260208201526000926000905b808210612ece575b50612e676128f082612c4c565b9160005b8351811015612ec657600190612eb3612e8d612e8686612e0b565b958561284b565b517fff000000000000000000000000000000000000000000000000000000000000001690565b871a612ebf828761284b565b5301612e6b565b509193505050565b90612f04612edf612e8d838661284b565b7fff000000000000000000000000000000000000000000000000000000000000001690565b612f115760010190612e52565b90612e5a565b90612f20612d8f565b60209260208201526000926000905b808210612f76575b50612f446128f082612c4c565b9160005b8351811015612ec657600190612f63612e8d612e8686612e0b565b871a612f6f828761284b565b5301612f48565b90612f87612edf612e8d838661284b565b612f945760010190612f2f565b90612f37565b9060018201809211612bc857565b9060378201809211612bc857565b9060808201809211612bc857565b9060c08201809211612bc857565b91908201809211612bc857565b601f8111612bc8576101000a90565b15612ff557565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f416e206974656d20696e20746865206c69737420746f20626520524c5020656e60448201527f636f646564206973206e756c6c2e0000000000000000000000000000000000006064820152fd5b80511561311e5790600091825b81518410156130c5576130bd6001916130ab6130a28786611df5565b51511515612fee565b6130b58685611df5565b515190612fd2565b930192613086565b6130d191929350612dda565b906020808301936000945b83518610156131165761310e6001916131046130f88988611df5565b51868151910183613127565b6130b58887611df5565b9501946130dc565b509350505090565b506106eb612dc2565b92905b60209384841061315f5781518152848101809111612bc857938101809111612bc85791601f198101908111612bc8579161312a565b929091935060200360208111612bc85761317890612fdf565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211612bc857518251821691191617905256fea164736f6c6343000819000ac65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8a164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca83000000000000000000000000000000", + "nonce": "0x43", + "chainId": "0x3039" + }, + "additionalContracts": [ + { + "transactionType": "CREATE2", + "address": "0x4fdaf3b68cf16e9fdd817c1d517d556085a4de57", + "initCode": "0x60a034607357601f615cf138819003918201601f19168301916001600160401b03831184841017607857808492602094604052833981010312607357516001600160a01b038116908190036073576001600055608052604051615c62908161008f823960805181818160e9015261042d0152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c90816306433b1b146100a45781630b0fdb3d14610055575080637fddd602146100505763b60bda491461004b57600080fd5b61020f565b610145565b346100a15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15760ff60406020926004358152600184522054166040519015158152f35b80fd5b346100a157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100a15773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660805260206080f35b600091031261011d57565b600080fd5b6064359073ffffffffffffffffffffffffffffffffffffffff8216820361011d57565b3461011d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011d5760043573ffffffffffffffffffffffffffffffffffffffff80821680920361011d576101d56020926040516101cd816101bf8782019460243590869091604092825260208201520190565b03601f19810183528261033f565b519020610b6e565b60405191168152f35b9181601f8401121561011d5782359167ffffffffffffffff831161011d576020808501948460051b01011161011d57565b3461011d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a08136011261011d576004359067ffffffffffffffff9081831161011d57608081843603011261011d576024359082821161011d57604090823603011261011d5760443591821161011d576102d7926102966102b09336906004016101de565b9061029f610122565b926084359460040190600401610362565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161031e57604052565b6102db565b6040810190811067ffffffffffffffff82111761031e57604052565b90601f601f19910116810190811067ffffffffffffffff82111761031e57604052565b93929490916000916002835414610640576002835560409586519182610398602082019232849091604092825260208201520190565b03926103ac601f199485810183528261033f565b519020946103ce6103c7876000526001602052604060002090565b5460ff1690565b6106175732867f4d26f9b035ac4dafb21ce257260243ad6adf7e105ac6517fe42bebde1d0828ca8780a3614e29916104086020840161066a565b92808452610e2d602085013973ffffffffffffffffffffffffffffffffffffffff998a7f0000000000000000000000000000000000000000000000000000000000000000169889918b51978895602087019561046396610a48565b038281018452610473908461033f565b86519283916020830161048591610b37565b61048e91610b37565b03908101825261049e908261033f565b6104a89083610d3e565b946104b283610b6e565b9080871690811592831561060a575b5050506105d957823b156100a15783517f4420e48600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86166004820152928390602490829084905af19081156105d45761056c92610541926105bb575b506000526001602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b5173ffffffffffffffffffffffffffffffffffffffff8216815233907ffb2d8b84e2e1acdcdbad3ce10c5a03d9f07b3f9f2e4a6d818a1a6a43610ac3b990602090a2906105b96001600055565b565b806105c86105ce9261030a565b80610112565b38610530565b610b62565b83517f8e6ae65f00000000000000000000000000000000000000000000000000000000815260048101839052602490fd5b16141590503880806104c1565b600488517f0ced3043000000000000000000000000000000000000000000000000000000008152fd5b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b906105b9604051928361033f565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18236030181121561011d570190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561011d57016020813591019167ffffffffffffffff821161011d57813603831361011d57565b601f8260209493601f19938186528686013760008582860101520116010190565b6107569161074861073d61072f84806106aa565b6040855260408501916106fa565b9260208101906106aa565b9160208185039101526106fa565b90565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff218236030181121561011d570190565b359067ffffffffffffffff8216820361011d57565b908281815260208091019360208360051b82010194846000925b8584106107cb575050505050505090565b9091929394959685806107f383601f1986600196030188526107ed8c886106aa565b906106fa565b9901940194019295949391906107ba565b67ffffffffffffffff91826108188361078b565b16815260208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18336030181121561011d5782019260208435940190841161011d578360051b3603811361011d576109006108a561088a61090b936107569760e0602088015260e08701916107a0565b61089760408701876106aa565b9086830360408801526106fa565b6108c56108b46060870161078b565b67ffffffffffffffff166060860152565b6108e56108d46080870161078b565b67ffffffffffffffff166080860152565b6108f260a08601866106aa565b9085830360a08701526106fa565b9260c08101906106aa565b9160c08185039101526106fa565b80357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818236030181121561011d57810191604081528235604082015260208301356060820152604083013573ffffffffffffffffffffffffffffffffffffffff811680910361011d576109b061099f610756956109bb93608086015260608101906106aa565b608060a086015260c08501916106fa565b926020810190610759565b906020818403910152610804565b9082818152602080910193818360051b82010194846000925b8584106109f3575050505050505090565b90919293949596858082601f198560019503018752610a128b87610678565b908280610a316040610a2486806106aa565b90918087528601916106fa565b9301359101529901940194019295949391906109e2565b91909496959360a08352610ab0610a74610a628880610678565b608060a087015261012086019061071b565b610a816020890189610678565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608683030160c087015261071b565b93604087013591600483101561011d57610aee608096610b1b9560606105b99b610afc9760e08b015201356101008901528782036020890152610919565b9185830360408701526109c9565b73ffffffffffffffffffffffffffffffffffffffff9097166060830152565b019073ffffffffffffffffffffffffffffffffffffffff169052565b9081519160005b838110610b4f575050016000815290565b8060208092840101518185015201610b3e565b6040513d6000823e3d90fd5b6040519060208201907fff0000000000000000000000000000000000000000000000000000000000000082523060601b602184015260358301527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605583015260558252608082019180831067ffffffffffffffff84111761031e57827f010000000000000000000000000000000000000000000000000000000000000060b6610c9b946107569660405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610c7f81610323565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b604051906040820182811067ffffffffffffffff82111761031e57604052601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b3d15610d39573d9067ffffffffffffffff821161031e5760405191610d2d6020601f19601f840116018461033f565b82523d6000602084013e565b606090565b9190610d48610cb4565b92610d5281610b6e565b93843b610e02576020815191016000f573ffffffffffffffffffffffffffffffffffffffff811615610dd85781600092918360208194519301915af1610d96610cfe565b50158015610dcf575b610da557565b60046040517f53de54b9000000000000000000000000000000000000000000000000000000008152fd5b50813b15610d9f565b60046040517fbbd2fe87000000000000000000000000000000000000000000000000000000008152fd5b60046040517fcd43efa1000000000000000000000000000000000000000000000000000000008152fdfe6101006040523461145957614e29803803809161001e826101006118c6565b6101003960a0811261145957610100516001600160401b03811161145957610100019060808282610100010312611459576040519161005c83611875565b80516001600160401b0381116114595761007d908361010001908301611960565b835260208101516001600160401b038111611459576100a3908361010001908301611960565b6020840152604081015190600482101561145957604084019190915260609081015190830152610120516001600160401b03811161145957610100016040818361010001031261145957604051906100fa82611890565b80516001600160401b03811161145957810160808185610100010312611459576040519061012782611875565b8051825260208101516020830152610141604082016119bc565b60408301526060810151906001600160401b0382116114595761016a918661010001910161190c565b6060820152825260208101516001600160401b0381116114595760e08183018561010001031261145957604051916101a1836118ab565b6101ac8282016119d0565b8352808201602001516001600160401b038111611459578561010001601f8285850101011215611459578083830101516101e5816119e4565b916101f360405193846118c6565b81835260208301886101000160208460051b8489890101010111611459576020828787010101905b60208460051b84898901010101821061183957505050506020840152808201604001516001600160401b0381116114595761025f908661010001908484010161190c565b60408401526102726060838301016119d0565b60608401526102856080838301016119d0565b608084015280820160a001516001600160401b038111611459576102b2908661010001908484010161190c565b60a084015280820160c001516001600160401b038111611459576102dd92866101000192010161190c565b60c08201526020820152610140516001600160401b03811161145957610100830161011f8201121561145957806101000151610318816119e4565b9361032660405195866118c6565b81855260208501926101008201610120600585901b83010111611459576101208101935b610120600585901b83010185106117c0578787876103696101606119bc565b926103756101806119bc565b602083015183516001600160a01b038716156117ae576001600160a01b0383161561179c5760a0820151511561178a5760c0820151511561177857604001516001600160a01b03161561176657610900608052604051906103d582611890565b600182526020368184013760016103eb836119fb565b5260805190516040805163338c1f5160e01b81526001600160401b039092166004830152602482015282516044820181905290926001600160a01b0390921691839160648301916020019060005b81811061174a5750505091818060009403915afa908115611466576000916114e0575b5061046d60206104779201516119fb565b5151805190611aca565b90156114ce57600080546001600160a01b0319166001600160a01b039290921691909117905561090260a05261090360c0526040516001600160401b0360608201908111908211176107d257606081016040526002815260005b604081106114bd57506020830151516104e9826119fb565b526104f3816119fb565b50602080840151015161050582611a08565b5261050f81611a08565b5060405161051c81611890565b6001815260646020820152606084810151604051939184018085116001600160401b03909111176107d2576060840160405283526020830152604082015260018060a01b0360c05116906040519060208083015260c08201908051604084015260208101519160806060850152825180915260e0840190602060e08260051b8701019401916000905b8282106114925750505050604001516000608084015b6002821061147257505050819003601f1981018252600092602092610628926105e490826118c6565b604051948580948193630b1e6daf60e31b83526040600484015260096044840152681c1c9a58d95c1c995960ba1b6064840152608060248401526084830190611a18565b03925af190811561146657600091611427575b50601180546001600160401b0319166001600160401b03929092169190911790556001600160a01b031660e05260005b83518110156107fe5760208160051b8501015160125490680100000000000000008210156107d25760018201806012558210156107e8576012600052805180517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344492916001600160401b0382116107d2576106fa826106ef8760011b870154611a3d565b8760011b8701611a8e565b602090601f83116001146107555792610735836001989796946020948a9760009261074a575b50508160011b916000199060031b1c19161790565b85851b8401555b015192821b0101550161066b565b015190508e80610720565b908560011b850160005260206000209160005b601f19851681106107ba575083602093600199989795938a9794938894601f198116106107a1575b505050811b0185851b84015561073c565b015160001960f88460031b161c191690558d8080610790565b91926020600181928685015181550194019201610768565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b508051805180518692916001600160401b0382116107d257610821600154611a3d565b601f81116113d8575b50602090601f831160011461136957918061085f92602095946000926111e65750508160011b916000199060031b1c19161790565b6001555b015180519093906001600160401b0381116107d257610883600254611a3d565b601f811161131a575b506020601f82116001146112af5781906108bf93949596600092610d5c5750508160011b916000199060031b1c19161790565b6002555b602083015180518051906001600160401b0382116107d2576108e6600354611a3d565b601f8111611260575b50602090601f83116001146111f157918061092492602095946000926111e65750508160011b916000199060031b1c19161790565b6003555b015180519093906001600160401b0381116107d257610948600454611a3d565b601f8111611197575b506020601f821160011461112c57819061098493949596600092610d5c5750508160011b916000199060031b1c19161790565b6004555b60408101519060048210156111165760609160ff8019600554169116176005550151600655606081518051600755602081015160085560018060a01b0360408201511660018060a01b03196009541617600955015180519060018060401b0382116107d2576109f8600a54611a3d565b601f81116110d9575b50602090601f8311600114611061579180610a369260209594600092610d5c5750508160011b916000199060031b1c19161790565b600a555b01519060018060401b0382511660018060401b0319600b541617600b5560208201518051906801000000000000000082116107d257600c5482600c55808310610fd0575b50600c60009081527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c792916020015b828210610ee95760408601518051869088906001600160401b0381116107d257610ad8600d54611a3d565b601f8111610e9a575b506020601f8211600114610e30578190610b13939495600092610e255750508160011b916000199060031b1c19161790565b600d555b6060810151600e805460808401516001600160801b03199091166001600160401b039384161760409190911b6fffffffffffffffff00000000000000001617905560a082015180519182116107d257610b71600f54611a3d565b601f8111610dd6575b50602090601f8311600114610d67579180610baf9260c09594600092610d5c5750508160011b916000199060031b1c19161790565b600f555b015180519091906001600160401b0381116107d257610bd3601054611a3d565b601f8111610d02575b50602092601f8211600114610c9c57610c0e92938291600092610c915750508160011b916000199060031b1c19161790565b6010555b60138054610100600160a81b03191660089290921b610100600160a81b031691909117905542620151808101908110610c7b576015556040516131bd9081611c4c8239608051816127b1015260a05181612371015260c051816122c5015260e0518161091e0152f35b634e487b7160e01b600052601160045260246000fd5b015190508480610720565b601f19821693601060005260206000209160005b868110610cea5750836001959610610cd1575b505050811b01601055610c12565b015160001960f88460031b161c19169055838080610cc3565b91926020600181928685015181550194019201610cb0565b6010600052610d4c907f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672601f840160051c81019160208510610d52575b601f0160051c0190611a77565b83610bdc565b9091508190610d3f565b015190508680610720565b90600f60005260206000209160005b601f1985168110610dbe575091839160019360c09695601f19811610610da5575b505050811b01600f55610bb3565b015160001960f88460031b161c19169055858080610d97565b91926020600181928685015181550194019201610d76565b600f600052610e1f907f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802601f850160051c81019160208610610d5257601f0160051c0190611a77565b84610b7a565b015190508580610720565b600d60005260206000209060005b601f1984168110610e825750600193949583601f19811610610e69575b505050811b01600d55610b17565b015160001960f88460031b161c19169055848080610e5b565b9091602060018192858a015181550193019101610e3e565b600d600052610ee3907fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5601f840160051c81019160208510610d5257601f0160051c0190611a77565b84610ae1565b80518051906001600160401b0382116107d257610f1082610f0a8854611a3d565b88611a8e565b602090601f8311600114610f625792610f4883600195946020948796600092610f575750508160011b916000199060031b1c19161790565b87555b01940191019092610aad565b015190508c80610720565b90601f198316918760005260206000209260005b818110610fb85750936020936001969387969383889510610f9f575b505050811b018755610f4b565b015160001960f88460031b161c191690558b8080610f92565b92936020600181928786015181550195019301610f76565b600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c79081019083015b81811061100a5750610a7e565b8061101760019254611a3d565b80611024575b5001610ffd565b601f8111831461103a5750600081555b8761101d565b600090828252611058601f60208420920160051c8201858301611a77565b81835555611034565b600a6000908152600080516020614e09833981519152929190601f198516905b8181106110c157509160019391856020979694106110a8575b505050811b01600a55610a3a565b015160001960f88460031b161c1916905585808061109a565b92936020600181928786015181550195019301611081565b600a60005261111090600080516020614e09833981519152601f850160051c81019160208610610d5257601f0160051c0190611a77565b84610a01565b634e487b7160e01b600052602160045260246000fd5b600460005260206000209060005b601f198416811061117f575060019394959683601f19811610611166575b505050811b01600455610988565b015160001960f88460031b161c19169055858080611158565b9091602060018192858b01518155019301910161113a565b60046000526111e0907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c81019160208510610d5257601f0160051c0190611a77565b85610951565b015190508880610720565b90600360005260206000209160005b601f1985168110611248575091839160019360209695601f1981161061122f575b505050811b01600355610928565b015160001960f88460031b161c19169055878080611221565b91926020600181928685015181550194019201611200565b60036000526112a9907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f850160051c81019160208610610d5257601f0160051c0190611a77565b866108ef565b600260005260206000209060005b601f1984168110611302575060019394959683601f198116106112e9575b505050811b016002556108c3565b015160001960f88460031b161c191690558580806112db565b9091602060018192858b0151815501930191016112bd565b6002600052611363907f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f840160051c81019160208510610d5257601f0160051c0190611a77565b8561088c565b90600160005260206000209160005b601f19851681106113c0575091839160019360209695601f198116106113a7575b505050811b01600155610863565b015160001960f88460031b161c19169055878080611399565b91926020600181928685015181550194019201611378565b6001600052611421907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f850160051c81019160208610610d5257601f0160051c0190611a77565b8661082a565b90506020813d60201161145e575b81611442602093836118c6565b8101031261145957611453906119d0565b8661063b565b600080fd5b3d9150611435565b6040513d6000823e3d90fd5b82516001600160401b0316815260209283019260019290920191016105bb565b909192946020806114af60019360df198b82030186528951611a18565b9701920192019092916105a5565b8060606020809385010152016104d1565b6040516307456b9160e21b8152600490fd5b903d8082843e6114f081846118c6565b6020838281010312611746578251926001600160401b0384116117425760408482018383010312611742576040519361152885611890565b818101516001600160401b03811161173e5760e08183850101858501031261173e5760405190611557826118ab565b61156481848601016119d0565b825261157660208285870101016119d0565b602083015261158b60408285870101016119d0565b6040830152606081848601010151600381101561172b5760608301528383018101608001516001600160401b03811161172b576115fb916115d760c0928888019083888a01010161190c565b60808501526115ec60a08287890101016119d0565b60a085015284860101016119d0565b60c0820152855281810160200151936001600160401b03851161173b57838301601f868486010101121561173b5784828401015192611639846119e4565b9561164760405197886118c6565b848752602087019386830160208760051b8484870101010111611737576020828285010101945b60208760051b84848701010101861061169b57505050505060208501939093525061046d915061045c9050565b85516001600160401b038111611733576040858401850182018a870103601f19011261173357604051906116ce82611890565b85840185018101602001516001600160401b03811161172f579061170260409260208d8a0191848a8a8d010101010161190c565b83528585880101010151600381101561172b57602082810191909152908252958601950161166e565b8680fd5b8780fd5b8580fd5b8380fd5b80fd5b8480fd5b8280fd5b5080fd5b825160030b845286945060209384019390920191600101610439565b604051630695a62360e51b8152600490fd5b604051636fc5f47160e01b8152600490fd5b60405163460be67160e11b8152600490fd5b6040516311a1e69760e01b8152600490fd5b60405163bcda548360e01b8152600490fd5b84516001600160401b038111611459578201610100810191906040908503601f19011261145957604051916117f483611890565b6020810151916001600160401b0383116114595760209360408594936118248695868b610100019184010161190c565b8352015183820152815201950194905061034a565b8151906001600160401b03821161145957602080929161186889838f95898e839861010001940101010161190c565b815201920191905061021b565b608081019081106001600160401b038211176107d257604052565b604081019081106001600160401b038211176107d257604052565b60e081019081106001600160401b038211176107d257604052565b601f909101601f19168101906001600160401b038211908210176107d257604052565b60005b8381106118fc5750506000910152565b81810151838201526020016118ec565b81601f820112156114595780516001600160401b0381116107d2576040519261193f601f8301601f1916602001856118c6565b818452602082840101116114595761195d91602080850191016118e9565b90565b9190604083820312611459576040519061197982611890565b8351919384926001600160401b039290838111611459578161199c91840161190c565b84526020820151928311611459576020926119b7920161190c565b910152565b51906001600160a01b038216820361145957565b51906001600160401b038216820361145957565b6001600160401b0381116107d25760051b60200190565b8051156107e85760200190565b8051600110156107e85760400190565b90602091611a31815180928185528580860191016118e9565b601f01601f1916010190565b90600182811c92168015611a6d575b6020831014611a5757565b634e487b7160e01b600052602260045260246000fd5b91607f1691611a4c565b818110611a82575050565b60008155600101611a77565b9190601f8111611a9d57505050565b611ac8926000526020600020906020601f840160051c83019310610d5257601f0160051c0190611a77565b565b9061060f60f31b61ffff60f01b602084015116148060011b9080820460021490151715610c7b5760280180602811610c7b578103611b1b57611b0b91611b25565b90916001600160a01b0390911690565b5050600090600090565b919060209061060f60f31b61ffff60f01b60208601511614936001928560011b9580870460021490151715610c7b57929190600095935b828510611b6e57505050505060019190565b909192939560ff611b888160f81b848a8701015116611bd9565b1690600f8211611bc957600481811b9180830460101490151715611bb457500195840193929190611b5c565b601190634e487b7160e01b6000525260246000fd5b5050505050509050600090600090565b60f81c602f811180611c41575b15611bf557602f190160ff1690565b6060811180611c37575b15611c0e576056190160ff1690565b6040811180611c2d575b15611c27576036190160ff1690565b5060ff90565b5060478110611c18565b5060678110611bff565b50603a8110611be656fe6080604052600436101561001257600080fd5b60003560e01c80631c9feaa5146100d7578063229e81fb146100d257806342859ab3146100cd5780635a509280146100c857806362b61c8b146100c357806378b90337146100be578063819ef8ba146100b957806388328a69146100b4578063b3d7ad48146100af578063cad31c74146100aa578063cbe61e59146100a55763d47e4eeb146100a057600080fd5b61165d565b611635565b611593565b61146e565b611350565b61126a565b610e15565b610c3d565b610b38565b6107ca565b61072c565b6100ec565b60009103126100e757565b600080fd5b346100e75760006003193601126100e757602060ff601354166040519015158152f35b90600182811c92168015610158575b602083101461012957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161011e565b600f54600092916101728261010f565b808252916020906001908181169081156101f15750600114610195575b50505050565b92939450600f6000527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802926000935b8585106101de57505050602092500101903880808061018f565b80548585018401529382019381016101c4565b915050602094955060ff1991509291921683830152151560051b0101903880808061018f565b601054600092916102278261010f565b808252916020906001908181169081156101f157506001146102495750505050565b9293945060106000527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672926000935b85851061029257505050602092500101903880808061018f565b8054858501840152938201938101610278565b600454600092916102b58261010f565b808252916020906001908181169081156101f157506001146102d75750505050565b9293945060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b926000935b85851061032057505050602092500101903880808061018f565b8054858501840152938201938101610306565b906000916001906001546103468161010f565b80835292602091600181169081156101f157506001146103665750505050565b9293945060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6926000935b8585106103af57505050602092500101903880808061018f565b8054858501840152938201938101610395565b600254600092916103d28261010f565b808252916020906001908181169081156101f157506001146103f45750505050565b9293945060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace926000935b85851061043d57505050602092500101903880808061018f565b8054858501840152938201938101610423565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761049b57604052565b610450565b67ffffffffffffffff811161049b57604052565b60a0810190811067ffffffffffffffff82111761049b57604052565b6080810190811067ffffffffffffffff82111761049b57604052565b60e0810190811067ffffffffffffffff82111761049b57604052565b6060810190811067ffffffffffffffff82111761049b57604052565b6020810190811067ffffffffffffffff82111761049b57604052565b90601f601f19910116810190811067ffffffffffffffff82111761049b57604052565b6040519061057b8261057481610162565b0383610540565b565b6040519061057b8261057481610217565b6040519061059b8261047f565b60405160035483916000816105af8461010f565b91828252602094600190866001821691826000146106595750506001146105fc575b506105de92500382610540565b8252604051916105f8836105f1816102a5565b0384610540565b0152565b85915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b8583106106415750506105de9350820101386105d1565b8054838801850152869450879390920191810161062a565b60ff1916858201526105de95151560051b85010192503891506105d19050565b60005b83811061068c5750506000910152565b818101518382015260200161067c565b90601f19601f6020936106ba81518092818752878088019101610679565b0116010190565b6106eb9160206106da835160408452604084019061069c565b92015190602081840391015261069c565b90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004111561072757565b6106ee565b346100e75760006003193601126100e7576040516107498161047f565b6040516107608161075981610333565b0382610540565b815260405161077281610759816103c2565b602082015261077f61058e565b60ff60055416906107b0600654916107a2604051956080875260808701906106c1565b9085820360208701526106c1565b906004831015610727578392604084015260608301520390f35b346100e75760a06003193601126100e75760046013549073ffffffffffffffffffffffffffffffffffffffff91828160081c163303610aa65760ff16610a7e57610819610815612247565b1590565b610a565761086b90610829611679565b92604051937f62b61c8b0000000000000000000000000000000000000000000000000000000085528480600095869360843560643560243589358a87016117aa565b0381305afa9384156109ce5783908495610a2f575b5061088a90611897565b6108e660206040516108b4816108a68985830160209181520190565b03601f198101835282610540565b604051809381927fcad31c74000000000000000000000000000000000000000000000000000000008352878301611b7a565b038187305af180156109ce57610911918591610a00575b5060ff60ff19601354169115151617601355565b60135460ff166109d7575b7f00000000000000000000000000000000000000000000000000000000000000001690813b156109d357604080517faa733a4400000000000000000000000000000000000000000000000000000000815232928101928352602083018690529392849290918391859183910103925af180156109ce576109b5575b5060135460ff166040805191151582526020820192909252f35b0390f35b806109c26109c8926104a0565b806100dc565b38610997565b611819565b8280fd5b7f68f46c45a243a0e9065a97649faf9a5afe1692f2679e650c2f853b9cd734cc0e8380a161091c565b610a22915060203d602011610a28575b610a1a8183610540565b8101906119c3565b386108fd565b503d610a10565b61088a9550610a5091503d8086833e610a488183610540565b81019061173c565b94610880565b6040517f741926a1000000000000000000000000000000000000000000000000000000008152fd5b6040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b506040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b908160809103126100e75790565b6020815273ffffffffffffffffffffffffffffffffffffffff80835116602083015260208301511660408201526040820151606082015260a06080610b2f6060850151838386015260c085019061069c565b93015191015290565b346100e75760206003193601126100e75760043567ffffffffffffffff81116100e757610b6c6109b1913690600401610acf565b610b74611c57565b5073ffffffffffffffffffffffffffffffffffffffff90610bd9826000541692604083013590610ba382611c82565b610bb06060850185611caa565b91909260405196610bc0886104b4565b8752166020860152602084013560408601523691611cfb565b606083015235608082015260405191829182610add565b9181601f840112156100e75782359167ffffffffffffffff83116100e7576020808501948460051b0101116100e757565b929190610c3860209160408652604086019061069c565b930152565b346100e75760c06003193601126100e75767ffffffffffffffff6084358181116100e757610c6f903690600401610bf0565b60a4929192359182116100e757610dd5610dd0610dfe94610c97610dee953690600401610acf565b93610db5610cba610dae610ca961168c565b97610cbf610cba6020830135612f17565b61285c565b610cc88a611d61565b52610cd289611d61565b50610ce1610cba600435612f17565b610cea8a611d73565b52610cf489611d73565b50610d03610cba604435612f17565b610d0c8a611d83565b52610d1689611d83565b50610d25610cba606435612f17565b610d2e8a611d93565b52610d3889611d93565b50610d47610cba602435612f17565b610d508a611da3565b52610d5a89611da3565b50610d6f610d6a60408301611ca0565b61281b565b610d788a611db3565b52610d8289611db3565b50610d90610cba8235612f17565b610d998a611dc3565b52610da389611dc3565b506060810190611caa565b3691611cfb565b610dbe86611dd3565b52610dc885611dd3565b503691611e09565b6129e2565b610dde82611de4565b52610de881611de4565b506129e2565b610df9610cba612e38565b612b12565b80516020820120906109b160405192839283610c21565b346100e75760006003193601126100e7576020610e30612247565b6040519015158152f35b600a5460009291610e4a8261010f565b808252916020906001908181169081156101f15750600114610e6c5750505050565b92939450600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8926000935b858510610eb557505050602092500101903880808061018f565b8054858501840152938201938101610e9b565b600d5460009291610ed88261010f565b808252916020906001908181169081156101f15750600114610efa5750505050565b92939450600d6000527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5926000935b858510610f4357505050602092500101903880808061018f565b8054858501840152938201938101610f29565b600a5460009291610f668261010f565b808252916020906001908181169081156101f15750600114610f885750505050565b92939450600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8926000935b858510610fd157505050602092500101903880808061018f565b8054858501840152938201938101610fb7565b805460009392610ff38261010f565b9182825260209360019160018116908160001461105b575060011461101a575b5050505050565b90939495506000929192528360002092846000945b83861061104757505050500101903880808080611013565b80548587018301529401938590820161102f565b60ff19168685015250505090151560051b010191503880808080611013565b6040519061057b8261057481610ec8565b67ffffffffffffffff811161049b5760051b60200190565b600c54906110b08261108b565b9160406110c06040519485610540565b81845283602080910191600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7906000935b85851061110457505050505050565b6001848192845161111981610759818a610fe4565b8152019301940193916110f5565b90808251908181526020809101926020808460051b8301019501936000915b8483106111565750505050505090565b909192939495848061117483601f1986600196030187528a5161069c565b9801930193019194939290611146565b6111d560606106eb9493604084528051604085015260208101518285015273ffffffffffffffffffffffffffffffffffffffff60408201511660808501520151608060a084015260c083019061069c565b90602081830391015267ffffffffffffffff825116815260c061125961121f61120d602086015160e0602087015260e0860190611127565b6040860151858203604087015261069c565b60608581015167ffffffffffffffff169085015260808581015167ffffffffffffffff169085015260a085015184820360a086015261069c565b9201519060c081840391015261069c565b346100e75760006003193601126100e75760408051611288816104d0565b6007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff600954168282015281516112c18161075981610e3a565b60608201526109b18251926112d5846104ec565b61132c67ffffffffffffffff80600b541686526112f06110a3565b60208701526112fd61107a565b86840152600e5467ffffffffffffffff828216166060880152831c16608086019067ffffffffffffffff169052565b611334610563565b60a085015261134161057d565b60c08501525192839283611184565b346100e75760008060031936011261146b5760ff601354161561144157604051908082601454916113808361010f565b928383526020946001918660018216918260001461141e5750506001146113c4575b50506113b092500383610540565b6109b160405192828493845283019061069c565b90859250601482527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec5b8583106114065750506113b0935082010138806113a2565b805483890185015287945086939092019181016113ee565b915093506113b095925060ff1991501682840152151560051b82010138806113a2565b60046040517ff4490980000000000000000000000000000000000000000000000000000000008152fd5b80fd5b346100e75760008060031936011261146b57611488611c57565b50604051907f5a509280000000000000000000000000000000000000000000000000000000008252602060048301528082806114c66024820161176d565b0381305afa9081156109ce5780916114e7575b604051806109b18482610add565b90503d8082843e6114f88184610540565b820160208382031261158f57825167ffffffffffffffff9384821161158b57019260a0848303126109d35760405192611530846104b4565b845161153b81611c82565b8452602085015161154b81611c82565b602085015260408501516040850152606085015191821161146b5750926115796080926109b1958301611722565b606084015201516080820152386114d9565b8380fd5b5080fd5b346100e7576003196060813601126100e75760043567ffffffffffffffff918282116100e75760e09082360301126100e757602435918083116100e757366023840112156100e7578260040135928184116100e75736602485830101116100e7576044359182116100e7576109b193611623936116166024943690600401610bf0565b949093019060040161270c565b60405190151581529081906020820190565b346100e75760006003193601126100e757602067ffffffffffffffff60115416604051908152f35b346100e75760006003193601126100e757602060405160108152f35b60405161168581610524565b6000815290565b60405190610140820182811067ffffffffffffffff82111761049b57604052600982528160005b61012081106116c0575050565b8060606020809385010152016116b3565b67ffffffffffffffff811161049b57601f01601f191660200190565b909291926116fa816116d1565b916117086040519384610540565b8294828452828201116100e757602061057b930190610679565b9080601f830112156100e75781516106eb926020016116ed565b91906040838203126100e757825167ffffffffffffffff81116100e757602091611767918501611722565b92015190565b60806106eb916007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff60095416604082015281606082015201610f56565b92936080946117d9936106eb9793865260208601526040850152606084015260c08484015260c0830190611127565b9060a08183039101526007548152600854602082015273ffffffffffffffffffffffffffffffffffffffff60095416604082015281606082015201610f56565b6040513d6000823e3d90fd5b601f8111611831575050565b60009060146000527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec906020601f850160051c8301941061188d575b601f0160051c01915b82811061188257505050565b818155600101611876565b909250829061186d565b90815167ffffffffffffffff811161049b576118bd816118b860145461010f565b611825565b602080601f831160011461191d5750819061190d9394600092611912575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b601455565b0151905038806118db565b90601f1983169461195060146000527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec90565b926000905b8782106119ab575050836001959610611974575b505050811b01601455565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611969565b80600185968294968601518155019501930190611955565b908160209103126100e7575180151581036100e75790565b80600c5480825260208092019160208260051b85010193600c6000527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7936000915b848310611a2d5750505050505090565b909192939495846001611a4a83601f19868496030187528a610fe4565b9801930193019194939290611a1d565b8060125490818152602080910191600591808260051b86010194600094601286527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34449580925b858410611ab257505050505050505090565b9091929394959697601f19828203018452856040808352898b8692815490611ad98261010f565b80918801526060916001948582169182600014611b5b575050600114611b1a575b505001549282019290925290986002019796959460010193019190611aa0565b909180945088528488209088915b818310611b3d57505085010191836001611afa565b8496929491939550805486868a0101520192018d93918b9593611b28565b60ff19168985015291151590911b870190910193508490506001611afa565b611c496106eb9260608352611bad60608401611b9f600b5467ffffffffffffffff1690565b67ffffffffffffffff169052565b60e06080840152611c3b611bc461014085016119db565b611c2b611bfb7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa092838882030160a0890152610ec8565b600e5467ffffffffffffffff80821660c08a015260409190911c1660e08801528287820301610100880152610162565b9085820301610120860152610217565b90838203602085015261069c565b906040818303910152611a5a565b60405190611c64826104b4565b60006080838281528260208201528260408201526060808201520152565b73ffffffffffffffffffffffffffffffffffffffff8116036100e757565b356106eb81611c82565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e7570180359067ffffffffffffffff82116100e7576020019181360383136100e757565b929192611d07826116d1565b91611d156040519384610540565b8294818452818301116100e7578281602093846000960137010152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805115611d6e5760200190565b611d32565b805160011015611d6e5760400190565b805160021015611d6e5760600190565b805160031015611d6e5760800190565b805160041015611d6e5760a00190565b805160051015611d6e5760c00190565b805160061015611d6e5760e00190565b805160071015611d6e576101000190565b805160081015611d6e576101200190565b8051821015611d6e5760209160051b010190565b92919092611e168461108b565b91611e246040519384610540565b829480845260208094019060051b8301928284116100e75780915b848310611e4e57505050505050565b823567ffffffffffffffff81116100e757820184601f820112156100e7578691611e7e8683858095359101611cfb565b815201920191611e3f565b67ffffffffffffffff8116036100e757565b9080601f830112156100e757815191602091611eb68461108b565b93604091611ec76040519687610540565b818652848087019260051b850101938185116100e757858101925b858410611ef3575050505050505090565b83519067ffffffffffffffff918281116100e757830160609081601f1982880301126100e757875193611f2585610508565b8a820151611f3281611e89565b8552888201519081116100e757868b611f4d92840101611722565b8a85015201519060038210156100e757828993928885940152815201930192611ee2565b91906060838203126100e75760405190611f8a82610508565b81938051611f9781611e89565b835260208101519167ffffffffffffffff928381116100e75781611fbc918401611722565b602085015260408201519283116100e757604092611fda9201611722565b910152565b9060209081838203126100e757825167ffffffffffffffff938482116100e757019282848303126100e75760409182519461201986610524565b8051908382116100e75701916060838303126100e75783519461203b86610508565b83518281116100e75784016080818503126100e75785519061205c826104d0565b805161206781611e89565b82528281015161207681611c82565b83830152868101518481116100e757810185601f820112156100e7578581856120a1935191016116ed565b878301526060810151908482116100e7576120be91869101611722565b60608201528652808401518281116100e757836120dc918601611e9b565b90860152838301519081116100e7576120f59201611f71565b90820152815290565b60209081818403126100e75780519067ffffffffffffffff82116100e757019180601f840112156100e75782516121348161108b565b936121426040519586610540565b818552838086019260051b8201019283116100e7578301905b828210612169575050505090565b8151815290830190830161215b565b8091039060c082126100e75760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0604051936121b4856104d0565b83516121bf81611e89565b855260208401516121cf81611e89565b602086015260408401516121e281611e89565b604086015201126100e75760a0604051916121fc83610508565b606081015161220a81611e89565b83526080810151602084015201516040820152606082015290565b6106eb906040815261223960408201610333565b9060208183039101526103c2565b60155442116124685773ffffffffffffffffffffffffffffffffffffffff6122c0600061227d60115467ffffffffffffffff1690565b6040517f012d56e000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015291829081906024820190565b0381857f0000000000000000000000000000000000000000000000000000000000000000165afa80156109ce57604091600091612445575b5051015167ffffffffffffffff612317825167ffffffffffffffff1690565b161561243e576020612334910151602080825183010191016120fe565b9060c060405180927f3d0f34da000000000000000000000000000000000000000000000000000000008252818061236d60048201612225565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa80156109ce576106eb9261240392600092612409575b50806123cb6123c46123bd6123d094611d61565b5192611d73565b5191612be4565b612c13565b6123fd6123f06040806060860151015194015167ffffffffffffffff1690565b67ffffffffffffffff1690565b91612c67565b90612cd1565b6123d09192506124309060c03d60c011612437575b6124288183610540565b810190612178565b91906123a9565b503d61241e565b5050600090565b61246291503d806000833e61245a8183610540565b810190611fdf565b386122f8565b600090565b356106eb81611e89565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156100e7570180359067ffffffffffffffff82116100e757602001918160051b360383136100e757565b601f8260209493601f19938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100e757016020813591019167ffffffffffffffff82116100e75781360383136100e757565b90918092808252602080920191808260051b8601019484600080925b85841061256a57505050505050505090565b9091929394959697601f1982820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18536030181121561158b5786600192868293019082806125d060406125c386806124ec565b90918087528601916124cb565b9301359101529a01980196959401929190612558565b9e9b999f9d9c9a989694918f9694939061261b9167ffffffffffffffff610140941689526020938060208b01528901916124cb565b956040818803910152818652602086019560208360051b82010196846000925b8584106126d357505050505050509461269e8c9d60a061268d61057b9e9f986101209e9c9861267f6126cb9f9d996126af996126bc9e8e60608185039101526124cb565b918b830360808d015261253c565b97019067ffffffffffffffff169052565b67ffffffffffffffff1660c08d0152565b8a830360e08c01526124cb565b918783036101008901526124cb565b930160019052565b9091929394959885806126fb836126f58e601f198860019803018a52886124ec565b906124cb565b9b019401940192959493919061263b565b909293919361271a8261246d565b926127286020840184612477565b9390926127386040830183611caa565b919093606084016127489061246d565b916127556080860161246d565b9361276360a0870187611caa565b97909660c0810161277391611caa565b9a90996040519e8f9e8f7f07d145e90000000000000000000000000000000000000000000000000000000081526004019e6127ad9f6125e6565b03817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a602094600091f19081156109ce57600091612802575090565b6106eb915060203d602011610a2857610a1a8183610540565b6106eb9060405190741400000000000000000000000000000000000000001860148201526034810160405261285c565b908151811015611d6e570160200190565b906000918051926001936001811490816129ca575b501561287c57509150565b81519360388510156128d65750926106eb92937fff000000000000000000000000000000000000000000000000000000000000006128c16128bb612da8565b93612fb6565b60f81b16901a6128d082611d61565b53612b12565b8190806001915b61299a575b50506128f56128f082612f9a565b612dda565b917fff0000000000000000000000000000000000000000000000000000000000000061292861292384612fb6565b612fa8565b8160f89160f81b16831a61293b86611d61565b5360015b848111156129575750505050506106eb929350612b12565b808361298061297a61297461296f612995968b612c5a565b612fdf565b8d612c13565b60ff1690565b841b16851a61298f828961284b565b53612e0b565b61293f565b90916129a68388612c13565b156129c4576129b76129bd91612e0b565b92612bcd565b90806128dd565b916128e2565b905015611d6e576080602083015160f81c1038612871565b6129eb90613079565b908151600060388210600014612a445750916106eb91927fff00000000000000000000000000000000000000000000000000000000000000612a34612a2e612da8565b92612fc4565b60f81b1660001a6128d082611d61565b916001925b612a538484612c13565b15612a7057612a64612a6a91612e0b565b93612bcd565b92612a49565b909250929092612a826128f082612f9a565b907fff00000000000000000000000000000000000000000000000000000000000000612ab061292383612fc4565b8160f89160f81b1660001a612ac485611d61565b5360015b83811115612adf57505050506106eb929350612b12565b8083612afd61297a612af761296f612b0d968a612c5a565b8c612c13565b841b1660001a61298f828861284b565b612ac8565b6040518151808252909290830191602083810192818301828088015b868110612b7b5750505080518094875182018852950194828087019201905b828110612b6c575050505091603f91601f199351011501011660405290565b81518152908301908301612b4d565b8251815291810191849101612b2e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b604d8111612bc857600a0a90565b612b8b565b908160081b918083046101001490151715612bc857565b90662386f26fc1000091828102928184041490151715612bc857565b81810292918115918404141715612bc857565b8115612c1d570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6020039060208211612bc857565b91908203918211612bc857565b909291906010821115612cc957815b820390828211612bc857612c8c612c9292612bba565b90612c00565b927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08201918211612bc857612c8c6106eb92612bba565b601091612c76565b60ff6005541691612ce18361071d565b600183149283612d84575b8315612d61575b8315612d3d575b8315612d12575b505050612d0d57600090565b600190565b600291929350612d218161071d565b149182612d33575b5050388080612d01565b1090503880612d29565b9250612d488361071d565b6003831480612d58575b92612cfa565b50808211612d52565b9250612d6c8361071d565b821580612d7a575b92612cf3565b5080821115612d74565b818310159350612cec565b60405190612d9c8261047f565b60208083523683820137565b60405190612db58261047f565b6001825260203681840137565b604051612dce81610524565b60008152906000368137565b90612de4826116d1565b612df16040519182610540565b828152601f19612e0182946116d1565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612bc85760010190565b612e40612d8f565b90602091600260208201526000926000905b808210612ece575b50612e676128f082612c4c565b9160005b8351811015612ec657600190612eb3612e8d612e8686612e0b565b958561284b565b517fff000000000000000000000000000000000000000000000000000000000000001690565b871a612ebf828761284b565b5301612e6b565b509193505050565b90612f04612edf612e8d838661284b565b7fff000000000000000000000000000000000000000000000000000000000000001690565b612f115760010190612e52565b90612e5a565b90612f20612d8f565b60209260208201526000926000905b808210612f76575b50612f446128f082612c4c565b9160005b8351811015612ec657600190612f63612e8d612e8686612e0b565b871a612f6f828761284b565b5301612f48565b90612f87612edf612e8d838661284b565b612f945760010190612f2f565b90612f37565b9060018201809211612bc857565b9060378201809211612bc857565b9060808201809211612bc857565b9060c08201809211612bc857565b91908201809211612bc857565b601f8111612bc8576101000a90565b15612ff557565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f416e206974656d20696e20746865206c69737420746f20626520524c5020656e60448201527f636f646564206973206e756c6c2e0000000000000000000000000000000000006064820152fd5b80511561311e5790600091825b81518410156130c5576130bd6001916130ab6130a28786611df5565b51511515612fee565b6130b58685611df5565b515190612fd2565b930192613086565b6130d191929350612dda565b906020808301936000945b83518610156131165761310e6001916131046130f88988611df5565b51868151910183613127565b6130b58887611df5565b9501946130dc565b509350505090565b506106eb612dc2565b92905b60209384841061315f5781518152848101809111612bc857938101809111612bc85791601f198101908111612bc8579161312a565b929091935060200360208111612bc85761317890612fdf565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211612bc857518251821691191617905256fea164736f6c6343000819000ac65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8a164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca83" + } + ], + "isFixedGasLimit": false + }, + { + "hash": "0x3a1273cfe7d6faeb2efd98ea8c3d5f08ac19c72e06470fe5735ba5c43b6e9ef2", + "transactionType": "CALL", + "contractName": "Create2", + "contractAddress": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "function": "deploy(bytes32,bytes)", + "arguments": [ + "0x6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003ea", + "0x60e03461017a57601f61149a38819003918201601f191683019291906001600160401b0384118385101761017f578160a0928492604096875283398101031261017a5761004b81610195565b9061005860208201610195565b90610064848201610195565b9061007d608061007660608401610195565b9201610195565b6001600160a01b0392831693909190841561016257836000549660018060a01b03199680888a1617600055828a5199167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3600180551695861561015357508316948515610142579083916080521660a0521660c0526003541617600355516112f090816101aa823960805181610c65015260a05181818161025f015281816104e70152610834015260c05181818161038e015281816104630152610acc0152f35b8651637d8ed95960e11b8152600490fd5b637bfd2e8360e01b8152600490fd5b8651631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820361017a5756fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306433b1b14610c395750816315a96ae91461064a5781633f6746ce1461058c578163715018a61461050b57816372bdda54146104ba5781638da5cb5b14610487578163aa63810714610436578163d1ad17bf14610401578163f04e5bed146101b0578163f2fde38b146100e7575063f40e84711461009e57600080fd5b346100e35760206003193601126100e3576020918173ffffffffffffffffffffffffffffffffffffffff91826100d2610c89565b168152600285522054169051908152f35b5080fd5b9050346101ac5760206003193601126101ac57610102610c89565b9061010b611292565b73ffffffffffffffffffffffffffffffffffffffff80921692831561017d5750508254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b908460249251917f1e4fbdf7000000000000000000000000000000000000000000000000000000008352820152fd5b8280fd5b8383346100e35760606003193601126100e3576101cb610c89565b602435906044359460028610156103fd57849580156000146102eb575083949550610246602093945194859384937f7fddd60200000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102df579073ffffffffffffffffffffffffffffffffffffffff91602094916102b2575b50915b5191168152f35b6102d29150843d86116102d8575b6102ca8183610cb1565b810190610df9565b846102a8565b503d6102c0565b505051903d90823e3d90fd5b939493600114610318575b505050509073ffffffffffffffffffffffffffffffffffffffff6020926102ab565b602092939550610375855194859384937f7fddd60200000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102df579073ffffffffffffffffffffffffffffffffffffffff91602094916103e0575b509284806102f6565b6103f79150843d86116102d8576102ca8183610cb1565b846103d7565b8480fd5b5050346100e357816003193601126100e35760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5050346100e357816003193601126100e3576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5050346100e357816003193601126100e35773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b5050346100e357816003193601126100e3576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8334610589578060031936011261058957610524611292565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b9050346101ac5760206003193601126101ac576105a7610c89565b906105b0611292565b73ffffffffffffffffffffffffffffffffffffffff809216928315610624575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167fd8a42eaab83c563642705bc71a5905c29682aa5bf997aaa24b2ff7b3f32ed0b68380a380f35b517ffb1db2b2000000000000000000000000000000000000000000000000000000008152fd5b919050346101ac5760031960a081360112610c355782359267ffffffffffffffff91828511610c315736602386011215610c31578482013591838311610c2d576024918287019387019183830195368711610c2957843592818411610c255788818585019536030112610c2557604435828111610c215736602382011215610c21578084013591838311610c1d57878201918836918560051b010111610c1d576064359260028410156109435760029c6084359460019e8f5414610bf55760028f558e908061094757505060209a8b828b03126109135735868111610913576060910180990312610943578b51966060880188811087821117610917578d5289890135885260448901359b878d1015610913578b89019c8d5260648a0135968711610913578a8e978d9b01019061078091610d96565b998689019a8b5273ffffffffffffffffffffffffffffffffffffffff9a8b6003541697519d8e9a8b9a7f3dc48a34000000000000000000000000000000000000000000000000000000008c528b0160a090525160a48b01525160c48a016107e691610eb0565b5160e489016060905261010489016107fd91610e83565b9084898303019089015261081091610f90565b91868303016044870152610823926111ca565b9160648401526084830152038189857f0000000000000000000000000000000000000000000000000000000000000000165af1928315610909579573ffffffffffffffffffffffffffffffffffffffff9493929160209782946108e7575b5060029084169283835252838120337fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055337f08e9a1418653bd72d79048c016f319d58d60c2615929361e4c38adc69265c4c88280a4925b80555191168152f35b600291945061090290843d86116102d8576102ca8183610cb1565b9390610881565b84513d88823e3d90fd5b8f80fd5b50898f6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8d80fd5b9c98999a96929c14600014610bcd5760209a8b828c031261091357358281116109135760809101809a0312610943578b51966080880188811083821117610ba1578d52858a01358281116109135781876109a3928d0101610d96565b885260448a0135918211610b9d57856109be928b0101610d96565b998987019a8b5260648901359786891015610b9d578a988d96878a0191825260608a019b608401358c5273ffffffffffffffffffffffffffffffffffffffff9b8c6003541698519e8f9b8c9b7fb60bda49000000000000000000000000000000000000000000000000000000008d528c0160a090525160a48c01608090526101248c01610a4a91610e83565b9051908b81037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c0160c48d0152610a8091610e83565b925160e48b01610a8f91610eb0565b516101048a0152848983030190890152610aa891610f90565b91868303016044870152610abb926111ca565b9160648401526084830152038189857f0000000000000000000000000000000000000000000000000000000000000000165af1928315610909578673ffffffffffffffffffffffffffffffffffffffff95949392879260209995610b7b575b5060029085169384835252848120337fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790557f08e9a1418653bd72d79048c016f319d58d60c2615929361e4c38adc69265c4c8339180a4926108de565b6002919550610b9690853d87116102d8576102ca8183610cb1565b9490610b1a565b8e80fd5b50858f6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b868d517fa3c0e0d1000000000000000000000000000000000000000000000000000000008152fd5b878e517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b8c80fd5b8b80fd5b8a80fd5b8980fd5b8680fd5b8580fd5b8380fd5b8490346100e357816003193601126100e35760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610cac57565b600080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610cf257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b81601f82011215610cac5780359067ffffffffffffffff8211610cf25760405192610d7460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185610cb1565b82845260208383010111610cac57816000926020809301838601378301015290565b919091604081840312610cac57604080519167ffffffffffffffff91830182811184821017610cf25760405282948135838111610cac5781610dd9918401610d21565b84526020820135928311610cac57602092610df49201610d21565b910152565b90816020910312610cac575173ffffffffffffffffffffffffffffffffffffffff81168103610cac5790565b919082519283825260005b848110610e6f5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610e30565b610ead916020610e9c8351604084526040840190610e25565b920151906020818403910152610e25565b90565b906004821015610ebd5752565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610cac57016020813591019167ffffffffffffffff8211610cac578136038313610cac57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b359067ffffffffffffffff82168203610cac57565b91908235833603907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818201811215610cac578401936040835284356040840152602094858101356060850152604081013573ffffffffffffffffffffffffffffffffffffffff8116809103610cac57611027916110169160808701526060810190610eec565b608060a087015260c0860191610f3c565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff21868301359101811215610cac5701918481830391015260e0810167ffffffffffffffff948561107785610f7b565b168352808401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811215610cac57840190808235920192878311610cac578260051b908136038513610cac5760e0868401528390528401610100908101939291906000908601845b8483106111755750505050505061115c610ead949561111b6111679361110d6040880188610eec565b908783036040890152610f3c565b908061112960608801610f7b565b16606086015261113b60808701610f7b565b16608085015261114e60a0860186610eec565b9085830360a0870152610f3c565b9260c0810190610eec565b9160c0818503910152610f3c565b90919293949584806111ba837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008c600196030187526111b48b87610eec565b90610f3c565b98019301930191949392906110e4565b90918092808252602080920191808260051b8601019484600080925b8584106111f857505050505050505090565b90919293949596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc185360301811215610c3557866001928682930190828061127c604061126f8680610eec565b9091808752860191610f3c565b9301359101529a019801969594019291906111e6565b73ffffffffffffffffffffffffffffffffffffffff6000541633036112b357565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fdfea164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca8300000000000000000000000003506d9a00fd1e2c9176454a267424285eda18ac000000000000000000000000b342a793be112dfb4526aafbfbe55bc3ef74c2a1000000000000000000000000a779126c3314385e9b0041072ea6a89d295fd1950000000000000000000000004fdaf3b68cf16e9fdd817c1d517d556085a4de57" + ], + "transaction": { + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "gas": "0x18b9a7", + "value": "0x0", + "input": "0xcdcb760a6ea8ac1673402989e7b653ae4e83b54173719c300000000000000000000003ea0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000153a60e03461017a57601f61149a38819003918201601f191683019291906001600160401b0384118385101761017f578160a0928492604096875283398101031261017a5761004b81610195565b9061005860208201610195565b90610064848201610195565b9061007d608061007660608401610195565b9201610195565b6001600160a01b0392831693909190841561016257836000549660018060a01b03199680888a1617600055828a5199167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3600180551695861561015357508316948515610142579083916080521660a0521660c0526003541617600355516112f090816101aa823960805181610c65015260a05181818161025f015281816104e70152610834015260c05181818161038e015281816104630152610acc0152f35b8651637d8ed95960e11b8152600490fd5b637bfd2e8360e01b8152600490fd5b8651631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820361017a5756fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306433b1b14610c395750816315a96ae91461064a5781633f6746ce1461058c578163715018a61461050b57816372bdda54146104ba5781638da5cb5b14610487578163aa63810714610436578163d1ad17bf14610401578163f04e5bed146101b0578163f2fde38b146100e7575063f40e84711461009e57600080fd5b346100e35760206003193601126100e3576020918173ffffffffffffffffffffffffffffffffffffffff91826100d2610c89565b168152600285522054169051908152f35b5080fd5b9050346101ac5760206003193601126101ac57610102610c89565b9061010b611292565b73ffffffffffffffffffffffffffffffffffffffff80921692831561017d5750508254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b908460249251917f1e4fbdf7000000000000000000000000000000000000000000000000000000008352820152fd5b8280fd5b8383346100e35760606003193601126100e3576101cb610c89565b602435906044359460028610156103fd57849580156000146102eb575083949550610246602093945194859384937f7fddd60200000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102df579073ffffffffffffffffffffffffffffffffffffffff91602094916102b2575b50915b5191168152f35b6102d29150843d86116102d8575b6102ca8183610cb1565b810190610df9565b846102a8565b503d6102c0565b505051903d90823e3d90fd5b939493600114610318575b505050509073ffffffffffffffffffffffffffffffffffffffff6020926102ab565b602092939550610375855194859384937f7fddd60200000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102df579073ffffffffffffffffffffffffffffffffffffffff91602094916103e0575b509284806102f6565b6103f79150843d86116102d8576102ca8183610cb1565b846103d7565b8480fd5b5050346100e357816003193601126100e35760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5050346100e357816003193601126100e3576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5050346100e357816003193601126100e35773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b5050346100e357816003193601126100e3576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8334610589578060031936011261058957610524611292565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b9050346101ac5760206003193601126101ac576105a7610c89565b906105b0611292565b73ffffffffffffffffffffffffffffffffffffffff809216928315610624575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167fd8a42eaab83c563642705bc71a5905c29682aa5bf997aaa24b2ff7b3f32ed0b68380a380f35b517ffb1db2b2000000000000000000000000000000000000000000000000000000008152fd5b919050346101ac5760031960a081360112610c355782359267ffffffffffffffff91828511610c315736602386011215610c31578482013591838311610c2d576024918287019387019183830195368711610c2957843592818411610c255788818585019536030112610c2557604435828111610c215736602382011215610c21578084013591838311610c1d57878201918836918560051b010111610c1d576064359260028410156109435760029c6084359460019e8f5414610bf55760028f558e908061094757505060209a8b828b03126109135735868111610913576060910180990312610943578b51966060880188811087821117610917578d5289890135885260448901359b878d1015610913578b89019c8d5260648a0135968711610913578a8e978d9b01019061078091610d96565b998689019a8b5273ffffffffffffffffffffffffffffffffffffffff9a8b6003541697519d8e9a8b9a7f3dc48a34000000000000000000000000000000000000000000000000000000008c528b0160a090525160a48b01525160c48a016107e691610eb0565b5160e489016060905261010489016107fd91610e83565b9084898303019089015261081091610f90565b91868303016044870152610823926111ca565b9160648401526084830152038189857f0000000000000000000000000000000000000000000000000000000000000000165af1928315610909579573ffffffffffffffffffffffffffffffffffffffff9493929160209782946108e7575b5060029084169283835252838120337fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055337f08e9a1418653bd72d79048c016f319d58d60c2615929361e4c38adc69265c4c88280a4925b80555191168152f35b600291945061090290843d86116102d8576102ca8183610cb1565b9390610881565b84513d88823e3d90fd5b8f80fd5b50898f6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8d80fd5b9c98999a96929c14600014610bcd5760209a8b828c031261091357358281116109135760809101809a0312610943578b51966080880188811083821117610ba1578d52858a01358281116109135781876109a3928d0101610d96565b885260448a0135918211610b9d57856109be928b0101610d96565b998987019a8b5260648901359786891015610b9d578a988d96878a0191825260608a019b608401358c5273ffffffffffffffffffffffffffffffffffffffff9b8c6003541698519e8f9b8c9b7fb60bda49000000000000000000000000000000000000000000000000000000008d528c0160a090525160a48c01608090526101248c01610a4a91610e83565b9051908b81037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c0160c48d0152610a8091610e83565b925160e48b01610a8f91610eb0565b516101048a0152848983030190890152610aa891610f90565b91868303016044870152610abb926111ca565b9160648401526084830152038189857f0000000000000000000000000000000000000000000000000000000000000000165af1928315610909578673ffffffffffffffffffffffffffffffffffffffff95949392879260209995610b7b575b5060029085169384835252848120337fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790557f08e9a1418653bd72d79048c016f319d58d60c2615929361e4c38adc69265c4c8339180a4926108de565b6002919550610b9690853d87116102d8576102ca8183610cb1565b9490610b1a565b8e80fd5b50858f6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b868d517fa3c0e0d1000000000000000000000000000000000000000000000000000000008152fd5b878e517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b8c80fd5b8b80fd5b8a80fd5b8980fd5b8680fd5b8580fd5b8380fd5b8490346100e357816003193601126100e35760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610cac57565b600080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610cf257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b81601f82011215610cac5780359067ffffffffffffffff8211610cf25760405192610d7460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185610cb1565b82845260208383010111610cac57816000926020809301838601378301015290565b919091604081840312610cac57604080519167ffffffffffffffff91830182811184821017610cf25760405282948135838111610cac5781610dd9918401610d21565b84526020820135928311610cac57602092610df49201610d21565b910152565b90816020910312610cac575173ffffffffffffffffffffffffffffffffffffffff81168103610cac5790565b919082519283825260005b848110610e6f5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610e30565b610ead916020610e9c8351604084526040840190610e25565b920151906020818403910152610e25565b90565b906004821015610ebd5752565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610cac57016020813591019167ffffffffffffffff8211610cac578136038313610cac57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b359067ffffffffffffffff82168203610cac57565b91908235833603907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818201811215610cac578401936040835284356040840152602094858101356060850152604081013573ffffffffffffffffffffffffffffffffffffffff8116809103610cac57611027916110169160808701526060810190610eec565b608060a087015260c0860191610f3c565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff21868301359101811215610cac5701918481830391015260e0810167ffffffffffffffff948561107785610f7b565b168352808401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811215610cac57840190808235920192878311610cac578260051b908136038513610cac5760e0868401528390528401610100908101939291906000908601845b8483106111755750505050505061115c610ead949561111b6111679361110d6040880188610eec565b908783036040890152610f3c565b908061112960608801610f7b565b16606086015261113b60808701610f7b565b16608085015261114e60a0860186610eec565b9085830360a0870152610f3c565b9260c0810190610eec565b9160c0818503910152610f3c565b90919293949584806111ba837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008c600196030187526111b48b87610eec565b90610f3c565b98019301930191949392906110e4565b90918092808252602080920191808260051b8601019484600080925b8584106111f857505050505050505090565b90919293949596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc185360301811215610c3557866001928682930190828061127c604061126f8680610eec565b9091808752860191610f3c565b9301359101529a019801969594019291906111e6565b73ffffffffffffffffffffffffffffffffffffffff6000541633036112b357565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fdfea164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca8300000000000000000000000003506d9a00fd1e2c9176454a267424285eda18ac000000000000000000000000b342a793be112dfb4526aafbfbe55bc3ef74c2a1000000000000000000000000a779126c3314385e9b0041072ea6a89d295fd1950000000000000000000000004fdaf3b68cf16e9fdd817c1d517d556085a4de57000000000000", + "nonce": "0x44", + "chainId": "0x3039" + }, + "additionalContracts": [ + { + "transactionType": "CREATE2", + "address": "0x7f64e16ec2557fc17150883c7dedc7e9ad936cdf", + "initCode": "0x60e03461017a57601f61149a38819003918201601f191683019291906001600160401b0384118385101761017f578160a0928492604096875283398101031261017a5761004b81610195565b9061005860208201610195565b90610064848201610195565b9061007d608061007660608401610195565b9201610195565b6001600160a01b0392831693909190841561016257836000549660018060a01b03199680888a1617600055828a5199167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3600180551695861561015357508316948515610142579083916080521660a0521660c0526003541617600355516112f090816101aa823960805181610c65015260a05181818161025f015281816104e70152610834015260c05181818161038e015281816104630152610acc0152f35b8651637d8ed95960e11b8152600490fd5b637bfd2e8360e01b8152600490fd5b8651631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b038216820361017a5756fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306433b1b14610c395750816315a96ae91461064a5781633f6746ce1461058c578163715018a61461050b57816372bdda54146104ba5781638da5cb5b14610487578163aa63810714610436578163d1ad17bf14610401578163f04e5bed146101b0578163f2fde38b146100e7575063f40e84711461009e57600080fd5b346100e35760206003193601126100e3576020918173ffffffffffffffffffffffffffffffffffffffff91826100d2610c89565b168152600285522054169051908152f35b5080fd5b9050346101ac5760206003193601126101ac57610102610c89565b9061010b611292565b73ffffffffffffffffffffffffffffffffffffffff80921692831561017d5750508254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b908460249251917f1e4fbdf7000000000000000000000000000000000000000000000000000000008352820152fd5b8280fd5b8383346100e35760606003193601126100e3576101cb610c89565b602435906044359460028610156103fd57849580156000146102eb575083949550610246602093945194859384937f7fddd60200000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102df579073ffffffffffffffffffffffffffffffffffffffff91602094916102b2575b50915b5191168152f35b6102d29150843d86116102d8575b6102ca8183610cb1565b810190610df9565b846102a8565b503d6102c0565b505051903d90823e3d90fd5b939493600114610318575b505050509073ffffffffffffffffffffffffffffffffffffffff6020926102ab565b602092939550610375855194859384937f7fddd60200000000000000000000000000000000000000000000000000000000855284016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102df579073ffffffffffffffffffffffffffffffffffffffff91602094916103e0575b509284806102f6565b6103f79150843d86116102d8576102ca8183610cb1565b846103d7565b8480fd5b5050346100e357816003193601126100e35760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5050346100e357816003193601126100e3576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5050346100e357816003193601126100e35773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b5050346100e357816003193601126100e3576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8334610589578060031936011261058957610524611292565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b9050346101ac5760206003193601126101ac576105a7610c89565b906105b0611292565b73ffffffffffffffffffffffffffffffffffffffff809216928315610624575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167fd8a42eaab83c563642705bc71a5905c29682aa5bf997aaa24b2ff7b3f32ed0b68380a380f35b517ffb1db2b2000000000000000000000000000000000000000000000000000000008152fd5b919050346101ac5760031960a081360112610c355782359267ffffffffffffffff91828511610c315736602386011215610c31578482013591838311610c2d576024918287019387019183830195368711610c2957843592818411610c255788818585019536030112610c2557604435828111610c215736602382011215610c21578084013591838311610c1d57878201918836918560051b010111610c1d576064359260028410156109435760029c6084359460019e8f5414610bf55760028f558e908061094757505060209a8b828b03126109135735868111610913576060910180990312610943578b51966060880188811087821117610917578d5289890135885260448901359b878d1015610913578b89019c8d5260648a0135968711610913578a8e978d9b01019061078091610d96565b998689019a8b5273ffffffffffffffffffffffffffffffffffffffff9a8b6003541697519d8e9a8b9a7f3dc48a34000000000000000000000000000000000000000000000000000000008c528b0160a090525160a48b01525160c48a016107e691610eb0565b5160e489016060905261010489016107fd91610e83565b9084898303019089015261081091610f90565b91868303016044870152610823926111ca565b9160648401526084830152038189857f0000000000000000000000000000000000000000000000000000000000000000165af1928315610909579573ffffffffffffffffffffffffffffffffffffffff9493929160209782946108e7575b5060029084169283835252838120337fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055337f08e9a1418653bd72d79048c016f319d58d60c2615929361e4c38adc69265c4c88280a4925b80555191168152f35b600291945061090290843d86116102d8576102ca8183610cb1565b9390610881565b84513d88823e3d90fd5b8f80fd5b50898f6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8d80fd5b9c98999a96929c14600014610bcd5760209a8b828c031261091357358281116109135760809101809a0312610943578b51966080880188811083821117610ba1578d52858a01358281116109135781876109a3928d0101610d96565b885260448a0135918211610b9d57856109be928b0101610d96565b998987019a8b5260648901359786891015610b9d578a988d96878a0191825260608a019b608401358c5273ffffffffffffffffffffffffffffffffffffffff9b8c6003541698519e8f9b8c9b7fb60bda49000000000000000000000000000000000000000000000000000000008d528c0160a090525160a48c01608090526101248c01610a4a91610e83565b9051908b81037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c0160c48d0152610a8091610e83565b925160e48b01610a8f91610eb0565b516101048a0152848983030190890152610aa891610f90565b91868303016044870152610abb926111ca565b9160648401526084830152038189857f0000000000000000000000000000000000000000000000000000000000000000165af1928315610909578673ffffffffffffffffffffffffffffffffffffffff95949392879260209995610b7b575b5060029085169384835252848120337fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790557f08e9a1418653bd72d79048c016f319d58d60c2615929361e4c38adc69265c4c8339180a4926108de565b6002919550610b9690853d87116102d8576102ca8183610cb1565b9490610b1a565b8e80fd5b50858f6041897f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b868d517fa3c0e0d1000000000000000000000000000000000000000000000000000000008152fd5b878e517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b8c80fd5b8b80fd5b8a80fd5b8980fd5b8680fd5b8580fd5b8380fd5b8490346100e357816003193601126100e35760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610cac57565b600080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610cf257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b81601f82011215610cac5780359067ffffffffffffffff8211610cf25760405192610d7460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185610cb1565b82845260208383010111610cac57816000926020809301838601378301015290565b919091604081840312610cac57604080519167ffffffffffffffff91830182811184821017610cf25760405282948135838111610cac5781610dd9918401610d21565b84526020820135928311610cac57602092610df49201610d21565b910152565b90816020910312610cac575173ffffffffffffffffffffffffffffffffffffffff81168103610cac5790565b919082519283825260005b848110610e6f5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610e30565b610ead916020610e9c8351604084526040840190610e25565b920151906020818403910152610e25565b90565b906004821015610ebd5752565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610cac57016020813591019167ffffffffffffffff8211610cac578136038313610cac57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b359067ffffffffffffffff82168203610cac57565b91908235833603907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818201811215610cac578401936040835284356040840152602094858101356060850152604081013573ffffffffffffffffffffffffffffffffffffffff8116809103610cac57611027916110169160808701526060810190610eec565b608060a087015260c0860191610f3c565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff21868301359101811215610cac5701918481830391015260e0810167ffffffffffffffff948561107785610f7b565b168352808401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811215610cac57840190808235920192878311610cac578260051b908136038513610cac5760e0868401528390528401610100908101939291906000908601845b8483106111755750505050505061115c610ead949561111b6111679361110d6040880188610eec565b908783036040890152610f3c565b908061112960608801610f7b565b16606086015261113b60808701610f7b565b16608085015261114e60a0860186610eec565b9085830360a0870152610f3c565b9260c0810190610eec565b9160c0818503910152610f3c565b90919293949584806111ba837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008c600196030187526111b48b87610eec565b90610f3c565b98019301930191949392906110e4565b90918092808252602080920191808260051b8601019484600080925b8584106111f857505050505050505090565b90919293949596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc185360301811215610c3557866001928682930190828061127c604061126f8680610eec565b9091808752860191610f3c565b9301359101529a019801969594019291906111e6565b73ffffffffffffffffffffffffffffffffffffffff6000541633036112b357565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fdfea164736f6c6343000819000a0000000000000000000000003565f2c0c305bbeeb0a433feaafacc4e8f1dca8300000000000000000000000003506d9a00fd1e2c9176454a267424285eda18ac000000000000000000000000b342a793be112dfb4526aafbfbe55bc3ef74c2a1000000000000000000000000a779126c3314385e9b0041072ea6a89d295fd1950000000000000000000000004fdaf3b68cf16e9fdd817c1d517d556085a4de57" + } + ], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x2c6ac", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xaffdfef61fa59ce8e56fc69b48db8e3e806a18d59dcf2da015370d9b71e2baf1", + "transactionIndex": "0x0", + "blockHash": "0x1d58c836d6294de7e14fc12b4df52cff1efa11aafa0d7523024d5e0f69a4429d", + "blockNumber": "0x1a7b7", + "gasUsed": "0x2c6ac", + "effectiveGasPrice": "0x8", + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": null, + "contractAddress": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x952d4", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6921bf89511ae24dea797d56c0f8b25cfcf87ea12918975dde3bdcf643a7d58d", + "transactionIndex": "0x0", + "blockHash": "0x4d3776d20c3fdbdda7cdf6c8450cad5fe243d9d4988c266ac92afdd5bfe3da55", + "blockNumber": "0x1a7b8", + "gasUsed": "0x952d4", + "effectiveGasPrice": "0x8", + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x45da0b", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x71351ba06c4e7c904b90ddae1192e04b8f5d53f8789bc7001f34fb13e88d80ab", + "transactionIndex": "0x0", + "blockHash": "0x72ca4f001426bd3854c6f28ffa01f02865136ca129da5a3464854b09e9f7bf95", + "blockNumber": "0x1a7ba", + "gasUsed": "0x45da0b", + "effectiveGasPrice": "0x8", + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x4f1638", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x8e0be03a943558f7822446da997c035ee27bdad3f88a391c2e2223c4632244fb", + "transactionIndex": "0x0", + "blockHash": "0xa589f259dd326b2b5922748143af5a3bd58ac7638fd9c302b7a7e633722231ff", + "blockNumber": "0x1a7bb", + "gasUsed": "0x4f1638", + "effectiveGasPrice": "0x8", + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x11e68f", + "logs": [ + { + "address": "0x7f64e16ec2557fc17150883c7dedc7e9ad936cdf", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b342a793be112dfb4526aafbfbe55bc3ef74c2a1" + ], + "data": "0x", + "blockHash": "0x5ff34a78ae2c23d2c78e4852fd4c56cd4d21e257e7c4c99798a235d44efa4538", + "blockNumber": "0x1a7bc", + "transactionHash": "0x3a1273cfe7d6faeb2efd98ea8c3d5f08ac19c72e06470fe5735ba5c43b6e9ef2", + "transactionIndex": "0x0", + "logIndex": "0x0", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000020000000000000000000000040000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000020000020000000000008001000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x3a1273cfe7d6faeb2efd98ea8c3d5f08ac19c72e06470fe5735ba5c43b6e9ef2", + "transactionIndex": "0x0", + "blockHash": "0x5ff34a78ae2c23d2c78e4852fd4c56cd4d21e257e7c4c99798a235d44efa4538", + "blockNumber": "0x1a7bc", + "gasUsed": "0x11e68f", + "effectiveGasPrice": "0x8", + "from": "0x6ea8ac1673402989e7b653ae4e83b54173719c30", + "to": "0xbd0197fc96a4aeb00620fd3e7fc9470c737ec126", + "contractAddress": null + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1737711959, + "chain": 12345, + "commit": "b0c6dc23" +} \ No newline at end of file diff --git a/src/orders/foundry.toml b/src/orders/foundry.toml new file mode 100644 index 0000000..e3a1718 --- /dev/null +++ b/src/orders/foundry.toml @@ -0,0 +1,33 @@ +# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config + +[profile.default] + auto_detect_solc = false + block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT + bytecode_hash = "none" + evm_version = "paris" + fuzz = { runs = 1_000 } + gas_reports = ["*"] + optimizer = true + optimizer_runs = 10_000 + out = "out" + script = "script" + solc = "0.8.25" + src = "src" + test = "test" + fs_permissions = [ + { access = "read-write", path = "./broadcast/Deploy.s.sol/"} + ] + +[profile.ci] + fuzz = { runs = 10_000 } + verbosity = 4 + +[fmt] + bracket_spacing = true + int_types = "long" + line_length = 120 + multiline_func_header = "all" + number_underscore = "thousands" + quote_style = "double" + tab_width = 4 + wrap_comments = true diff --git a/src/orders/mocks/MockAsyncPrecompile.sol b/src/orders/mocks/MockAsyncPrecompile.sol new file mode 100644 index 0000000..3343b7a --- /dev/null +++ b/src/orders/mocks/MockAsyncPrecompile.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { + Future, + FutureByIdResponse, + FutureResponse, + FuturesResponse, + FutureResult, + FutureVote, + IAsync, + PendingFuturesResponse +} from "../precompiles/async/IAsync.sol"; +import { Types } from "../precompiles/async/IAsync.sol"; + +contract MockAsyncPrecompile is IAsync { + uint64 public futuresCount = 0; + mapping(uint64 id => FutureByIdResponse output) public _futures; + mapping(address orderAddress => address orderCreator) public orders; + + function addFuture(string calldata handler, bytes calldata input) external returns (uint64 futureId) { + futureId = uint64(++futuresCount); + Future memory future = Future({ + id: futureId, + // solhint-disable-next-line + creator: tx.origin, + handler: handler, + input: input + }); + + FutureVote[] memory emptyVotes = new FutureVote[](0); + bytes memory emptySubmitter; + FutureResult memory futureResult = FutureResult({ id: futureId, output: input, submitter: emptySubmitter }); + FutureResponse memory futureResponse = + FutureResponse({ future: future, votes: emptyVotes, result: futureResult }); + _futures[futureId] = FutureByIdResponse({ futureResponse: futureResponse }); + } + + function futureById(uint64 futureId) external view returns (FutureByIdResponse memory response) { + response = _futures[futureId]; + } + + function futures(Types.PageRequest calldata, address) external pure returns (FuturesResponse memory) { + // solhint-disable-next-line + revert("Unimplemented"); + } + + function pendingFutures(Types.PageRequest calldata) external pure returns (PendingFuturesResponse memory) { + // solhint-disable-next-line + revert("Unimplemented"); + } +} diff --git a/src/orders/mocks/MockSlinkyPrecompile.sol b/src/orders/mocks/MockSlinkyPrecompile.sol new file mode 100644 index 0000000..f562c77 --- /dev/null +++ b/src/orders/mocks/MockSlinkyPrecompile.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { GetPriceResponse, QuotePrice, ISlinky } from "../precompiles/slinky/ISlinky.sol"; + +contract MockSlinkyPrecompile is ISlinky { + mapping(string base => mapping(string quote => uint256 price)) private prices; + + function getPrice( + string calldata base, + string calldata quote + ) + external + view + returns (GetPriceResponse memory response) + { + uint256 price = prices[base][quote]; + if (price == 0) { + string memory s1 = string.concat("no price / nonce reported for CurrencyPair: ", base); + string memory s2 = string.concat(s1, "/"); + string memory s3 = string.concat(s2, quote); + string memory s4 = string.concat(s3, ", the module is not tracking this CurrencyPair"); + revert(s4); + } + + QuotePrice memory quotePrice = QuotePrice({ blockHeight: 0, blockTimestamp: 0, price: price }); + + response = GetPriceResponse({ id: 0, nonce: 0, decimals: 9, price: quotePrice }); + } + + function setPrice(string calldata base, string calldata quote, uint256 price) external { + prices[base][quote] = price; + } +} diff --git a/src/orders/mocks/MockWardenPrecompile.sol b/src/orders/mocks/MockWardenPrecompile.sol new file mode 100644 index 0000000..04c2564 --- /dev/null +++ b/src/orders/mocks/MockWardenPrecompile.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { AddressesResponse, AddressType, BroadcastType, Key, KeyResponse } from "../precompiles/warden/IWarden.sol"; +import { Types } from "../precompiles/common/Types.sol"; + +contract MockWardenPrecompile { + mapping(uint64 keyId => KeyResponse keyResponse) private keys; + mapping(uint64 keyId => bool isGood) private goodKeys; + + function keyById(uint64, int32[] calldata) external pure returns (KeyResponse memory keyResponse) { + Key memory key; + AddressesResponse[] memory addresses = new AddressesResponse[](1); + addresses[0] = AddressesResponse({ + addressValue: "0x0000000000000000000000000000000000000000", + addressType: AddressType.Ethereum + }); + keyResponse = KeyResponse({ key: key, addresses: addresses }); + } + + function newSignRequest( + uint64 keyId, + bytes calldata, + bytes[] calldata, + bytes calldata, + Types.Coin[] calldata, + uint64, + uint64, + string calldata, + string calldata, + BroadcastType + ) + external + view + returns (bool isGood) + { + isGood = goodKeys[keyId]; + } + + function addKey(uint64 keyId, bool isGood) external { + goodKeys[keyId] = isGood; + } +} diff --git a/src/orders/package.json b/src/orders/package.json new file mode 100644 index 0000000..48d92a0 --- /dev/null +++ b/src/orders/package.json @@ -0,0 +1,27 @@ +{ + "name": "@wardenprotocol/orders", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "forge-std": "github:foundry-rs/forge-std#v1.8.1", + "prettier": "^3.0.0", + "solhint": "^3.6.2" + }, + "dependencies": { + "@0xsequence/create3": "https://github.com/0xsequence/create3#acc4703a21ec1d71dc2a99db088c4b1f467530fd", + "@openzeppelin/contracts": "^5.0.1" + }, + "scripts": { + "clean": "rm -rf cache out", + "build": "forge build src --via-ir", + "lint": "yarn run lint:sol && yarn run prettier:check", + "lint:sol": "forge fmt --check && yarn solhint \"{script,src,test}/**/*.sol\"", + "prettier:check": "prettier --check \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"", + "prettier:write": "prettier --write \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"", + "test": "forge test --via-ir", + "test:coverage": "forge coverage", + "test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage", + "deploy": "forge script script/Deploy.s.sol:Deploy --chain $CHAIN_ID --rpc-url $RPC_URL --broadcast -vvvv --via-ir --slow" + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" +} diff --git a/src/orders/precompiles/act/IAct.go b/src/orders/precompiles/act/IAct.go new file mode 100644 index 0000000..3173d0e --- /dev/null +++ b/src/orders/precompiles/act/IAct.go @@ -0,0 +1,1254 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package act + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// Action is an auto generated low-level Go binding around an user-defined struct. +type Action struct { + Id uint64 + Status uint8 + Msg TypesAnyType + Result TypesAnyType + Creator common.Address + TimeoutHeight uint64 + CreatedAt TypesTimestamp + UpdatedAt TypesTimestamp + ApproveExpression string + RejectExpression string + Mentions []common.Address + Votes []ActionVote +} + +// ActionByIdResponse is an auto generated low-level Go binding around an user-defined struct. +type ActionByIdResponse struct { + Action Action +} + +// ActionVote is an auto generated low-level Go binding around an user-defined struct. +type ActionVote struct { + Participant common.Address + VotedAt TypesTimestamp + VoteType uint8 +} + +// ActionsByAddressResponse is an auto generated low-level Go binding around an user-defined struct. +type ActionsByAddressResponse struct { + Pagination TypesPageResponse + Actions []Action +} + +// ActionsResponse is an auto generated low-level Go binding around an user-defined struct. +type ActionsResponse struct { + Pagination TypesPageResponse + Actions []Action +} + +// Template is an auto generated low-level Go binding around an user-defined struct. +type Template struct { + Id uint64 + Creator common.Address + Name string + Expression string +} + +// TemplateByIdResponse is an auto generated low-level Go binding around an user-defined struct. +type TemplateByIdResponse struct { + Template Template +} + +// TemplatesResponse is an auto generated low-level Go binding around an user-defined struct. +type TemplatesResponse struct { + Pagination TypesPageResponse + Templates []Template +} + +// TypesAnyType is an auto generated low-level Go binding around an user-defined struct. +type TypesAnyType struct { + TypeUrl string + Value []byte +} + +// TypesPageRequest is an auto generated low-level Go binding around an user-defined struct. +type TypesPageRequest struct { + Key []byte + Offset uint64 + Limit uint64 + CountTotal bool + Reverse bool +} + +// TypesPageResponse is an auto generated low-level Go binding around an user-defined struct. +type TypesPageResponse struct { + NextKey []byte + Total uint64 +} + +// TypesTimestamp is an auto generated low-level Go binding around an user-defined struct. +type TypesTimestamp struct { + Secs uint64 + Nanos uint64 +} + +// IActMetaData contains all meta data concerning the IAct contract. +var IActMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"author\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"enumActionStatus\",\"name\":\"previousStatus\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumActionStatus\",\"name\":\"newStatus\",\"type\":\"uint8\"}],\"name\":\"ActionStateChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"participant\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"enumVoteType\",\"name\":\"voteType\",\"type\":\"uint8\"}],\"name\":\"ActionVoted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"}],\"name\":\"CreateAction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"templateId\",\"type\":\"uint64\"}],\"name\":\"CreateTemplate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"author\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"templateId\",\"type\":\"uint64\"}],\"name\":\"UpdateTemplate\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"}],\"name\":\"actionById\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"enumActionStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"typeUrl\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.AnyType\",\"name\":\"msg\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"typeUrl\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.AnyType\",\"name\":\"result\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"timeoutHeight\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"createdAt\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"updatedAt\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"approveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"rejectExpression\",\"type\":\"string\"},{\"internalType\":\"address[]\",\"name\":\"mentions\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"participant\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"votedAt\",\"type\":\"tuple\"},{\"internalType\":\"enumVoteType\",\"name\":\"voteType\",\"type\":\"uint8\"}],\"internalType\":\"structActionVote[]\",\"name\":\"votes\",\"type\":\"tuple[]\"}],\"internalType\":\"structAction\",\"name\":\"action\",\"type\":\"tuple\"}],\"internalType\":\"structActionByIdResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"actions\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"enumActionStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"typeUrl\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.AnyType\",\"name\":\"msg\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"typeUrl\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.AnyType\",\"name\":\"result\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"timeoutHeight\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"createdAt\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"updatedAt\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"approveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"rejectExpression\",\"type\":\"string\"},{\"internalType\":\"address[]\",\"name\":\"mentions\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"participant\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"votedAt\",\"type\":\"tuple\"},{\"internalType\":\"enumVoteType\",\"name\":\"voteType\",\"type\":\"uint8\"}],\"internalType\":\"structActionVote[]\",\"name\":\"votes\",\"type\":\"tuple[]\"}],\"internalType\":\"structAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"structActionsResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"enumActionStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"actionsByAddress\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"enumActionStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"typeUrl\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.AnyType\",\"name\":\"msg\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"typeUrl\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.AnyType\",\"name\":\"result\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"timeoutHeight\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"createdAt\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"updatedAt\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"approveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"rejectExpression\",\"type\":\"string\"},{\"internalType\":\"address[]\",\"name\":\"mentions\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"participant\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"secs\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nanos\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.Timestamp\",\"name\":\"votedAt\",\"type\":\"tuple\"},{\"internalType\":\"enumVoteType\",\"name\":\"voteType\",\"type\":\"uint8\"}],\"internalType\":\"structActionVote[]\",\"name\":\"votes\",\"type\":\"tuple[]\"}],\"internalType\":\"structAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"structActionsByAddressResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"}],\"name\":\"checkAction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"definition\",\"type\":\"string\"}],\"name\":\"newTemplate\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"}],\"name\":\"revokeAction\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"templateId\",\"type\":\"uint64\"}],\"name\":\"templateById\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expression\",\"type\":\"string\"}],\"internalType\":\"structTemplate\",\"name\":\"template\",\"type\":\"tuple\"}],\"internalType\":\"structTemplateByIdResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"}],\"name\":\"templates\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expression\",\"type\":\"string\"}],\"internalType\":\"structTemplate[]\",\"name\":\"templates\",\"type\":\"tuple[]\"}],\"internalType\":\"structTemplatesResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"templateId\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"definition\",\"type\":\"string\"}],\"name\":\"updateTemplate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"actionId\",\"type\":\"uint64\"},{\"internalType\":\"enumVoteType\",\"name\":\"voteType\",\"type\":\"uint8\"}],\"name\":\"voteForAction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IActABI is the input ABI used to generate the binding from. +// Deprecated: Use IActMetaData.ABI instead. +var IActABI = IActMetaData.ABI + +// IAct is an auto generated Go binding around an Ethereum contract. +type IAct struct { + IActCaller // Read-only binding to the contract + IActTransactor // Write-only binding to the contract + IActFilterer // Log filterer for contract events +} + +// IActCaller is an auto generated read-only Go binding around an Ethereum contract. +type IActCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IActTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IActTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IActFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IActFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IActSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IActSession struct { + Contract *IAct // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IActCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IActCallerSession struct { + Contract *IActCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IActTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IActTransactorSession struct { + Contract *IActTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IActRaw is an auto generated low-level Go binding around an Ethereum contract. +type IActRaw struct { + Contract *IAct // Generic contract binding to access the raw methods on +} + +// IActCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IActCallerRaw struct { + Contract *IActCaller // Generic read-only contract binding to access the raw methods on +} + +// IActTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IActTransactorRaw struct { + Contract *IActTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIAct creates a new instance of IAct, bound to a specific deployed contract. +func NewIAct(address common.Address, backend bind.ContractBackend) (*IAct, error) { + contract, err := bindIAct(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IAct{IActCaller: IActCaller{contract: contract}, IActTransactor: IActTransactor{contract: contract}, IActFilterer: IActFilterer{contract: contract}}, nil +} + +// NewIActCaller creates a new read-only instance of IAct, bound to a specific deployed contract. +func NewIActCaller(address common.Address, caller bind.ContractCaller) (*IActCaller, error) { + contract, err := bindIAct(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IActCaller{contract: contract}, nil +} + +// NewIActTransactor creates a new write-only instance of IAct, bound to a specific deployed contract. +func NewIActTransactor(address common.Address, transactor bind.ContractTransactor) (*IActTransactor, error) { + contract, err := bindIAct(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IActTransactor{contract: contract}, nil +} + +// NewIActFilterer creates a new log filterer instance of IAct, bound to a specific deployed contract. +func NewIActFilterer(address common.Address, filterer bind.ContractFilterer) (*IActFilterer, error) { + contract, err := bindIAct(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IActFilterer{contract: contract}, nil +} + +// bindIAct binds a generic wrapper to an already deployed contract. +func bindIAct(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(IActABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAct *IActRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAct.Contract.IActCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAct *IActRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAct.Contract.IActTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IAct *IActRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAct.Contract.IActTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAct *IActCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAct.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAct *IActTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAct.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IAct *IActTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAct.Contract.contract.Transact(opts, method, params...) +} + +// ActionById is a free data retrieval call binding the contract method 0x51619ef0. +// +// Solidity: function actionById(uint64 actionId) view returns(((uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])) response) +func (_IAct *IActCaller) ActionById(opts *bind.CallOpts, actionId uint64) (ActionByIdResponse, error) { + var out []interface{} + err := _IAct.contract.Call(opts, &out, "actionById", actionId) + + if err != nil { + return *new(ActionByIdResponse), err + } + + out0 := *abi.ConvertType(out[0], new(ActionByIdResponse)).(*ActionByIdResponse) + + return out0, err + +} + +// ActionById is a free data retrieval call binding the contract method 0x51619ef0. +// +// Solidity: function actionById(uint64 actionId) view returns(((uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])) response) +func (_IAct *IActSession) ActionById(actionId uint64) (ActionByIdResponse, error) { + return _IAct.Contract.ActionById(&_IAct.CallOpts, actionId) +} + +// ActionById is a free data retrieval call binding the contract method 0x51619ef0. +// +// Solidity: function actionById(uint64 actionId) view returns(((uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])) response) +func (_IAct *IActCallerSession) ActionById(actionId uint64) (ActionByIdResponse, error) { + return _IAct.Contract.ActionById(&_IAct.CallOpts, actionId) +} + +// Actions is a free data retrieval call binding the contract method 0x9e9d1e27. +// +// Solidity: function actions((bytes,uint64,uint64,bool,bool) pagination) view returns(((bytes,uint64),(uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])[]) response) +func (_IAct *IActCaller) Actions(opts *bind.CallOpts, pagination TypesPageRequest) (ActionsResponse, error) { + var out []interface{} + err := _IAct.contract.Call(opts, &out, "actions", pagination) + + if err != nil { + return *new(ActionsResponse), err + } + + out0 := *abi.ConvertType(out[0], new(ActionsResponse)).(*ActionsResponse) + + return out0, err + +} + +// Actions is a free data retrieval call binding the contract method 0x9e9d1e27. +// +// Solidity: function actions((bytes,uint64,uint64,bool,bool) pagination) view returns(((bytes,uint64),(uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])[]) response) +func (_IAct *IActSession) Actions(pagination TypesPageRequest) (ActionsResponse, error) { + return _IAct.Contract.Actions(&_IAct.CallOpts, pagination) +} + +// Actions is a free data retrieval call binding the contract method 0x9e9d1e27. +// +// Solidity: function actions((bytes,uint64,uint64,bool,bool) pagination) view returns(((bytes,uint64),(uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])[]) response) +func (_IAct *IActCallerSession) Actions(pagination TypesPageRequest) (ActionsResponse, error) { + return _IAct.Contract.Actions(&_IAct.CallOpts, pagination) +} + +// ActionsByAddress is a free data retrieval call binding the contract method 0x589d42b6. +// +// Solidity: function actionsByAddress((bytes,uint64,uint64,bool,bool) pagination, address addr, uint8 status) view returns(((bytes,uint64),(uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])[]) response) +func (_IAct *IActCaller) ActionsByAddress(opts *bind.CallOpts, pagination TypesPageRequest, addr common.Address, status uint8) (ActionsByAddressResponse, error) { + var out []interface{} + err := _IAct.contract.Call(opts, &out, "actionsByAddress", pagination, addr, status) + + if err != nil { + return *new(ActionsByAddressResponse), err + } + + out0 := *abi.ConvertType(out[0], new(ActionsByAddressResponse)).(*ActionsByAddressResponse) + + return out0, err + +} + +// ActionsByAddress is a free data retrieval call binding the contract method 0x589d42b6. +// +// Solidity: function actionsByAddress((bytes,uint64,uint64,bool,bool) pagination, address addr, uint8 status) view returns(((bytes,uint64),(uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])[]) response) +func (_IAct *IActSession) ActionsByAddress(pagination TypesPageRequest, addr common.Address, status uint8) (ActionsByAddressResponse, error) { + return _IAct.Contract.ActionsByAddress(&_IAct.CallOpts, pagination, addr, status) +} + +// ActionsByAddress is a free data retrieval call binding the contract method 0x589d42b6. +// +// Solidity: function actionsByAddress((bytes,uint64,uint64,bool,bool) pagination, address addr, uint8 status) view returns(((bytes,uint64),(uint64,uint8,(string,bytes),(string,bytes),address,uint64,(uint64,uint64),(uint64,uint64),string,string,address[],(address,(uint64,uint64),uint8)[])[]) response) +func (_IAct *IActCallerSession) ActionsByAddress(pagination TypesPageRequest, addr common.Address, status uint8) (ActionsByAddressResponse, error) { + return _IAct.Contract.ActionsByAddress(&_IAct.CallOpts, pagination, addr, status) +} + +// TemplateById is a free data retrieval call binding the contract method 0x161f1e48. +// +// Solidity: function templateById(uint64 templateId) view returns(((uint64,address,string,string)) response) +func (_IAct *IActCaller) TemplateById(opts *bind.CallOpts, templateId uint64) (TemplateByIdResponse, error) { + var out []interface{} + err := _IAct.contract.Call(opts, &out, "templateById", templateId) + + if err != nil { + return *new(TemplateByIdResponse), err + } + + out0 := *abi.ConvertType(out[0], new(TemplateByIdResponse)).(*TemplateByIdResponse) + + return out0, err + +} + +// TemplateById is a free data retrieval call binding the contract method 0x161f1e48. +// +// Solidity: function templateById(uint64 templateId) view returns(((uint64,address,string,string)) response) +func (_IAct *IActSession) TemplateById(templateId uint64) (TemplateByIdResponse, error) { + return _IAct.Contract.TemplateById(&_IAct.CallOpts, templateId) +} + +// TemplateById is a free data retrieval call binding the contract method 0x161f1e48. +// +// Solidity: function templateById(uint64 templateId) view returns(((uint64,address,string,string)) response) +func (_IAct *IActCallerSession) TemplateById(templateId uint64) (TemplateByIdResponse, error) { + return _IAct.Contract.TemplateById(&_IAct.CallOpts, templateId) +} + +// Templates is a free data retrieval call binding the contract method 0x236d0b9f. +// +// Solidity: function templates((bytes,uint64,uint64,bool,bool) pagination, address creator) view returns(((bytes,uint64),(uint64,address,string,string)[]) response) +func (_IAct *IActCaller) Templates(opts *bind.CallOpts, pagination TypesPageRequest, creator common.Address) (TemplatesResponse, error) { + var out []interface{} + err := _IAct.contract.Call(opts, &out, "templates", pagination, creator) + + if err != nil { + return *new(TemplatesResponse), err + } + + out0 := *abi.ConvertType(out[0], new(TemplatesResponse)).(*TemplatesResponse) + + return out0, err + +} + +// Templates is a free data retrieval call binding the contract method 0x236d0b9f. +// +// Solidity: function templates((bytes,uint64,uint64,bool,bool) pagination, address creator) view returns(((bytes,uint64),(uint64,address,string,string)[]) response) +func (_IAct *IActSession) Templates(pagination TypesPageRequest, creator common.Address) (TemplatesResponse, error) { + return _IAct.Contract.Templates(&_IAct.CallOpts, pagination, creator) +} + +// Templates is a free data retrieval call binding the contract method 0x236d0b9f. +// +// Solidity: function templates((bytes,uint64,uint64,bool,bool) pagination, address creator) view returns(((bytes,uint64),(uint64,address,string,string)[]) response) +func (_IAct *IActCallerSession) Templates(pagination TypesPageRequest, creator common.Address) (TemplatesResponse, error) { + return _IAct.Contract.Templates(&_IAct.CallOpts, pagination, creator) +} + +// CheckAction is a paid mutator transaction binding the contract method 0x737c52b5. +// +// Solidity: function checkAction(uint64 actionId) returns(string) +func (_IAct *IActTransactor) CheckAction(opts *bind.TransactOpts, actionId uint64) (*types.Transaction, error) { + return _IAct.contract.Transact(opts, "checkAction", actionId) +} + +// CheckAction is a paid mutator transaction binding the contract method 0x737c52b5. +// +// Solidity: function checkAction(uint64 actionId) returns(string) +func (_IAct *IActSession) CheckAction(actionId uint64) (*types.Transaction, error) { + return _IAct.Contract.CheckAction(&_IAct.TransactOpts, actionId) +} + +// CheckAction is a paid mutator transaction binding the contract method 0x737c52b5. +// +// Solidity: function checkAction(uint64 actionId) returns(string) +func (_IAct *IActTransactorSession) CheckAction(actionId uint64) (*types.Transaction, error) { + return _IAct.Contract.CheckAction(&_IAct.TransactOpts, actionId) +} + +// NewTemplate is a paid mutator transaction binding the contract method 0x20748349. +// +// Solidity: function newTemplate(string name, string definition) returns(uint64) +func (_IAct *IActTransactor) NewTemplate(opts *bind.TransactOpts, name string, definition string) (*types.Transaction, error) { + return _IAct.contract.Transact(opts, "newTemplate", name, definition) +} + +// NewTemplate is a paid mutator transaction binding the contract method 0x20748349. +// +// Solidity: function newTemplate(string name, string definition) returns(uint64) +func (_IAct *IActSession) NewTemplate(name string, definition string) (*types.Transaction, error) { + return _IAct.Contract.NewTemplate(&_IAct.TransactOpts, name, definition) +} + +// NewTemplate is a paid mutator transaction binding the contract method 0x20748349. +// +// Solidity: function newTemplate(string name, string definition) returns(uint64) +func (_IAct *IActTransactorSession) NewTemplate(name string, definition string) (*types.Transaction, error) { + return _IAct.Contract.NewTemplate(&_IAct.TransactOpts, name, definition) +} + +// RevokeAction is a paid mutator transaction binding the contract method 0xb8fcbfef. +// +// Solidity: function revokeAction(uint64 actionId) returns(bool) +func (_IAct *IActTransactor) RevokeAction(opts *bind.TransactOpts, actionId uint64) (*types.Transaction, error) { + return _IAct.contract.Transact(opts, "revokeAction", actionId) +} + +// RevokeAction is a paid mutator transaction binding the contract method 0xb8fcbfef. +// +// Solidity: function revokeAction(uint64 actionId) returns(bool) +func (_IAct *IActSession) RevokeAction(actionId uint64) (*types.Transaction, error) { + return _IAct.Contract.RevokeAction(&_IAct.TransactOpts, actionId) +} + +// RevokeAction is a paid mutator transaction binding the contract method 0xb8fcbfef. +// +// Solidity: function revokeAction(uint64 actionId) returns(bool) +func (_IAct *IActTransactorSession) RevokeAction(actionId uint64) (*types.Transaction, error) { + return _IAct.Contract.RevokeAction(&_IAct.TransactOpts, actionId) +} + +// UpdateTemplate is a paid mutator transaction binding the contract method 0xcb7391d5. +// +// Solidity: function updateTemplate(uint64 templateId, string name, string definition) returns(bool) +func (_IAct *IActTransactor) UpdateTemplate(opts *bind.TransactOpts, templateId uint64, name string, definition string) (*types.Transaction, error) { + return _IAct.contract.Transact(opts, "updateTemplate", templateId, name, definition) +} + +// UpdateTemplate is a paid mutator transaction binding the contract method 0xcb7391d5. +// +// Solidity: function updateTemplate(uint64 templateId, string name, string definition) returns(bool) +func (_IAct *IActSession) UpdateTemplate(templateId uint64, name string, definition string) (*types.Transaction, error) { + return _IAct.Contract.UpdateTemplate(&_IAct.TransactOpts, templateId, name, definition) +} + +// UpdateTemplate is a paid mutator transaction binding the contract method 0xcb7391d5. +// +// Solidity: function updateTemplate(uint64 templateId, string name, string definition) returns(bool) +func (_IAct *IActTransactorSession) UpdateTemplate(templateId uint64, name string, definition string) (*types.Transaction, error) { + return _IAct.Contract.UpdateTemplate(&_IAct.TransactOpts, templateId, name, definition) +} + +// VoteForAction is a paid mutator transaction binding the contract method 0xaa9b484b. +// +// Solidity: function voteForAction(uint64 actionId, uint8 voteType) returns(string) +func (_IAct *IActTransactor) VoteForAction(opts *bind.TransactOpts, actionId uint64, voteType uint8) (*types.Transaction, error) { + return _IAct.contract.Transact(opts, "voteForAction", actionId, voteType) +} + +// VoteForAction is a paid mutator transaction binding the contract method 0xaa9b484b. +// +// Solidity: function voteForAction(uint64 actionId, uint8 voteType) returns(string) +func (_IAct *IActSession) VoteForAction(actionId uint64, voteType uint8) (*types.Transaction, error) { + return _IAct.Contract.VoteForAction(&_IAct.TransactOpts, actionId, voteType) +} + +// VoteForAction is a paid mutator transaction binding the contract method 0xaa9b484b. +// +// Solidity: function voteForAction(uint64 actionId, uint8 voteType) returns(string) +func (_IAct *IActTransactorSession) VoteForAction(actionId uint64, voteType uint8) (*types.Transaction, error) { + return _IAct.Contract.VoteForAction(&_IAct.TransactOpts, actionId, voteType) +} + +// IActActionStateChangeIterator is returned from FilterActionStateChange and is used to iterate over the raw logs and unpacked data for ActionStateChange events raised by the IAct contract. +type IActActionStateChangeIterator struct { + Event *IActActionStateChange // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IActActionStateChangeIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IActActionStateChange) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IActActionStateChange) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IActActionStateChangeIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IActActionStateChangeIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IActActionStateChange represents a ActionStateChange event raised by the IAct contract. +type IActActionStateChange struct { + Author common.Address + ActionId uint64 + PreviousStatus uint8 + NewStatus uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterActionStateChange is a free log retrieval operation binding the contract event 0x4ec265596164182b2025b3bd681450aef02c2b9487924e1b6ac3785f9c4636dc. +// +// Solidity: event ActionStateChange(address indexed author, uint64 actionId, uint8 previousStatus, uint8 newStatus) +func (_IAct *IActFilterer) FilterActionStateChange(opts *bind.FilterOpts, author []common.Address) (*IActActionStateChangeIterator, error) { + + var authorRule []interface{} + for _, authorItem := range author { + authorRule = append(authorRule, authorItem) + } + + logs, sub, err := _IAct.contract.FilterLogs(opts, "ActionStateChange", authorRule) + if err != nil { + return nil, err + } + return &IActActionStateChangeIterator{contract: _IAct.contract, event: "ActionStateChange", logs: logs, sub: sub}, nil +} + +// WatchActionStateChange is a free log subscription operation binding the contract event 0x4ec265596164182b2025b3bd681450aef02c2b9487924e1b6ac3785f9c4636dc. +// +// Solidity: event ActionStateChange(address indexed author, uint64 actionId, uint8 previousStatus, uint8 newStatus) +func (_IAct *IActFilterer) WatchActionStateChange(opts *bind.WatchOpts, sink chan<- *IActActionStateChange, author []common.Address) (event.Subscription, error) { + + var authorRule []interface{} + for _, authorItem := range author { + authorRule = append(authorRule, authorItem) + } + + logs, sub, err := _IAct.contract.WatchLogs(opts, "ActionStateChange", authorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IActActionStateChange) + if err := _IAct.contract.UnpackLog(event, "ActionStateChange", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseActionStateChange is a log parse operation binding the contract event 0x4ec265596164182b2025b3bd681450aef02c2b9487924e1b6ac3785f9c4636dc. +// +// Solidity: event ActionStateChange(address indexed author, uint64 actionId, uint8 previousStatus, uint8 newStatus) +func (_IAct *IActFilterer) ParseActionStateChange(log types.Log) (*IActActionStateChange, error) { + event := new(IActActionStateChange) + if err := _IAct.contract.UnpackLog(event, "ActionStateChange", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IActActionVotedIterator is returned from FilterActionVoted and is used to iterate over the raw logs and unpacked data for ActionVoted events raised by the IAct contract. +type IActActionVotedIterator struct { + Event *IActActionVoted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IActActionVotedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IActActionVoted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IActActionVoted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IActActionVotedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IActActionVotedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IActActionVoted represents a ActionVoted event raised by the IAct contract. +type IActActionVoted struct { + Participant common.Address + ActionId uint64 + VoteType uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterActionVoted is a free log retrieval operation binding the contract event 0x39db7e0304bfea692e054bba473c1d34175e298180e0c64dc10db63bd6449ae3. +// +// Solidity: event ActionVoted(address indexed participant, uint64 actionId, uint8 voteType) +func (_IAct *IActFilterer) FilterActionVoted(opts *bind.FilterOpts, participant []common.Address) (*IActActionVotedIterator, error) { + + var participantRule []interface{} + for _, participantItem := range participant { + participantRule = append(participantRule, participantItem) + } + + logs, sub, err := _IAct.contract.FilterLogs(opts, "ActionVoted", participantRule) + if err != nil { + return nil, err + } + return &IActActionVotedIterator{contract: _IAct.contract, event: "ActionVoted", logs: logs, sub: sub}, nil +} + +// WatchActionVoted is a free log subscription operation binding the contract event 0x39db7e0304bfea692e054bba473c1d34175e298180e0c64dc10db63bd6449ae3. +// +// Solidity: event ActionVoted(address indexed participant, uint64 actionId, uint8 voteType) +func (_IAct *IActFilterer) WatchActionVoted(opts *bind.WatchOpts, sink chan<- *IActActionVoted, participant []common.Address) (event.Subscription, error) { + + var participantRule []interface{} + for _, participantItem := range participant { + participantRule = append(participantRule, participantItem) + } + + logs, sub, err := _IAct.contract.WatchLogs(opts, "ActionVoted", participantRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IActActionVoted) + if err := _IAct.contract.UnpackLog(event, "ActionVoted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseActionVoted is a log parse operation binding the contract event 0x39db7e0304bfea692e054bba473c1d34175e298180e0c64dc10db63bd6449ae3. +// +// Solidity: event ActionVoted(address indexed participant, uint64 actionId, uint8 voteType) +func (_IAct *IActFilterer) ParseActionVoted(log types.Log) (*IActActionVoted, error) { + event := new(IActActionVoted) + if err := _IAct.contract.UnpackLog(event, "ActionVoted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IActCreateActionIterator is returned from FilterCreateAction and is used to iterate over the raw logs and unpacked data for CreateAction events raised by the IAct contract. +type IActCreateActionIterator struct { + Event *IActCreateAction // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IActCreateActionIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IActCreateAction) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IActCreateAction) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IActCreateActionIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IActCreateActionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IActCreateAction represents a CreateAction event raised by the IAct contract. +type IActCreateAction struct { + Creator common.Address + ActionId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCreateAction is a free log retrieval operation binding the contract event 0xadae3ff0cdd6a7009cbfd8df0000b91dfa31585868d4afda8b0aff24c0e6c075. +// +// Solidity: event CreateAction(address indexed creator, uint64 actionId) +func (_IAct *IActFilterer) FilterCreateAction(opts *bind.FilterOpts, creator []common.Address) (*IActCreateActionIterator, error) { + + var creatorRule []interface{} + for _, creatorItem := range creator { + creatorRule = append(creatorRule, creatorItem) + } + + logs, sub, err := _IAct.contract.FilterLogs(opts, "CreateAction", creatorRule) + if err != nil { + return nil, err + } + return &IActCreateActionIterator{contract: _IAct.contract, event: "CreateAction", logs: logs, sub: sub}, nil +} + +// WatchCreateAction is a free log subscription operation binding the contract event 0xadae3ff0cdd6a7009cbfd8df0000b91dfa31585868d4afda8b0aff24c0e6c075. +// +// Solidity: event CreateAction(address indexed creator, uint64 actionId) +func (_IAct *IActFilterer) WatchCreateAction(opts *bind.WatchOpts, sink chan<- *IActCreateAction, creator []common.Address) (event.Subscription, error) { + + var creatorRule []interface{} + for _, creatorItem := range creator { + creatorRule = append(creatorRule, creatorItem) + } + + logs, sub, err := _IAct.contract.WatchLogs(opts, "CreateAction", creatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IActCreateAction) + if err := _IAct.contract.UnpackLog(event, "CreateAction", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCreateAction is a log parse operation binding the contract event 0xadae3ff0cdd6a7009cbfd8df0000b91dfa31585868d4afda8b0aff24c0e6c075. +// +// Solidity: event CreateAction(address indexed creator, uint64 actionId) +func (_IAct *IActFilterer) ParseCreateAction(log types.Log) (*IActCreateAction, error) { + event := new(IActCreateAction) + if err := _IAct.contract.UnpackLog(event, "CreateAction", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IActCreateTemplateIterator is returned from FilterCreateTemplate and is used to iterate over the raw logs and unpacked data for CreateTemplate events raised by the IAct contract. +type IActCreateTemplateIterator struct { + Event *IActCreateTemplate // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IActCreateTemplateIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IActCreateTemplate) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IActCreateTemplate) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IActCreateTemplateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IActCreateTemplateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IActCreateTemplate represents a CreateTemplate event raised by the IAct contract. +type IActCreateTemplate struct { + Creator common.Address + TemplateId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCreateTemplate is a free log retrieval operation binding the contract event 0x1c8026eaa08d75eaeabd1b3a5f4b53660b24c2ccd983f1300121ce50f9755ead. +// +// Solidity: event CreateTemplate(address indexed creator, uint64 templateId) +func (_IAct *IActFilterer) FilterCreateTemplate(opts *bind.FilterOpts, creator []common.Address) (*IActCreateTemplateIterator, error) { + + var creatorRule []interface{} + for _, creatorItem := range creator { + creatorRule = append(creatorRule, creatorItem) + } + + logs, sub, err := _IAct.contract.FilterLogs(opts, "CreateTemplate", creatorRule) + if err != nil { + return nil, err + } + return &IActCreateTemplateIterator{contract: _IAct.contract, event: "CreateTemplate", logs: logs, sub: sub}, nil +} + +// WatchCreateTemplate is a free log subscription operation binding the contract event 0x1c8026eaa08d75eaeabd1b3a5f4b53660b24c2ccd983f1300121ce50f9755ead. +// +// Solidity: event CreateTemplate(address indexed creator, uint64 templateId) +func (_IAct *IActFilterer) WatchCreateTemplate(opts *bind.WatchOpts, sink chan<- *IActCreateTemplate, creator []common.Address) (event.Subscription, error) { + + var creatorRule []interface{} + for _, creatorItem := range creator { + creatorRule = append(creatorRule, creatorItem) + } + + logs, sub, err := _IAct.contract.WatchLogs(opts, "CreateTemplate", creatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IActCreateTemplate) + if err := _IAct.contract.UnpackLog(event, "CreateTemplate", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCreateTemplate is a log parse operation binding the contract event 0x1c8026eaa08d75eaeabd1b3a5f4b53660b24c2ccd983f1300121ce50f9755ead. +// +// Solidity: event CreateTemplate(address indexed creator, uint64 templateId) +func (_IAct *IActFilterer) ParseCreateTemplate(log types.Log) (*IActCreateTemplate, error) { + event := new(IActCreateTemplate) + if err := _IAct.contract.UnpackLog(event, "CreateTemplate", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IActUpdateTemplateIterator is returned from FilterUpdateTemplate and is used to iterate over the raw logs and unpacked data for UpdateTemplate events raised by the IAct contract. +type IActUpdateTemplateIterator struct { + Event *IActUpdateTemplate // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IActUpdateTemplateIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IActUpdateTemplate) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IActUpdateTemplate) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IActUpdateTemplateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IActUpdateTemplateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IActUpdateTemplate represents a UpdateTemplate event raised by the IAct contract. +type IActUpdateTemplate struct { + Author common.Address + TemplateId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdateTemplate is a free log retrieval operation binding the contract event 0x208e43824ec2e0ac2f091a72bb6aaf6f69aa0f522624bef02e403b80a29d1acd. +// +// Solidity: event UpdateTemplate(address indexed author, uint64 templateId) +func (_IAct *IActFilterer) FilterUpdateTemplate(opts *bind.FilterOpts, author []common.Address) (*IActUpdateTemplateIterator, error) { + + var authorRule []interface{} + for _, authorItem := range author { + authorRule = append(authorRule, authorItem) + } + + logs, sub, err := _IAct.contract.FilterLogs(opts, "UpdateTemplate", authorRule) + if err != nil { + return nil, err + } + return &IActUpdateTemplateIterator{contract: _IAct.contract, event: "UpdateTemplate", logs: logs, sub: sub}, nil +} + +// WatchUpdateTemplate is a free log subscription operation binding the contract event 0x208e43824ec2e0ac2f091a72bb6aaf6f69aa0f522624bef02e403b80a29d1acd. +// +// Solidity: event UpdateTemplate(address indexed author, uint64 templateId) +func (_IAct *IActFilterer) WatchUpdateTemplate(opts *bind.WatchOpts, sink chan<- *IActUpdateTemplate, author []common.Address) (event.Subscription, error) { + + var authorRule []interface{} + for _, authorItem := range author { + authorRule = append(authorRule, authorItem) + } + + logs, sub, err := _IAct.contract.WatchLogs(opts, "UpdateTemplate", authorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IActUpdateTemplate) + if err := _IAct.contract.UnpackLog(event, "UpdateTemplate", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpdateTemplate is a log parse operation binding the contract event 0x208e43824ec2e0ac2f091a72bb6aaf6f69aa0f522624bef02e403b80a29d1acd. +// +// Solidity: event UpdateTemplate(address indexed author, uint64 templateId) +func (_IAct *IActFilterer) ParseUpdateTemplate(log types.Log) (*IActUpdateTemplate, error) { + event := new(IActUpdateTemplate) + if err := _IAct.contract.UnpackLog(event, "UpdateTemplate", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/src/orders/precompiles/act/IAct.sol b/src/orders/precompiles/act/IAct.sol new file mode 100644 index 0000000..98d664a --- /dev/null +++ b/src/orders/precompiles/act/IAct.sol @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.18; + +import "../common/Types.sol"; + +/// @dev The IAct contract's address. +address constant IACT_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000901; + +/// @dev The IAct contract's instance. +IAct constant IACT_CONTRACT = IAct(IACT_PRECOMPILE_ADDRESS); + +enum ActionStatus { Unspecified, Pending, Completed, Revoked, Timeout } +enum VoteType { None, Approve, Reject } + +struct ActionVote { + address participant; + Types.Timestamp votedAt; + VoteType voteType; +} + +struct Action { + uint64 id; + ActionStatus status; + Types.AnyType msg; + Types.AnyType result; + address creator; + uint64 timeoutHeight; + Types.Timestamp createdAt; + Types.Timestamp updatedAt; + string approveExpression; + string rejectExpression; + address[] mentions; + ActionVote[] votes; +} + +struct ActionsResponse { + Types.PageResponse pagination; + Action[] actions; +} + +struct ActionByIdResponse { + Action action; +} + +struct ActionsByAddressResponse { + Types.PageResponse pagination; + Action[] actions; +} + +struct Template { + uint64 id; + address creator; + string name; + string expression; +} + +struct TemplatesResponse { + Types.PageResponse pagination; + Template[] templates; +} + +struct TemplateByIdResponse { + Template template; +} + +/** + * @author Act Team + * @title x/act Interface + * @dev The interface through which users and solidity contracts will interact with x/act. + * @custom:address 0x0000000000000000000000000000000000000901 + */ +interface IAct { + /// @dev Defines a method to check an action. + /// @param actionId The action id + /// @return action status + function checkAction(uint64 actionId) external returns (string memory); + + /// @dev Defines a method to create a new template. + /// @param name The template name + /// @param definition The template definition + /// @return template id + function newTemplate( + string calldata name, + string calldata definition + ) external returns (uint64); + + /// @dev Defines a method to revoke an action. + /// @param actionId The id of the action + /// @return true If execution was successful + function revokeAction(uint64 actionId) external returns (bool); + + /// @dev Defines a method to update a template. + /// @param templateId The id of the template + /// @param name The template name + /// @param definition The template definition + /// @return true If execution was successful + function updateTemplate( + uint64 templateId, + string calldata name, + string calldata definition + ) external returns (bool); + + /// @dev Defines a method to vote for an action. + /// @param actionId The id of the action + /// @param voteType The type of the vote + /// @return action status + function voteForAction( + uint64 actionId, + VoteType voteType + ) external returns (string memory); + + /// @dev Defines a method to query actions. + /// @param pagination The pagination details + /// @return response The paged actions + function actions( + Types.PageRequest calldata pagination + ) external view returns (ActionsResponse memory response); + + /// @dev Defines a method to query an action by id. + /// @param actionId The id of the action + /// @return response The action + function actionById( + uint64 actionId + ) external view returns (ActionByIdResponse memory response); + + /// @dev Defines a method to query an action by participant address. + /// @param pagination The pagination details + /// @param addr The participant address + /// @param status The action status + /// @return response The paged actions + function actionsByAddress( + Types.PageRequest calldata pagination, + address addr, + ActionStatus status + ) external view returns (ActionsByAddressResponse memory response); + + /// @dev Defines a method to query templates. + /// @param pagination The pagination details + /// @param creator The template creator + /// @return response The paged templates + function templates( + Types.PageRequest calldata pagination, + address creator + ) external view returns (TemplatesResponse memory response); + + /// @dev Defines a method to query a template by id. + /// @param templateId The id of the template + /// @return response The template + function templateById( + uint64 templateId + ) external view returns (TemplateByIdResponse memory response); + + /// @dev CreateTemplate defines an Event emitted when a template is created. + /// @param creator The address of the creator + /// @param templateId The template id + event CreateTemplate(address indexed creator, uint64 templateId); + + /// @dev UpdateTemplate defines an Event emitted when a template is updated. + /// @param author The address of the author + /// @param templateId The template id + event UpdateTemplate(address indexed author, uint64 templateId); + + /// @dev ActionVoted defines an Event emitted when an action is voted. + /// @param participant The address of the participant + /// @param actionId The action Id + /// @param voteType The type of the vote + event ActionVoted( + address indexed participant, + uint64 actionId, + VoteType voteType + ); + + /// @dev CreateAction defines an Event emitted when an action is created. + /// @param creator The address of the creator + /// @param actionId The action Id + event CreateAction(address indexed creator, uint64 actionId); + + /// @dev ActionStateChange defines an Event emitted when an action state is changed. + /// @param author The address of the author + /// @param actionId The action Id + /// @param previousStatus The previous status of the action + /// @param newStatus The new status of the action + event ActionStateChange( + address indexed author, + uint64 actionId, + ActionStatus previousStatus, + ActionStatus newStatus + ); +} diff --git a/src/orders/precompiles/act/Types.abi b/src/orders/precompiles/act/Types.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/src/orders/precompiles/act/Types.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/orders/precompiles/act/abi.json b/src/orders/precompiles/act/abi.json new file mode 100644 index 0000000..7a719b1 --- /dev/null +++ b/src/orders/precompiles/act/abi.json @@ -0,0 +1,970 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "author", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "enum ActionStatus", + "name": "previousStatus", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ActionStatus", + "name": "newStatus", + "type": "uint8" + } + ], + "name": "ActionStateChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "participant", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "enum VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "name": "ActionVoted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + } + ], + "name": "CreateAction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "templateId", + "type": "uint64" + } + ], + "name": "CreateTemplate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "author", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "templateId", + "type": "uint64" + } + ], + "name": "UpdateTemplate", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + } + ], + "name": "actionById", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "enum ActionStatus", + "name": "status", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "typeUrl", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct Types.AnyType", + "name": "msg", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "typeUrl", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct Types.AnyType", + "name": "result", + "type": "tuple" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timeoutHeight", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "createdAt", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "updatedAt", + "type": "tuple" + }, + { + "internalType": "string", + "name": "approveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "rejectExpression", + "type": "string" + }, + { + "internalType": "address[]", + "name": "mentions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "participant", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "votedAt", + "type": "tuple" + }, + { + "internalType": "enum VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "internalType": "struct ActionVote[]", + "name": "votes", + "type": "tuple[]" + } + ], + "internalType": "struct Action", + "name": "action", + "type": "tuple" + } + ], + "internalType": "struct ActionByIdResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "actions", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pagination", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "enum ActionStatus", + "name": "status", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "typeUrl", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct Types.AnyType", + "name": "msg", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "typeUrl", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct Types.AnyType", + "name": "result", + "type": "tuple" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timeoutHeight", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "createdAt", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "updatedAt", + "type": "tuple" + }, + { + "internalType": "string", + "name": "approveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "rejectExpression", + "type": "string" + }, + { + "internalType": "address[]", + "name": "mentions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "participant", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "votedAt", + "type": "tuple" + }, + { + "internalType": "enum VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "internalType": "struct ActionVote[]", + "name": "votes", + "type": "tuple[]" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + } + ], + "internalType": "struct ActionsResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pagination", + "type": "tuple" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "enum ActionStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "actionsByAddress", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pagination", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "enum ActionStatus", + "name": "status", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "string", + "name": "typeUrl", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct Types.AnyType", + "name": "msg", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "typeUrl", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct Types.AnyType", + "name": "result", + "type": "tuple" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timeoutHeight", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "createdAt", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "updatedAt", + "type": "tuple" + }, + { + "internalType": "string", + "name": "approveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "rejectExpression", + "type": "string" + }, + { + "internalType": "address[]", + "name": "mentions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "participant", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "secs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nanos", + "type": "uint64" + } + ], + "internalType": "struct Types.Timestamp", + "name": "votedAt", + "type": "tuple" + }, + { + "internalType": "enum VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "internalType": "struct ActionVote[]", + "name": "votes", + "type": "tuple[]" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + } + ], + "internalType": "struct ActionsByAddressResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + } + ], + "name": "checkAction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "definition", + "type": "string" + } + ], + "name": "newTemplate", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + } + ], + "name": "revokeAction", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "templateId", + "type": "uint64" + } + ], + "name": "templateById", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "expression", + "type": "string" + } + ], + "internalType": "struct Template", + "name": "template", + "type": "tuple" + } + ], + "internalType": "struct TemplateByIdResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pagination", + "type": "tuple" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + } + ], + "name": "templates", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pagination", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "expression", + "type": "string" + } + ], + "internalType": "struct Template[]", + "name": "templates", + "type": "tuple[]" + } + ], + "internalType": "struct TemplatesResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "templateId", + "type": "uint64" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "definition", + "type": "string" + } + ], + "name": "updateTemplate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "actionId", + "type": "uint64" + }, + { + "internalType": "enum VoteType", + "name": "voteType", + "type": "uint8" + } + ], + "name": "voteForAction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/src/orders/precompiles/act/act.go b/src/orders/precompiles/act/act.go new file mode 100644 index 0000000..1195103 --- /dev/null +++ b/src/orders/precompiles/act/act.go @@ -0,0 +1,166 @@ +package act + +import ( + "embed" + "fmt" + + "cosmossdk.io/log" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + ethcmn "github.com/ethereum/go-ethereum/common" + evmoscmn "github.com/evmos/evmos/v20/precompiles/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + "github.com/warden-protocol/wardenprotocol/precompiles/common" + actmodulekeeper "github.com/warden-protocol/wardenprotocol/warden/x/act/keeper" + types "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" +) + +var _ vm.PrecompiledContract = &Precompile{} + +const PrecompileAddress = "0x0000000000000000000000000000000000000901" + +// Embed abi json file to the executable binary. Needed when importing as dependency. +// +//go:embed abi.json +var f embed.FS + +// Precompile defines the precompiled contract for x/act. +type Precompile struct { + evmoscmn.Precompile + actmodulekeeper actmodulekeeper.Keeper + eventsRegistry *common.EthEventsRegistry + queryServer types.QueryServer +} + +// LoadABI loads the x/act ABI from the embedded abi.json file +// for the x/act precompile. +func LoadABI() (abi.ABI, error) { + return evmoscmn.LoadABI(f, "abi.json") +} + +func NewPrecompile(actkeeper actmodulekeeper.Keeper, er *common.EthEventsRegistry) (*Precompile, error) { + abi, err := LoadABI() + if err != nil { + return nil, err + } + + p := Precompile{ + Precompile: evmoscmn.Precompile{ + ABI: abi, + KvGasConfig: storetypes.KVGasConfig(), + TransientKVGasConfig: storetypes.TransientGasConfig(), + }, + actmodulekeeper: actkeeper, + eventsRegistry: er, + queryServer: actmodulekeeper.NewQueryServerImpl(actkeeper), + } + + p.SetAddress(p.Address()) + + return &p, nil +} + +// Address implements vm.PrecompiledContract. +func (p *Precompile) Address() ethcmn.Address { + return ethcmn.HexToAddress(PrecompileAddress) +} + +// RequiredGas implements vm.PrecompiledContract. +// Subtle: this method shadows the method (Precompile).RequiredGas of Precompile.Precompile. +func (p *Precompile) RequiredGas(input []byte) uint64 { + // NOTE: This check avoid panicking when trying to decode the method ID + if len(input) < 4 { + return 0 + } + + methodID := input[:4] + + method, err := p.MethodById(methodID) + if err != nil { + // This should never happen since this method is going to fail during Run + return 0 + } + + return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name)) +} + +// Run implements vm.PrecompiledContract. +func (p *Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) (bz []byte, err error) { + ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readonly, p.IsTransaction) + if err != nil { + return nil, err + } + + // This handles any out of gas errors that may occur during the execution of a precompile tx or query. + // It avoids panics and returns the out of gas error so the EVM can continue gracefully. + defer evmoscmn.HandleGasError(ctx, contract, initialGas, &err)() + + switch method.Name { + // transactions + case CheckActionMethod: + bz, err = p.CheckActionMethod(ctx, evm.Origin, stateDB, method, args) + case NewTemplateMethod: + bz, err = p.NewTemplateMethod(ctx, evm.Origin, stateDB, method, args) + case RevokeActionMethod: + bz, err = p.RevokeActionMethod(ctx, evm.Origin, stateDB, method, args) + case UpdateTemplateMethod: + bz, err = p.UpdateTemplateMethod(ctx, evm.Origin, stateDB, method, args) + case VoteForActionMethod: + bz, err = p.VoteForActionMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + // queries + case ActionsQuery: + bz, err = p.ActionsQuery(ctx, contract, method, args) + case ActionByIdQuery: + bz, err = p.ActionByIdQuery(ctx, contract, method, args) + case ActionsByAddressQuery: + bz, err = p.ActionsByAddressQuery(ctx, contract, method, args) + case TemplatesQuery: + bz, err = p.TemplatesQuery(ctx, contract, method, args) + case TemplateByIdQuery: + bz, err = p.TemplateByIdQuery(ctx, contract, method, args) + } + + if err != nil { + return nil, err + } + + cost := ctx.GasMeter().GasConsumed() - initialGas + + if !contract.UseGas(cost) { + return nil, vm.ErrOutOfGas + } + + if err := p.AddJournalEntries(stateDB, snapshot); err != nil { + return nil, err + } + + return bz, nil +} + +func (p *Precompile) IsTransaction(method string) bool { + switch method { + // transactions + case CheckActionMethod, + NewTemplateMethod, + RevokeActionMethod, + UpdateTemplateMethod, + VoteForActionMethod: + return true + // queries + case ActionsQuery, + ActionByIdQuery, + ActionsByAddressQuery, + TemplatesQuery, + TemplateByIdQuery: + return false + } + panic(fmt.Errorf("act precompile: method not exists: %s", method)) +} + +// Logger returns a precompile-specific logger. +func (p *Precompile) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("evm extension", "act") +} diff --git a/src/orders/precompiles/act/events.go b/src/orders/precompiles/act/events.go new file mode 100644 index 0000000..5de8fae --- /dev/null +++ b/src/orders/precompiles/act/events.go @@ -0,0 +1,256 @@ +package act + +import ( + "bytes" + "fmt" + "reflect" + + sdk "github.com/cosmos/cosmos-sdk/types" + ethcmn "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + cmn "github.com/evmos/evmos/v20/precompiles/common" + + "github.com/warden-protocol/wardenprotocol/precompiles/common" + "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" +) + +const ( + // EventCreateTemplate defines the event type for the x/act CreateTemplate transaction. + EventCreateTemplate = "CreateTemplate" + // EventUpdateTemplate defines the event type for the x/act UpdateTemplate transaction. + EventUpdateTemplate = "UpdateTemplate" + // EventActionVoted defines the event type for the x/act VoteForAction transaction. + EventActionVoted = "ActionVoted" + // EventCreateAction defines the event type for the x/act NewAction transaction. + EventCreateAction = "CreateAction" + // EventActionStateChange defines the event type for the x/act action status change. + EventActionStateChange = "ActionStateChange" +) + +// Map EventCreateTemplate to eth CreateTemplate event and write to eth log +func (p *Precompile) GetCreateTemplateEvent(ctx sdk.Context, writerAddress *ethcmn.Address, sdkEvent sdk.Event) (*ethtypes.Log, error) { + b, err := parseCreateTemplateEvent(sdkEvent) + if err != nil { + return nil, err + } + + if writerAddress == nil { + return nil, fmt.Errorf("writerAddress is nil") + } + + topics := make([]ethcmn.Hash, 2) + event := p.ABI.Events[EventCreateTemplate] + // The first topic is always the signature of the event. + topics[0] = event.ID + + topics[1], err = cmn.MakeTopic(*writerAddress) + if err != nil { + return nil, err + } + + ethLog := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return ðLog, nil +} + +func parseCreateTemplateEvent(sdkEvent sdk.Event) (*bytes.Buffer, error) { + var b bytes.Buffer + + typedEvent := v1beta1.EventCreateTemplate{} + err := common.ParseSdkEvent(sdkEvent, typedEvent.XXX_Merge) + if err != nil { + return nil, err + } + + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.Id))) + + return &b, nil +} + +// Map EventUpdateTemplate to eth UpdateTemplate event and write to eth log +func (p *Precompile) GetUpdateTemplateEvent(ctx sdk.Context, writerAddress *ethcmn.Address, sdkEvent sdk.Event) (*ethtypes.Log, error) { + b, err := parseUpdateTemplateEvent(sdkEvent) + if err != nil { + return nil, err + } + + if writerAddress == nil { + return nil, fmt.Errorf("writerAddress is nil") + } + + topics := make([]ethcmn.Hash, 2) + event := p.ABI.Events[EventUpdateTemplate] + // The first topic is always the signature of the event. + topics[0] = event.ID + + topics[1], err = cmn.MakeTopic(*writerAddress) + if err != nil { + return nil, err + } + + ethLog := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return ðLog, nil +} + +func parseUpdateTemplateEvent(sdkEvent sdk.Event) (*bytes.Buffer, error) { + var b bytes.Buffer + + typedEvent := v1beta1.EventUpdateTemplate{} + err := common.ParseSdkEvent(sdkEvent, typedEvent.XXX_Merge) + if err != nil { + return nil, err + } + + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.Id))) + + return &b, nil +} + +// Map EventCreateAction to eth CreateAction event and write to eth log +func (p *Precompile) GetCreateActionEvent(ctx sdk.Context, writerAddress *ethcmn.Address, sdkEvent sdk.Event) (*ethtypes.Log, error) { + b, err := parseCreateActionEvent(sdkEvent) + if err != nil { + return nil, err + } + + if writerAddress == nil { + return nil, fmt.Errorf("writerAddress is nil") + } + + topics := make([]ethcmn.Hash, 2) + event := p.ABI.Events[EventCreateAction] + // The first topic is always the signature of the event. + topics[0] = event.ID + + topics[1], err = cmn.MakeTopic(*writerAddress) + if err != nil { + return nil, err + } + + ethLog := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return ðLog, nil +} + +func parseCreateActionEvent(sdkEvent sdk.Event) (*bytes.Buffer, error) { + var b bytes.Buffer + + typedEvent := v1beta1.EventCreateAction{} + err := common.ParseSdkEvent(sdkEvent, typedEvent.XXX_Merge) + if err != nil { + return nil, err + } + + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.Id))) + + return &b, nil +} + +// Map EventActionVoted to eth ActionVoted event and write to eth log +func (p *Precompile) GetActionVotedEvent(ctx sdk.Context, writerAddress *ethcmn.Address, sdkEvent sdk.Event) (*ethtypes.Log, error) { + b, err := parseActionVotedEvent(sdkEvent) + if err != nil { + return nil, err + } + + if writerAddress == nil { + return nil, fmt.Errorf("writerAddress is nil") + } + + topics := make([]ethcmn.Hash, 2) + event := p.ABI.Events[EventActionVoted] + // The first topic is always the signature of the event. + topics[0] = event.ID + + topics[1], err = cmn.MakeTopic(*writerAddress) + if err != nil { + return nil, err + } + + ethLog := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return ðLog, nil +} + +func parseActionVotedEvent(sdkEvent sdk.Event) (*bytes.Buffer, error) { + var b bytes.Buffer + + typedEvent := v1beta1.EventActionVoted{} + err := common.ParseSdkEvent(sdkEvent, typedEvent.XXX_Merge) + if err != nil { + return nil, err + } + + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.Id))) + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.VoteType))) + + return &b, nil +} + +// Map EventActionStateChange to eth ActionStateChange event and write to eth log +func (p *Precompile) GetActionStateChangeEvent(ctx sdk.Context, writerAddress *ethcmn.Address, sdkEvent sdk.Event) (*ethtypes.Log, error) { + b, err := parseActionStateChangeEvent(sdkEvent) + if err != nil { + return nil, err + } + + if writerAddress == nil { + return nil, fmt.Errorf("writerAddress is nil") + } + + topics := make([]ethcmn.Hash, 2) + event := p.ABI.Events[EventActionStateChange] + // The first topic is always the signature of the event. + topics[0] = event.ID + + topics[1], err = cmn.MakeTopic(*writerAddress) + if err != nil { + return nil, err + } + + ethLog := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return ðLog, nil +} + +func parseActionStateChangeEvent(sdkEvent sdk.Event) (*bytes.Buffer, error) { + var b bytes.Buffer + + typedEvent := v1beta1.EventActionStateChange{} + err := common.ParseSdkEvent(sdkEvent, typedEvent.XXX_Merge) + if err != nil { + return nil, err + } + + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.Id))) + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.PreviousStatus))) + b.Write(cmn.PackNum(reflect.ValueOf(typedEvent.NewStatus))) + + return &b, nil +} diff --git a/src/orders/precompiles/act/query.go b/src/orders/precompiles/act/query.go new file mode 100644 index 0000000..d1c9895 --- /dev/null +++ b/src/orders/precompiles/act/query.go @@ -0,0 +1,256 @@ +package act + +import ( + "fmt" + "github.com/ethereum/go-ethereum/common" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + types "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" +) + +const ( + ActionsQuery = "actions" + ActionByIdQuery = "actionById" + ActionsByAddressQuery = "actionsByAddress" + TemplatesQuery = "templates" + TemplateByIdQuery = "templateById" +) + +// ActionsQuery actions query implementation, constructs QueryActionsRequest from args, passes it to query server and packs response into corresponding abi output. +func (p *Precompile) ActionsQuery( + ctx sdk.Context, + _ *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newActionsQuery(method, args) + if err != nil { + return nil, err + } + + res, err := p.queryServer.Actions(ctx, req) + if err != nil { + return nil, err + } + if res == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(ActionsResponse).FromResponse(res) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newActionsQuery(method *abi.Method, args []interface{}) (*types.QueryActionsRequest, error) { + if len(args) != 1 { + return nil, precommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input ActionsInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to ActionsInput struct: %w", err) + } + + precommon.ClearPaginationKey(&input.Pagination) + + return &types.QueryActionsRequest{ + Pagination: &input.Pagination, + }, nil +} + +// ActionByIdQuery is actionById query implementation, constructs QueryActionByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p *Precompile) ActionByIdQuery( + ctx sdk.Context, + _ *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newActionByIdQuery(args) + if err != nil { + return nil, err + } + + res, err := p.queryServer.ActionById(ctx, req) + if err != nil { + return nil, err + } + if res == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(ActionByIdResponse).FromResponse(res) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newActionByIdQuery(args []interface{}) (*types.QueryActionByIdRequest, error) { + if len(args) != 1 { + return nil, precommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + actionId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionId, got %T", args[0]) + } + + return &types.QueryActionByIdRequest{ + Id: actionId, + }, nil +} + +// ActionsByAddressQuery is actionsByAddress query implementation, Constructs QueryActionsByAddressRequest from args, passes it to query server and packs response into corresponding abi output. +func (p *Precompile) ActionsByAddressQuery( + ctx sdk.Context, + _ *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newActionsByAddressQuery(method, args) + if err != nil { + return nil, err + } + + res, err := p.queryServer.ActionsByAddress(ctx, req) + if err != nil { + return nil, err + } + if res == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(ActionsByAddressResponse).FromResponse(res) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newActionsByAddressQuery(method *abi.Method, args []interface{}) (*types.QueryActionsByAddressRequest, error) { + if len(args) != 3 { + return nil, precommon.WrongArgsNumber{Expected: 3, Got: len(args)} + } + + var input ActionsByAddressInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to ActionsByAddressInput struct: %w", err) + } + + precommon.ClearPaginationKey(&input.Pagination) + + if _, ok := types.ActionStatus_name[int32(input.Status)]; !ok { + return nil, fmt.Errorf("invalid Status value: %d", input.Status) + } + + return &types.QueryActionsByAddressRequest{ + Pagination: &input.Pagination, + Address: precommon.Bech32StrFromAddress(input.Address), + Status: types.ActionStatus(input.Status), + }, nil +} + +// TemplatesQuery is templates query implementation, constructs QueryTemplatesRequest from args, passes it to query server and packs response into corresponding abi output. +func (p *Precompile) TemplatesQuery( + ctx sdk.Context, + _ *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newTemplatesQuery(method, args) + if err != nil { + return nil, err + } + + res, err := p.queryServer.Templates(ctx, req) + if err != nil { + return nil, err + } + if res == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(TemplatesResponse).FromResponse(res) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newTemplatesQuery(method *abi.Method, args []interface{}) (*types.QueryTemplatesRequest, error) { + if len(args) != 2 { + return nil, precommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + var input TemplatesInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to TemplatesInput struct: %w", err) + } + + precommon.ClearPaginationKey(&input.Pagination) + + var creator string + if input.Creator == (common.Address{}) { + creator = "" + } else { + creator = precommon.Bech32StrFromAddress(input.Creator) + } + + return &types.QueryTemplatesRequest{ + Pagination: &input.Pagination, + Creator: creator, + }, nil +} + +// TemplateByIdQuery is templateById query implementation, constructs QueryTemplateByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p *Precompile) TemplateByIdQuery( + ctx sdk.Context, + _ *vm.Contract, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newTemplateByIdQuery(args) + if err != nil { + return nil, err + } + + res, err := p.queryServer.TemplateById(ctx, req) + if err != nil { + return nil, err + } + if res == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(TemplateByIdResponse).FromResponse(res) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newTemplateByIdQuery(args []interface{}) (*types.QueryTemplateByIdRequest, error) { + if len(args) != 1 { + return nil, precommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + templateId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for templateId, got %T", args[0]) + } + + return &types.QueryTemplateByIdRequest{ + Id: templateId, + }, nil +} diff --git a/src/orders/precompiles/act/tx.go b/src/orders/precompiles/act/tx.go new file mode 100644 index 0000000..1a5f4f5 --- /dev/null +++ b/src/orders/precompiles/act/tx.go @@ -0,0 +1,351 @@ +package act + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + actmodulekeeper "github.com/warden-protocol/wardenprotocol/warden/x/act/keeper" + "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" + acttypes "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" +) + +const ( + CheckActionMethod = "checkAction" + NewTemplateMethod = "newTemplate" + RevokeActionMethod = "revokeAction" + UpdateTemplateMethod = "updateTemplate" + VoteForActionMethod = "voteForAction" +) + +// CheckActionMethod constructs MsgCheckAction from args, passes it to msg server and packs corresponding abi output +func (p *Precompile) CheckActionMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actmodulekeeper.NewMsgServerImpl(p.actmodulekeeper) + + message, err := newMsgCheckAction(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + response, err := msgServer.CheckAction(ctx, message) + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(response.Status) +} + +func newMsgCheckAction(args []interface{}, origin common.Address) (*acttypes.MsgCheckAction, error) { + if len(args) != 1 { + return nil, precommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + authority := precommon.Bech32StrFromAddress(origin) + + actionId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionId, got %T", args[0]) + } + + return &acttypes.MsgCheckAction{ + Creator: authority, + ActionId: actionId, + }, nil +} + +// NewTemplateMethod constructs MsgNewTemplate from args, passes it to msg server and packs corresponding abi output. +func (p *Precompile) NewTemplateMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actmodulekeeper.NewMsgServerImpl(p.actmodulekeeper) + + message, err := newMsgNewTemplate(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + response, err := msgServer.NewTemplate(ctx, message) + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(response.Id) +} + +func newMsgNewTemplate(args []interface{}, origin common.Address) (*acttypes.MsgNewTemplate, error) { + if len(args) != 2 { + return nil, precommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + authority := precommon.Bech32StrFromAddress(origin) + + name, ok := args[0].(string) + if !ok { + return nil, fmt.Errorf("expected string for name, got %T", args[0]) + } + + definition, ok := args[1].(string) + if !ok { + return nil, fmt.Errorf("expected string for definition, got %T", args[1]) + } + + return &acttypes.MsgNewTemplate{ + Creator: authority, + Name: name, + Definition: definition, + }, nil +} + +// RevokeActionMethod constructs MsgRevokeAction from args, passes it to msg server and packs corresponding abi output. +func (p *Precompile) RevokeActionMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actmodulekeeper.NewMsgServerImpl(p.actmodulekeeper) + + message, err := newMsgRevokeAction(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + _, err = msgServer.RevokeAction(ctx, message) + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +func newMsgRevokeAction(args []interface{}, origin common.Address) (*acttypes.MsgRevokeAction, error) { + if len(args) != 1 { + return nil, precommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + authority := precommon.Bech32StrFromAddress(origin) + + actionId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionId, got %T", args[0]) + } + + return &acttypes.MsgRevokeAction{ + Creator: authority, + ActionId: actionId, + }, nil +} + +// UpdateTemplateMethod constructs MsgUpdateTemplate from args, passes it to msg server and packs corresponding abi output. +func (p *Precompile) UpdateTemplateMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actmodulekeeper.NewMsgServerImpl(p.actmodulekeeper) + + message, err := newMsgUpdateTemplate(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + _, err = msgServer.UpdateTemplate(ctx, message) + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +func newMsgUpdateTemplate(args []interface{}, origin common.Address) (*acttypes.MsgUpdateTemplate, error) { + if len(args) != 3 { + return nil, precommon.WrongArgsNumber{Expected: 3, Got: len(args)} + } + + authority := precommon.Bech32StrFromAddress(origin) + + templateId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for templateId, got %T", args[0]) + } + + name, ok := args[1].(string) + if !ok { + return nil, fmt.Errorf("expected string for name, got %T", args[1]) + } + + definition, ok := args[2].(string) + if !ok { + return nil, fmt.Errorf("expected string for definition, got %T", args[2]) + } + + return &acttypes.MsgUpdateTemplate{ + Creator: authority, + Id: templateId, + Name: name, + Definition: definition, + }, nil +} + +// VoteForActionMethod constructs MsgVoteForAction from args, passes it to msg server and packs corresponding abi output. +func (p *Precompile) VoteForActionMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actmodulekeeper.NewMsgServerImpl(p.actmodulekeeper) + + message, err := newMsgVoteForAction(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + response, err := msgServer.VoteForAction(ctx, message) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, message.ActionId, caller); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(response.Status) +} + +func newMsgVoteForAction(args []interface{}, origin common.Address) (*acttypes.MsgVoteForAction, error) { + if len(args) != 2 { + return nil, precommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + authority := precommon.Bech32StrFromAddress(origin) + + actionId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionId, got %T", args[0]) + } + + voteType, ok := args[1].(uint8) + if !ok { + return nil, fmt.Errorf("expected uint8 for voteType, got %T", args[1]) + } + + return &acttypes.MsgVoteForAction{ + Participant: authority, + ActionId: actionId, + VoteType: acttypes.ActionVoteType(voteType), + }, nil +} + +// tryVoteAsSender attempts to vote for an action as the sender of the action. +// This is useful if the contract attempts to vote for an action. +// If the action is not in the pending state, this function does nothing. +// If the action is in the pending state, it attempts to vote for the action +// with an approved vote type. If the vote is successful, this function returns +// nil. If the vote fails, this function returns the error. +func (p Precompile) tryVoteAsSender( + ctx sdk.Context, + msgServer v1beta1.MsgServer, + actionId uint64, + caller common.Address) error { + + actionResponse, err := p.queryServer.ActionById(ctx, &v1beta1.QueryActionByIdRequest{ + Id: actionId, + }) + if err != nil { + return err + } + + action := actionResponse.Action + + if action.GetStatus() != v1beta1.ActionStatus_ACTION_STATUS_PENDING { + return nil + } + + participant := precommon.Bech32StrFromAddress(caller) + + _, err = msgServer.VoteForAction(ctx, &v1beta1.MsgVoteForAction{ + Participant: participant, + ActionId: action.GetId(), + VoteType: v1beta1.ActionVoteType_VOTE_TYPE_APPROVED, + }) + if err != nil { + return err + } + + return nil +} diff --git a/src/orders/precompiles/act/types.go b/src/orders/precompiles/act/types.go new file mode 100644 index 0000000..bb61008 --- /dev/null +++ b/src/orders/precompiles/act/types.go @@ -0,0 +1,245 @@ +package act + +import ( + "encoding/json" + "fmt" + "time" + + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/ethereum/go-ethereum/common" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + types "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" +) + +// ActionsInput needed to unmarshal Pagination field and pass it to types.QueryActionsRequest +type ActionsInput struct { + Pagination query.PageRequest `abi:"pagination"` +} + +// FromResponse needed to map QueryActionsResponse to ActionsResponse +func (r *ActionsResponse) FromResponse(res *types.QueryActionsResponse) (ActionsResponse, error) { + if res != nil { + actions := make([]Action, 0, len(res.Actions)) + for _, action := range res.Actions { + mappedAction, err := mapAction(action) + if err != nil { + return ActionsResponse{}, err + } + + actions = append(actions, mappedAction) + } + + r.Actions = actions + r.Pagination = mapPageResponse(res.Pagination) + } + + return *r, nil +} + +// FromResponse needed to map QueryActionByIdResponse to ActionByIdResponse +func (r *ActionByIdResponse) FromResponse(res *types.QueryActionByIdResponse) (ActionByIdResponse, error) { + if res != nil && res.Action != nil { + mappedAction, err := mapAction(*res.Action) + if err != nil { + return ActionByIdResponse{}, err + } + + r.Action = mappedAction + } + + return *r, nil +} + +// ActionsByAddressInput needed to unmarshal Pagination field and pass it to types.QueryActionsByAddressRequest +type ActionsByAddressInput struct { + Pagination query.PageRequest `abi:"pagination"` + Address common.Address `abi:"addr"` + Status uint8 `abi:"status"` +} + +// FromResponse needed to map QueryActionsByAddressResponse to ActionsByAddressResponse +func (r *ActionsByAddressResponse) FromResponse(res *types.QueryActionsByAddressResponse) (ActionsByAddressResponse, error) { + if res != nil { + actions := make([]Action, 0, len(res.Actions)) + for _, action := range res.Actions { + mappedAction, err := mapAction(action) + if err != nil { + return ActionsByAddressResponse{}, err + } + + actions = append(actions, mappedAction) + } + + r.Actions = actions + r.Pagination = mapPageResponse(res.Pagination) + } + + return *r, nil +} + +// TemplatesInput needed to unmarshal Pagination field and pass it to types.QueryTemplatesRequest +type TemplatesInput struct { + Pagination query.PageRequest `abi:"pagination"` + Creator common.Address `abi:"creator"` +} + +// FromResponse needed to map QueryTemplatesResponse to TemplatesResponse +func (r *TemplatesResponse) FromResponse(res *types.QueryTemplatesResponse) (TemplatesResponse, error) { + if res != nil { + templates := make([]Template, 0, len(res.Templates)) + for _, action := range res.Templates { + mappedTemplate, err := mapTemplate(action) + if err != nil { + return TemplatesResponse{}, err + } + + templates = append(templates, mappedTemplate) + } + + r.Templates = templates + r.Pagination = mapPageResponse(res.Pagination) + } + + return *r, nil +} + +// FromResponse needed to map QueryTemplateByIdResponse to TemplateByIdResponse +func (r *TemplateByIdResponse) FromResponse(res *types.QueryTemplateByIdResponse) (TemplateByIdResponse, error) { + if res != nil && res.Template != nil { + mappedTemplate, err := mapTemplate(*res.Template) + if err != nil { + return TemplateByIdResponse{}, err + } + + r.Template = mappedTemplate + } + + return *r, nil +} + +func mapAction(action types.Action) (Action, error) { + mentions := make([]common.Address, 0, len(action.Mentions)) + for _, mention := range action.Mentions { + mentionAddress, err := precommon.AddressFromBech32Str(mention) + if err != nil { + return Action{}, fmt.Errorf("invalid mention %s: %w", mention, err) + } + + mentions = append(mentions, mentionAddress) + } + + creator, err := precommon.AddressFromBech32Str(action.Creator) + if err != nil { + return Action{}, fmt.Errorf("invalid creator: %w", err) + } + + mappedVotes, err := mapVotes(action.Votes) + if err != nil { + return Action{}, err + } + + approveExpressionJson, err := json.Marshal(action.ApproveExpression) + if err != nil { + return Action{}, nil + } + + rejectExpressionJson, err := json.Marshal(action.RejectExpression) + if err != nil { + return Action{}, nil + } + + return Action{ + Id: action.Id, + Status: uint8(action.Status), + Msg: mapAny(action.Msg), + Result: mapAny(action.Result), + Creator: creator, + TimeoutHeight: action.TimeoutHeight, + CreatedAt: mapTimestamp(action.CreatedAt), + UpdatedAt: mapTimestamp(action.UpdatedAt), + ApproveExpression: string(approveExpressionJson), + RejectExpression: string(rejectExpressionJson), + Mentions: mentions, + Votes: mappedVotes, + }, nil +} + +func mapVotes(values []*types.ActionVote) ([]ActionVote, error) { + result := make([]ActionVote, 0, len(values)) + for _, v := range values { + if v != nil { + mappedTemplate, err := mapVote(*v) + if err != nil { + return nil, err + } + + result = append(result, mappedTemplate) + } + } + return result, nil +} + +func mapVote(value types.ActionVote) (ActionVote, error) { + participant, err := precommon.AddressFromBech32Str(value.Participant) + + if err != nil { + return ActionVote{}, err + } + + return ActionVote{ + Participant: participant, + VotedAt: mapTimestamp(value.VotedAt), + VoteType: uint8(value.VoteType), + }, nil +} + +func mapTemplate(value types.Template) (Template, error) { + creator, err := precommon.AddressFromBech32Str(value.Creator) + + if err != nil { + return Template{}, err + } + + expressionJson, err := json.Marshal(value.Expression) + if err != nil { + return Template{}, nil + } + + return Template{ + Id: value.Id, + Creator: creator, + Name: value.Name, + Expression: string(expressionJson), + }, nil +} + +func mapAny(any *cdctypes.Any) TypesAnyType { + if any == nil { + return TypesAnyType{} + } + + return TypesAnyType{ + TypeUrl: any.TypeUrl, + Value: any.Value, + } +} + +func mapTimestamp(value time.Time) TypesTimestamp { + return TypesTimestamp{ + Secs: uint64(value.Unix()), + Nanos: uint64(value.Nanosecond()), + } +} + +func mapPageResponse(value *query.PageResponse) TypesPageResponse { + if value == nil { + return TypesPageResponse{} + } + + return TypesPageResponse{ + NextKey: value.NextKey, + Total: value.Total, + } +} diff --git a/src/orders/precompiles/async/IAsync.go b/src/orders/precompiles/async/IAsync.go new file mode 100644 index 0000000..7197698 --- /dev/null +++ b/src/orders/precompiles/async/IAsync.go @@ -0,0 +1,510 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package async + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// Future is an auto generated low-level Go binding around an user-defined struct. +type Future struct { + Id uint64 + Creator common.Address + Handler string + Input []byte +} + +// FutureByIdResponse is an auto generated low-level Go binding around an user-defined struct. +type FutureByIdResponse struct { + FutureResponse FutureResponse +} + +// FutureResponse is an auto generated low-level Go binding around an user-defined struct. +type FutureResponse struct { + Future Future + Votes []FutureVote + Result FutureResult +} + +// FutureResult is an auto generated low-level Go binding around an user-defined struct. +type FutureResult struct { + Id uint64 + Output []byte + Submitter []byte +} + +// FutureVote is an auto generated low-level Go binding around an user-defined struct. +type FutureVote struct { + FutureId uint64 + Voter []byte + Vote uint8 +} + +// FuturesResponse is an auto generated low-level Go binding around an user-defined struct. +type FuturesResponse struct { + Pagination TypesPageResponse + Futures []FutureResponse +} + +// PendingFuturesResponse is an auto generated low-level Go binding around an user-defined struct. +type PendingFuturesResponse struct { + Pagination TypesPageResponse + Futures []Future +} + +// TypesPageRequest is an auto generated low-level Go binding around an user-defined struct. +type TypesPageRequest struct { + Key []byte + Offset uint64 + Limit uint64 + CountTotal bool + Reverse bool +} + +// TypesPageResponse is an auto generated low-level Go binding around an user-defined struct. +type TypesPageResponse struct { + NextKey []byte + Total uint64 +} + +// IAsyncMetaData contains all meta data concerning the IAsync contract. +var IAsyncMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"futureId\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"handler\",\"type\":\"string\"}],\"name\":\"CreateFuture\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"handler\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"name\":\"addFuture\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"futureId\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"futureId\",\"type\":\"uint64\"}],\"name\":\"futureById\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"handler\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"internalType\":\"structFuture\",\"name\":\"future\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"futureId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"Voter\",\"type\":\"bytes\"},{\"internalType\":\"enumFutureVoteType\",\"name\":\"vote\",\"type\":\"uint8\"}],\"internalType\":\"structFutureVote[]\",\"name\":\"votes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"output\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"submitter\",\"type\":\"bytes\"}],\"internalType\":\"structFutureResult\",\"name\":\"result\",\"type\":\"tuple\"}],\"internalType\":\"structFutureResponse\",\"name\":\"futureResponse\",\"type\":\"tuple\"}],\"internalType\":\"structFutureByIdResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"}],\"name\":\"futures\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"handler\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"internalType\":\"structFuture\",\"name\":\"future\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"futureId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"Voter\",\"type\":\"bytes\"},{\"internalType\":\"enumFutureVoteType\",\"name\":\"vote\",\"type\":\"uint8\"}],\"internalType\":\"structFutureVote[]\",\"name\":\"votes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"output\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"submitter\",\"type\":\"bytes\"}],\"internalType\":\"structFutureResult\",\"name\":\"result\",\"type\":\"tuple\"}],\"internalType\":\"structFutureResponse[]\",\"name\":\"futures\",\"type\":\"tuple[]\"}],\"internalType\":\"structFuturesResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pagination\",\"type\":\"tuple\"}],\"name\":\"pendingFutures\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pagination\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"handler\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"internalType\":\"structFuture[]\",\"name\":\"futures\",\"type\":\"tuple[]\"}],\"internalType\":\"structPendingFuturesResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// IAsyncABI is the input ABI used to generate the binding from. +// Deprecated: Use IAsyncMetaData.ABI instead. +var IAsyncABI = IAsyncMetaData.ABI + +// IAsync is an auto generated Go binding around an Ethereum contract. +type IAsync struct { + IAsyncCaller // Read-only binding to the contract + IAsyncTransactor // Write-only binding to the contract + IAsyncFilterer // Log filterer for contract events +} + +// IAsyncCaller is an auto generated read-only Go binding around an Ethereum contract. +type IAsyncCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAsyncTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IAsyncTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAsyncFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IAsyncFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IAsyncSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IAsyncSession struct { + Contract *IAsync // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IAsyncCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IAsyncCallerSession struct { + Contract *IAsyncCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IAsyncTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IAsyncTransactorSession struct { + Contract *IAsyncTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IAsyncRaw is an auto generated low-level Go binding around an Ethereum contract. +type IAsyncRaw struct { + Contract *IAsync // Generic contract binding to access the raw methods on +} + +// IAsyncCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IAsyncCallerRaw struct { + Contract *IAsyncCaller // Generic read-only contract binding to access the raw methods on +} + +// IAsyncTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IAsyncTransactorRaw struct { + Contract *IAsyncTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIAsync creates a new instance of IAsync, bound to a specific deployed contract. +func NewIAsync(address common.Address, backend bind.ContractBackend) (*IAsync, error) { + contract, err := bindIAsync(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IAsync{IAsyncCaller: IAsyncCaller{contract: contract}, IAsyncTransactor: IAsyncTransactor{contract: contract}, IAsyncFilterer: IAsyncFilterer{contract: contract}}, nil +} + +// NewIAsyncCaller creates a new read-only instance of IAsync, bound to a specific deployed contract. +func NewIAsyncCaller(address common.Address, caller bind.ContractCaller) (*IAsyncCaller, error) { + contract, err := bindIAsync(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IAsyncCaller{contract: contract}, nil +} + +// NewIAsyncTransactor creates a new write-only instance of IAsync, bound to a specific deployed contract. +func NewIAsyncTransactor(address common.Address, transactor bind.ContractTransactor) (*IAsyncTransactor, error) { + contract, err := bindIAsync(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IAsyncTransactor{contract: contract}, nil +} + +// NewIAsyncFilterer creates a new log filterer instance of IAsync, bound to a specific deployed contract. +func NewIAsyncFilterer(address common.Address, filterer bind.ContractFilterer) (*IAsyncFilterer, error) { + contract, err := bindIAsync(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IAsyncFilterer{contract: contract}, nil +} + +// bindIAsync binds a generic wrapper to an already deployed contract. +func bindIAsync(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IAsyncMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAsync *IAsyncRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAsync.Contract.IAsyncCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAsync *IAsyncRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAsync.Contract.IAsyncTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IAsync *IAsyncRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAsync.Contract.IAsyncTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IAsync *IAsyncCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IAsync.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IAsync *IAsyncTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IAsync.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IAsync *IAsyncTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IAsync.Contract.contract.Transact(opts, method, params...) +} + +// FutureById is a free data retrieval call binding the contract method 0x012d56e0. +// +// Solidity: function futureById(uint64 futureId) view returns((((uint64,address,string,bytes),(uint64,bytes,uint8)[],(uint64,bytes,bytes))) response) +func (_IAsync *IAsyncCaller) FutureById(opts *bind.CallOpts, futureId uint64) (FutureByIdResponse, error) { + var out []interface{} + err := _IAsync.contract.Call(opts, &out, "futureById", futureId) + + if err != nil { + return *new(FutureByIdResponse), err + } + + out0 := *abi.ConvertType(out[0], new(FutureByIdResponse)).(*FutureByIdResponse) + + return out0, err + +} + +// FutureById is a free data retrieval call binding the contract method 0x012d56e0. +// +// Solidity: function futureById(uint64 futureId) view returns((((uint64,address,string,bytes),(uint64,bytes,uint8)[],(uint64,bytes,bytes))) response) +func (_IAsync *IAsyncSession) FutureById(futureId uint64) (FutureByIdResponse, error) { + return _IAsync.Contract.FutureById(&_IAsync.CallOpts, futureId) +} + +// FutureById is a free data retrieval call binding the contract method 0x012d56e0. +// +// Solidity: function futureById(uint64 futureId) view returns((((uint64,address,string,bytes),(uint64,bytes,uint8)[],(uint64,bytes,bytes))) response) +func (_IAsync *IAsyncCallerSession) FutureById(futureId uint64) (FutureByIdResponse, error) { + return _IAsync.Contract.FutureById(&_IAsync.CallOpts, futureId) +} + +// Futures is a free data retrieval call binding the contract method 0x83817c27. +// +// Solidity: function futures((bytes,uint64,uint64,bool,bool) pagination, address creator) view returns(((bytes,uint64),((uint64,address,string,bytes),(uint64,bytes,uint8)[],(uint64,bytes,bytes))[]) response) +func (_IAsync *IAsyncCaller) Futures(opts *bind.CallOpts, pagination TypesPageRequest, creator common.Address) (FuturesResponse, error) { + var out []interface{} + err := _IAsync.contract.Call(opts, &out, "futures", pagination, creator) + + if err != nil { + return *new(FuturesResponse), err + } + + out0 := *abi.ConvertType(out[0], new(FuturesResponse)).(*FuturesResponse) + + return out0, err + +} + +// Futures is a free data retrieval call binding the contract method 0x83817c27. +// +// Solidity: function futures((bytes,uint64,uint64,bool,bool) pagination, address creator) view returns(((bytes,uint64),((uint64,address,string,bytes),(uint64,bytes,uint8)[],(uint64,bytes,bytes))[]) response) +func (_IAsync *IAsyncSession) Futures(pagination TypesPageRequest, creator common.Address) (FuturesResponse, error) { + return _IAsync.Contract.Futures(&_IAsync.CallOpts, pagination, creator) +} + +// Futures is a free data retrieval call binding the contract method 0x83817c27. +// +// Solidity: function futures((bytes,uint64,uint64,bool,bool) pagination, address creator) view returns(((bytes,uint64),((uint64,address,string,bytes),(uint64,bytes,uint8)[],(uint64,bytes,bytes))[]) response) +func (_IAsync *IAsyncCallerSession) Futures(pagination TypesPageRequest, creator common.Address) (FuturesResponse, error) { + return _IAsync.Contract.Futures(&_IAsync.CallOpts, pagination, creator) +} + +// PendingFutures is a free data retrieval call binding the contract method 0xddebca34. +// +// Solidity: function pendingFutures((bytes,uint64,uint64,bool,bool) pagination) view returns(((bytes,uint64),(uint64,address,string,bytes)[]) response) +func (_IAsync *IAsyncCaller) PendingFutures(opts *bind.CallOpts, pagination TypesPageRequest) (PendingFuturesResponse, error) { + var out []interface{} + err := _IAsync.contract.Call(opts, &out, "pendingFutures", pagination) + + if err != nil { + return *new(PendingFuturesResponse), err + } + + out0 := *abi.ConvertType(out[0], new(PendingFuturesResponse)).(*PendingFuturesResponse) + + return out0, err + +} + +// PendingFutures is a free data retrieval call binding the contract method 0xddebca34. +// +// Solidity: function pendingFutures((bytes,uint64,uint64,bool,bool) pagination) view returns(((bytes,uint64),(uint64,address,string,bytes)[]) response) +func (_IAsync *IAsyncSession) PendingFutures(pagination TypesPageRequest) (PendingFuturesResponse, error) { + return _IAsync.Contract.PendingFutures(&_IAsync.CallOpts, pagination) +} + +// PendingFutures is a free data retrieval call binding the contract method 0xddebca34. +// +// Solidity: function pendingFutures((bytes,uint64,uint64,bool,bool) pagination) view returns(((bytes,uint64),(uint64,address,string,bytes)[]) response) +func (_IAsync *IAsyncCallerSession) PendingFutures(pagination TypesPageRequest) (PendingFuturesResponse, error) { + return _IAsync.Contract.PendingFutures(&_IAsync.CallOpts, pagination) +} + +// AddFuture is a paid mutator transaction binding the contract method 0x58f36d78. +// +// Solidity: function addFuture(string handler, bytes input) returns(uint64 futureId) +func (_IAsync *IAsyncTransactor) AddFuture(opts *bind.TransactOpts, handler string, input []byte) (*types.Transaction, error) { + return _IAsync.contract.Transact(opts, "addFuture", handler, input) +} + +// AddFuture is a paid mutator transaction binding the contract method 0x58f36d78. +// +// Solidity: function addFuture(string handler, bytes input) returns(uint64 futureId) +func (_IAsync *IAsyncSession) AddFuture(handler string, input []byte) (*types.Transaction, error) { + return _IAsync.Contract.AddFuture(&_IAsync.TransactOpts, handler, input) +} + +// AddFuture is a paid mutator transaction binding the contract method 0x58f36d78. +// +// Solidity: function addFuture(string handler, bytes input) returns(uint64 futureId) +func (_IAsync *IAsyncTransactorSession) AddFuture(handler string, input []byte) (*types.Transaction, error) { + return _IAsync.Contract.AddFuture(&_IAsync.TransactOpts, handler, input) +} + +// IAsyncCreateFutureIterator is returned from FilterCreateFuture and is used to iterate over the raw logs and unpacked data for CreateFuture events raised by the IAsync contract. +type IAsyncCreateFutureIterator struct { + Event *IAsyncCreateFuture // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IAsyncCreateFutureIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IAsyncCreateFuture) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IAsyncCreateFuture) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IAsyncCreateFutureIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IAsyncCreateFutureIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IAsyncCreateFuture represents a CreateFuture event raised by the IAsync contract. +type IAsyncCreateFuture struct { + FutureId uint64 + Creator common.Address + Handler string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCreateFuture is a free log retrieval operation binding the contract event 0x5ff36e17a53266688028dda85a1ae26868151e191647b9c731c7a43d5041ac96. +// +// Solidity: event CreateFuture(uint64 indexed futureId, address indexed creator, string handler) +func (_IAsync *IAsyncFilterer) FilterCreateFuture(opts *bind.FilterOpts, futureId []uint64, creator []common.Address) (*IAsyncCreateFutureIterator, error) { + + var futureIdRule []interface{} + for _, futureIdItem := range futureId { + futureIdRule = append(futureIdRule, futureIdItem) + } + var creatorRule []interface{} + for _, creatorItem := range creator { + creatorRule = append(creatorRule, creatorItem) + } + + logs, sub, err := _IAsync.contract.FilterLogs(opts, "CreateFuture", futureIdRule, creatorRule) + if err != nil { + return nil, err + } + return &IAsyncCreateFutureIterator{contract: _IAsync.contract, event: "CreateFuture", logs: logs, sub: sub}, nil +} + +// WatchCreateFuture is a free log subscription operation binding the contract event 0x5ff36e17a53266688028dda85a1ae26868151e191647b9c731c7a43d5041ac96. +// +// Solidity: event CreateFuture(uint64 indexed futureId, address indexed creator, string handler) +func (_IAsync *IAsyncFilterer) WatchCreateFuture(opts *bind.WatchOpts, sink chan<- *IAsyncCreateFuture, futureId []uint64, creator []common.Address) (event.Subscription, error) { + + var futureIdRule []interface{} + for _, futureIdItem := range futureId { + futureIdRule = append(futureIdRule, futureIdItem) + } + var creatorRule []interface{} + for _, creatorItem := range creator { + creatorRule = append(creatorRule, creatorItem) + } + + logs, sub, err := _IAsync.contract.WatchLogs(opts, "CreateFuture", futureIdRule, creatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IAsyncCreateFuture) + if err := _IAsync.contract.UnpackLog(event, "CreateFuture", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCreateFuture is a log parse operation binding the contract event 0x5ff36e17a53266688028dda85a1ae26868151e191647b9c731c7a43d5041ac96. +// +// Solidity: event CreateFuture(uint64 indexed futureId, address indexed creator, string handler) +func (_IAsync *IAsyncFilterer) ParseCreateFuture(log types.Log) (*IAsyncCreateFuture, error) { + event := new(IAsyncCreateFuture) + if err := _IAsync.contract.UnpackLog(event, "CreateFuture", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/src/orders/precompiles/async/IAsync.sol b/src/orders/precompiles/async/IAsync.sol new file mode 100644 index 0000000..e4c965c --- /dev/null +++ b/src/orders/precompiles/async/IAsync.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.18; + +import "../common/Types.sol"; + +/// @dev The IAsync contract's address. +address constant IASYNC_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000903; + +/// @dev The IAsync contract's instance. +IAsync constant IASYNC_CONTRACT = IAsync(IASYNC_PRECOMPILE_ADDRESS); + +struct Future { + uint64 id; + address creator; + string handler; + bytes input; +} + +enum FutureVoteType { + Unspecified, + Verified, + Rejected +} + +struct FutureVote { + uint64 futureId; + bytes Voter; + FutureVoteType vote; +} + +struct FutureResult { + uint64 id; + bytes output; + bytes submitter; +} + +struct FutureResponse { + Future future; + FutureVote[] votes; + FutureResult result; +} + +struct PendingFuturesResponse { + Types.PageResponse pagination; + Future[] futures; +} + +struct FuturesResponse { + Types.PageResponse pagination; + FutureResponse[] futures; +} + +struct FutureByIdResponse { + FutureResponse futureResponse; +} + +/** + * @author Warden Team + * @title x/async Interface + * @dev The interface through which users and solidity contracts will interact with x/async. + * @custom:address 0x0000000000000000000000000000000000000903 + */ +interface IAsync { + /// @dev Defines a method to add a future. + /// @param handler The unique name of the handler + /// @param input The handler's input + /// @return futureId The id of the future + function addFuture( + string calldata handler, + bytes calldata input + ) external returns (uint64 futureId); + + /// @dev Defines a method to query future by id. + /// @param futureId The future id + /// @return response The future reponse + function futureById( + uint64 futureId + ) external view returns (FutureByIdResponse memory response); + + /// @dev Defines a method to query futures. + /// @param pagination The pagination details + /// @param creator Optional creator address filter + /// @return response The paged futures + function futures( + Types.PageRequest calldata pagination, + address creator + ) external view returns (FuturesResponse memory response); + + /// @dev Defines a method to query pending futures. + /// @param pagination The pagination details + /// @return response The paged futures + function pendingFutures( + Types.PageRequest calldata pagination + ) external view returns (PendingFuturesResponse memory response); + + /// @dev CreateFuture defines an Event emitted when a future is created. + /// @param creator The address of the creator + /// @param futureId The future Id + /// @param handler The name of the handler + event CreateFuture( + uint64 indexed futureId, + address indexed creator, + string handler + ); +} diff --git a/src/orders/precompiles/async/Types.abi b/src/orders/precompiles/async/Types.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/src/orders/precompiles/async/Types.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/orders/precompiles/async/abi.json b/src/orders/precompiles/async/abi.json new file mode 100644 index 0000000..aed0c45 --- /dev/null +++ b/src/orders/precompiles/async/abi.json @@ -0,0 +1,392 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "futureId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "handler", + "type": "string" + } + ], + "name": "CreateFuture", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "handler", + "type": "string" + }, + { + "internalType": "bytes", + "name": "input", + "type": "bytes" + } + ], + "name": "addFuture", + "outputs": [ + { + "internalType": "uint64", + "name": "futureId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "futureId", + "type": "uint64" + } + ], + "name": "futureById", + "outputs": [ + { + "components": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "handler", + "type": "string" + }, + { + "internalType": "bytes", + "name": "input", + "type": "bytes" + } + ], + "internalType": "struct Future", + "name": "future", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "futureId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "Voter", + "type": "bytes" + }, + { + "internalType": "enum FutureVoteType", + "name": "vote", + "type": "uint8" + } + ], + "internalType": "struct FutureVote[]", + "name": "votes", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "output", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "submitter", + "type": "bytes" + } + ], + "internalType": "struct FutureResult", + "name": "result", + "type": "tuple" + } + ], + "internalType": "struct FutureResponse", + "name": "futureResponse", + "type": "tuple" + } + ], + "internalType": "struct FutureByIdResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pagination", + "type": "tuple" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + } + ], + "name": "futures", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pagination", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "handler", + "type": "string" + }, + { + "internalType": "bytes", + "name": "input", + "type": "bytes" + } + ], + "internalType": "struct Future", + "name": "future", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "futureId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "Voter", + "type": "bytes" + }, + { + "internalType": "enum FutureVoteType", + "name": "vote", + "type": "uint8" + } + ], + "internalType": "struct FutureVote[]", + "name": "votes", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "output", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "submitter", + "type": "bytes" + } + ], + "internalType": "struct FutureResult", + "name": "result", + "type": "tuple" + } + ], + "internalType": "struct FutureResponse[]", + "name": "futures", + "type": "tuple[]" + } + ], + "internalType": "struct FuturesResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pagination", + "type": "tuple" + } + ], + "name": "pendingFutures", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pagination", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "handler", + "type": "string" + }, + { + "internalType": "bytes", + "name": "input", + "type": "bytes" + } + ], + "internalType": "struct Future[]", + "name": "futures", + "type": "tuple[]" + } + ], + "internalType": "struct PendingFuturesResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } + ] +} diff --git a/src/orders/precompiles/async/async.go b/src/orders/precompiles/async/async.go new file mode 100644 index 0000000..15a3502 --- /dev/null +++ b/src/orders/precompiles/async/async.go @@ -0,0 +1,148 @@ +package async + +import ( + "embed" + "fmt" + + "cosmossdk.io/log" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + ethcmn "github.com/ethereum/go-ethereum/common" + evmoscmn "github.com/evmos/evmos/v20/precompiles/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + "github.com/warden-protocol/wardenprotocol/precompiles/common" + asyncmodulekeeper "github.com/warden-protocol/wardenprotocol/warden/x/async/keeper" + types "github.com/warden-protocol/wardenprotocol/warden/x/async/types/v1beta1" +) + +var _ vm.PrecompiledContract = &Precompile{} + +const PrecompileAddress = "0x0000000000000000000000000000000000000903" + +// Embed abi json file to the executable binary. Needed when importing as dependency. +// +//go:embed abi.json +var f embed.FS + +// Precompile defines the precompiled contract for x/async. +type Precompile struct { + evmoscmn.Precompile + asyncmodulekeeper asyncmodulekeeper.Keeper + eventsRegistry *common.EthEventsRegistry + queryServer types.QueryServer +} + +// LoadABI loads the x/async ABI from the embedded abi.json file +// for the x/async precompile. +func LoadABI() (abi.ABI, error) { + return evmoscmn.LoadABI(f, "abi.json") +} + +func NewPrecompile(asynckeeper asyncmodulekeeper.Keeper, er *common.EthEventsRegistry) (*Precompile, error) { + abi, err := LoadABI() + if err != nil { + return nil, err + } + + p := Precompile{ + Precompile: evmoscmn.Precompile{ + ABI: abi, + KvGasConfig: storetypes.KVGasConfig(), + TransientKVGasConfig: storetypes.TransientGasConfig(), + }, + asyncmodulekeeper: asynckeeper, + eventsRegistry: er, + queryServer: asyncmodulekeeper.NewQueryServerImpl(asynckeeper), + } + + p.SetAddress(p.Address()) + + return &p, nil +} + +// Address implements vm.PrecompiledContract. +func (p *Precompile) Address() ethcmn.Address { + return ethcmn.HexToAddress(PrecompileAddress) +} + +// RequiredGas implements vm.PrecompiledContract. +// Subtle: this method shadows the method (Precompile).RequiredGas of Precompile.Precompile. +func (p *Precompile) RequiredGas(input []byte) uint64 { + // NOTE: This check avoid panicking when trying to decode the method ID + if len(input) < 4 { + return 0 + } + + methodID := input[:4] + + method, err := p.MethodById(methodID) + if err != nil { + // This should never happen since this method is going to fail during Run + return 0 + } + + return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name)) +} + +// Run implements vm.PrecompiledContract. +func (p *Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) (bz []byte, err error) { + ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readonly, p.IsTransaction) + if err != nil { + return nil, err + } + + // This handles any out of gas errors that may occur during the execution of a precompile tx or query. + // It avoids panics and returns the out of gas error so the EVM can continue gracefully. + defer evmoscmn.HandleGasError(ctx, contract, initialGas, &err)() + + switch method.Name { + // transactions + case AddFutureMethod: + bz, err = p.AddFutureMethod(ctx, evm.Origin, stateDB, method, args) + // queries + case FutureByIdMethod: + bz, err = p.FutureByIdMethod(ctx, method, args) + case FuturesMethod: + bz, err = p.FuturesMethod(ctx, method, args) + case PendingFuturesMethod: + bz, err = p.PendingFuturesMethod(ctx, method, args) + } + + if err != nil { + return nil, err + } + + cost := ctx.GasMeter().GasConsumed() - initialGas + + if !contract.UseGas(cost) { + return nil, vm.ErrOutOfGas + } + + if err := p.AddJournalEntries(stateDB, snapshot); err != nil { + return nil, err + } + + return bz, nil +} + +func (p *Precompile) IsTransaction(method string) bool { + switch method { + // transactions + case AddFutureMethod: + return true + // queries + case FutureByIdMethod, + FuturesMethod, + PendingFuturesMethod: + return false + } + panic(fmt.Errorf("async precompile: method not exists: %s", method)) +} + +// Logger returns a precompile-specific logger. +func (p *Precompile) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("evm extension", "async") +} diff --git a/src/orders/precompiles/async/events.go b/src/orders/precompiles/async/events.go new file mode 100644 index 0000000..29133bb --- /dev/null +++ b/src/orders/precompiles/async/events.go @@ -0,0 +1,58 @@ +package async + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + ethtypes "github.com/ethereum/go-ethereum/core/types" + evmoscmn "github.com/evmos/evmos/v20/precompiles/common" + + ethcmn "github.com/ethereum/go-ethereum/common" + + "github.com/warden-protocol/wardenprotocol/precompiles/common" + "github.com/warden-protocol/wardenprotocol/warden/x/async/types/v1beta1" +) + +const ( + // EventCreateFuture defines the event type for the x/async CreateFuture transaction. + EventCreateFuture = "CreateFuture" +) + +// GetCreateFutureEvent Map EventCreateFuture to eth CreateFuture event and write to eth log +func (p *Precompile) GetCreateFutureEvent(ctx sdk.Context, writerAddress *ethcmn.Address, sdkEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventCreateFuture] + + topics := make([]ethcmn.Hash, 3) + topics[0] = event.ID + + typedEvent := v1beta1.EventCreateFuture{} + if err := common.ParseSdkEvent(sdkEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + packed, err := event.Inputs.NonIndexed().Pack( + typedEvent.GetHandler(), + ) + if err != nil { + return nil, err + } + + creatorAddress, err := common.AddressFromBech32Str(typedEvent.GetCreator()) + if err != nil { + return nil, err + } + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + topics[2], err = evmoscmn.MakeTopic(creatorAddress) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: packed, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} diff --git a/src/orders/precompiles/async/query.go b/src/orders/precompiles/async/query.go new file mode 100644 index 0000000..c734318 --- /dev/null +++ b/src/orders/precompiles/async/query.go @@ -0,0 +1,166 @@ +package async + +import ( + "fmt" + + wardencommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + types "github.com/warden-protocol/wardenprotocol/warden/x/async/types/v1beta1" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +const ( + FutureByIdMethod = "futureById" + FuturesMethod = "futures" + PendingFuturesMethod = "pendingFutures" +) + +// FutureByIdMethod constructs QueryFutureByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) FutureByIdMethod( + ctx sdk.Context, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newFutureByIdRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.FutureById(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(FutureByIdResponse).FromResponse(response) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newFutureByIdRequest(method *abi.Method, args []interface{}) (*types.QueryFutureByIdRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input futureByIdInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to futureByIdInput struct: %w", err) + } + + return &types.QueryFutureByIdRequest{ + Id: input.Id, + }, nil +} + +type futureByIdInput struct { + Id uint64 +} + +// FuturesMethod constructs QueryFuturesRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) FuturesMethod( + ctx sdk.Context, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newFuturesRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.Futures(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(FuturesResponse).FromResponse(response) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newFuturesRequest(method *abi.Method, args []interface{}) (*types.QueryFuturesRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + var input futuresInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to futuresInput struct: %w", err) + } + + var creator string + if input.Creator == (common.Address{}) { + creator = "" + } else { + creator = wardencommon.Bech32StrFromAddress(input.Creator) + } + + return &types.QueryFuturesRequest{ + Pagination: &input.PageRequest, + Creator: creator, + }, nil +} + +type futuresInput struct { + PageRequest query.PageRequest `abi:"pagination"` + Creator common.Address `abi:"creator"` +} + +// PendingFuturesMethod constructs QueryPendingFuturesRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) PendingFuturesMethod( + ctx sdk.Context, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newPendingFuturesRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.PendingFutures(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(PendingFuturesResponse).FromResponse(response) + if err != nil { + return nil, err + } + + return method.Outputs.Pack(out) +} + +func newPendingFuturesRequest(method *abi.Method, args []interface{}) (*types.QueryPendingFuturesRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input pendingFuturesInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to pendingFuturesInput struct: %w", err) + } + + return &types.QueryPendingFuturesRequest{ + Pagination: &input.PageRequest, + }, nil +} + +type pendingFuturesInput struct { + PageRequest query.PageRequest `abi:"pagination"` +} diff --git a/src/orders/precompiles/async/tx.go b/src/orders/precompiles/async/tx.go new file mode 100644 index 0000000..b9d3938 --- /dev/null +++ b/src/orders/precompiles/async/tx.go @@ -0,0 +1,76 @@ +package async + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + actmodulekeeper "github.com/warden-protocol/wardenprotocol/warden/x/async/keeper" + acttypes "github.com/warden-protocol/wardenprotocol/warden/x/async/types/v1beta1" +) + +const ( + AddFutureMethod = "addFuture" +) + +// AddFutureMethod constructs MsgAddFuture from args, passes it to msg server and packs corresponding abi output. +func (p *Precompile) AddFutureMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actmodulekeeper.NewMsgServerImpl(p.asyncmodulekeeper) + + message, err := newMsgAddFuture(args, origin, method) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + response, err := msgServer.AddFuture(ctx, message) + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(response.Id) +} + +func newMsgAddFuture(args []interface{}, origin common.Address, method *abi.Method) (*acttypes.MsgAddFuture, error) { + if len(args) != 2 { + return nil, precommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + authority := precommon.Bech32StrFromAddress(origin) + + var input addFutureInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to addFutureInput struct: %w", err) + } + + return &acttypes.MsgAddFuture{ + Creator: authority, + Input: input.Input, + Handler: input.Handler, + }, nil +} + +type addFutureInput struct { + Handler string + Input []byte +} diff --git a/src/orders/precompiles/async/types.go b/src/orders/precompiles/async/types.go new file mode 100644 index 0000000..1218cad --- /dev/null +++ b/src/orders/precompiles/async/types.go @@ -0,0 +1,152 @@ +package async + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/ethereum/go-ethereum/common" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + types "github.com/warden-protocol/wardenprotocol/warden/x/async/types/v1beta1" +) + +// FuturesInput needed to unmarshal Pagination field and pass it to types.QueryFuturesRequest +type FuturesInput struct { + Pagination query.PageRequest `abi:"pagination"` + Creator common.Address `abi:"creator"` +} + +// FromResponse needed to map QueryFuturesResponse to FuturesResponse +func (r *FuturesResponse) FromResponse(res *types.QueryFuturesResponse) (FuturesResponse, error) { + if res != nil { + futures := make([]FutureResponse, 0, len(res.Futures)) + for _, future := range res.Futures { + mappedFuture, err := mapFutureResponse(future) + if err != nil { + return FuturesResponse{}, err + } + + futures = append(futures, mappedFuture) + } + + r.Futures = futures + r.Pagination = mapPageResponse(res.Pagination) + } + + return *r, nil +} + +// FromResponse needed to map QueryPendingFuturesResponse to PendingFuturesResponse +func (r *PendingFuturesResponse) FromResponse(res *types.QueryPendingFuturesResponse) (PendingFuturesResponse, error) { + if res != nil { + futures := make([]Future, 0, len(res.Futures)) + for _, future := range res.Futures { + mappedFuture, err := mapFuture(future) + if err != nil { + return PendingFuturesResponse{}, err + } + + futures = append(futures, mappedFuture) + } + + r.Futures = futures + r.Pagination = mapPageResponse(res.Pagination) + } + + return *r, nil +} + +// FromResponse needed to map QueryFutureByIdResponse to FutureByIdResponse +func (r *FutureByIdResponse) FromResponse(res *types.QueryFutureByIdResponse) (FutureByIdResponse, error) { + if res != nil { + mappedFutureResponse, err := mapFutureResponse(res.FutureResponse) + if err != nil { + return FutureByIdResponse{}, err + } + + r.FutureResponse = mappedFutureResponse + } + + return *r, nil +} + +func mapFuture(future types.Future) (Future, error) { + creator, err := precommon.AddressFromBech32Str(future.Creator) + if err != nil { + return Future{}, fmt.Errorf("invalid creator: %w", err) + } + + return Future{ + Id: future.Id, + Creator: creator, + Handler: future.Handler, + Input: future.Input, + }, nil +} + +func mapFutureResponse(futureResponse types.FutureResponse) (FutureResponse, error) { + future, err := mapFuture(futureResponse.Future) + if err != nil { + return FutureResponse{}, err + } + + votes, err := mapVotes(futureResponse.Votes) + if err != nil { + return FutureResponse{}, err + } + + futureResult, err := mapFutureResult(futureResponse.Result) + if err != nil { + return FutureResponse{}, err + } + + return FutureResponse{ + Future: future, + Votes: votes, + Result: futureResult, + }, nil +} + +func mapVotes(values []types.FutureVote) ([]FutureVote, error) { + result := make([]FutureVote, 0, len(values)) + for _, v := range values { + mappedTemplate, err := mapVote(v) + if err != nil { + return nil, err + } + + result = append(result, mappedTemplate) + } + return result, nil +} + +func mapVote(value types.FutureVote) (FutureVote, error) { + return FutureVote{ + Voter: value.Voter, + FutureId: value.FutureId, + Vote: uint8(value.Vote), + }, nil +} + +func mapFutureResult(value *types.FutureResult) (FutureResult, error) { + if value == nil { + return FutureResult{}, nil + } + + return FutureResult{ + Id: value.Id, + Output: value.Output, + Submitter: value.Submitter, + }, nil +} + +func mapPageResponse(value *query.PageResponse) TypesPageResponse { + if value == nil { + return TypesPageResponse{} + } + + return TypesPageResponse{ + NextKey: value.NextKey, + Total: value.Total, + } +} diff --git a/src/orders/precompiles/common/Types.sol b/src/orders/precompiles/common/Types.sol new file mode 100644 index 0000000..cb29130 --- /dev/null +++ b/src/orders/precompiles/common/Types.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.18; + +library Types { + struct AnyType { + string typeUrl; + bytes value; + } + + struct Timestamp { + uint64 secs; + uint64 nanos; + } + +/// @dev Dec represents a fixed point decimal value. The value is stored as an integer, and the +/// precision is stored as a uint8. The value is multiplied by 10^precision to get the actual value. + struct Dec { + uint256 value; + uint8 precision; + } + +/// @dev Coin is a struct that represents a token with a denomination and an amount. + struct Coin { + string denom; + uint256 amount; + } + +/// @dev DecCoin is a struct that represents a token with a denomination, an amount and a precision. + struct DecCoin { + string denom; + uint256 amount; + uint8 precision; + } + +/// @dev PageResponse is a struct that represents a page response. + struct PageResponse { + bytes nextKey; + uint64 total; + } + +/// @dev PageRequest is a struct that represents a page request. + struct PageRequest { + bytes key; + uint64 offset; + uint64 limit; + bool countTotal; + bool reverse; + } + +/// @dev Height is a monotonically increasing data type +/// that can be compared against another Height for the purposes of updating and +/// freezing clients +/// +/// Normally the RevisionHeight is incremented at each height while keeping +/// RevisionNumber the same. However some consensus algorithms may choose to +/// reset the height in certain conditions e.g. hard forks, state-machine +/// breaking changes In these cases, the RevisionNumber is incremented so that +/// height continues to be monotonically increasing even as the RevisionHeight +/// gets reset + struct Height { + // the revision that the client is currently on + uint64 revisionNumber; + // the height within the given revision + uint64 revisionHeight; + } +} diff --git a/src/orders/precompiles/common/address.go b/src/orders/precompiles/common/address.go new file mode 100644 index 0000000..7c7e1d1 --- /dev/null +++ b/src/orders/precompiles/common/address.go @@ -0,0 +1,50 @@ +package common + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" +) + +// Bech32StrFromAddress Creates bech32 address string from eth address +func Bech32StrFromAddress(address common.Address) string { + return sdk.AccAddress(address.Bytes()).String() +} + +func Bech32StrFromBytes(address []byte) string { + return sdk.AccAddress(address).String() +} + +// AddressFromBech32Str Creates eth address from bech32 address string +func AddressFromBech32Str(address string) (common.Address, error) { + accAddress, err := sdk.AccAddressFromBech32(address) + if err != nil { + return common.Address{}, err + } + + return common.BytesToAddress(accAddress.Bytes()), nil +} + +// AddressesFromBech32StrItemArray tries to create a slice of common.Address values from arbitrary slice +func AddressesFromBech32StrItemArray[T any](items []T, addressFunc func(T) string) ([]common.Address, error) { + ethAddresses := make([]common.Address, 0, len(items)) + + for _, item := range items { + ethAddress, err := AddressFromBech32Str(addressFunc(item)) + if err != nil { + return nil, err + } + + ethAddresses = append(ethAddresses, ethAddress) + } + + return ethAddresses, nil +} + +// AddressesFromBech32StrArray tries to create a slice of common.Address values from a string slice +func AddressesFromBech32StrArray(items []string) ([]common.Address, error) { + id := func(i string) string { + return i + } + + return AddressesFromBech32StrItemArray(items, id) +} diff --git a/src/orders/precompiles/common/events.go b/src/orders/precompiles/common/events.go new file mode 100644 index 0000000..625adef --- /dev/null +++ b/src/orders/precompiles/common/events.go @@ -0,0 +1,22 @@ +package common + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" +) + +// Takes sdk.Event as proto msg, passes it to fillEvent. +// fillEvent should create typed event for caller. +func ParseSdkEvent(sdkEvent sdk.Event, fillEvent func(proto.Message)) error { + events := sdk.EmptyEvents().AppendEvent(sdkEvent).ToABCIEvents() + event := events[0] + + msg, err := sdk.ParseTypedEvent(event) + if err != nil { + return err + } + + fillEvent(msg) + + return nil +} diff --git a/src/orders/precompiles/common/eventsRegisty.go b/src/orders/precompiles/common/eventsRegisty.go new file mode 100644 index 0000000..0812b53 --- /dev/null +++ b/src/orders/precompiles/common/eventsRegisty.go @@ -0,0 +1,53 @@ +package common + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + ethcmn "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/evmos/evmos/v20/x/evm/core/vm" +) + +// EthEventsRegistry maps sdk.Event types to functions that construct and write to log corresponding eth events +type EthEventsRegistry struct { + p map[string]EthEventProvider +} + +// EthEventProvider an event provider func definition +type EthEventProvider func(sdk.Context, *ethcmn.Address, sdk.Event) (*ethtypes.Log, error) + +// RegisterEvent registers a provider for eventType +func (r *EthEventsRegistry) RegisterEvent(eventType string, ethEventProvider EthEventProvider) { + r.p[eventType] = ethEventProvider +} + +// getEventProvider returns a provider for a registered event type +func (r *EthEventsRegistry) getEventProvider(eventType string) EthEventProvider { + if provider, ok := r.p[eventType]; ok { + return provider + } + + return nil +} + +func NewEthEventsRegistry() *EthEventsRegistry { + return &EthEventsRegistry{ + p: make(map[string]EthEventProvider), + } +} + +// EmitEvents iterates through current transaction sdk events and writes eth event to log if sdk event registered in events registry +func (r *EthEventsRegistry) EmitEvents(ctx sdk.Context, stateDB vm.StateDB, address *ethcmn.Address) error { + for _, x := range ctx.EventManager().Events() { + if provider := r.getEventProvider(x.Type); provider != nil { + log, err := provider(ctx, address, x) + if err != nil { + return err + } + if log != nil { + stateDB.AddLog(log) + } + } + } + + return nil +} diff --git a/src/orders/precompiles/common/pagination.go b/src/orders/precompiles/common/pagination.go new file mode 100644 index 0000000..66ff765 --- /dev/null +++ b/src/orders/precompiles/common/pagination.go @@ -0,0 +1,19 @@ +package common + +import ( + "bytes" + + "github.com/cosmos/cosmos-sdk/types/query" +) + +func ClearPaginationKey(pagination *query.PageRequest) *query.PageRequest { + if pagination == nil { + return nil + } + + if bytes.Equal(pagination.Key, []byte{0}) { + pagination.Key = nil + } + + return pagination +} diff --git a/src/orders/precompiles/common/validation.go b/src/orders/precompiles/common/validation.go new file mode 100644 index 0000000..dc42725 --- /dev/null +++ b/src/orders/precompiles/common/validation.go @@ -0,0 +1,12 @@ +package common + +import "fmt" + +type WrongArgsNumber struct { + Expected int + Got int +} + +func (e WrongArgsNumber) Error() string { + return fmt.Sprintf("invalid number of arguments; expected %d; got: %d", e.Expected, e.Got) +} diff --git a/src/orders/precompiles/justfile b/src/orders/precompiles/justfile new file mode 100644 index 0000000..6a03006 --- /dev/null +++ b/src/orders/precompiles/justfile @@ -0,0 +1,24 @@ +git_root := `git rev-parse --show-toplevel` +tmpdir := `mktemp -d` + +all: abi + +_tools: + @command -v solc >/dev/null 2>&1 || (echo "solc not found. Please install solc. On MacOS, you can use 'brew install solidity'." && exit 1) + go install github.com/ethereum/go-ethereum/cmd/abigen + +abi: _tools + just generate_artifacts act IAct + just generate_artifacts warden IWarden + just generate_artifacts slinky ISlinky + just generate_artifacts async IAsync + +generate_artifacts target type: + solc --evm-version paris --abi {{git_root}}/precompiles/{{target}}/{{type}}.sol -o {{git_root}}/precompiles/{{target}}/ --overwrite + mv {{git_root}}/precompiles/{{target}}/{{type}}.abi {{git_root}}/precompiles/{{target}}/abi.json + abigen --abi {{git_root}}/precompiles/{{target}}/abi.json --pkg {{target}} --type {{type}} --out {{git_root}}/precompiles/{{target}}/{{type}}.go + + # pretty print the abi + echo '{"abi":[]}' > {{git_root}}/precompiles/{{target}}/formatted.json + echo "$(jq '.abi += inputs' {{git_root}}/precompiles/{{target}}/formatted.json {{git_root}}/precompiles/{{target}}/abi.json)" > {{git_root}}/precompiles/{{target}}/formatted.json + mv {{git_root}}/precompiles/{{target}}/formatted.json {{git_root}}/precompiles/{{target}}/abi.json \ No newline at end of file diff --git a/src/orders/precompiles/precompiles.go b/src/orders/precompiles/precompiles.go new file mode 100644 index 0000000..94899bb --- /dev/null +++ b/src/orders/precompiles/precompiles.go @@ -0,0 +1,77 @@ +package precompiles + +import ( + ethcmn "github.com/ethereum/go-ethereum/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + oraclekeeper "github.com/skip-mev/slinky/x/oracle/keeper" + + actprecompile "github.com/warden-protocol/wardenprotocol/precompiles/act" + asyncprecompile "github.com/warden-protocol/wardenprotocol/precompiles/async" + cmn "github.com/warden-protocol/wardenprotocol/precompiles/common" + slinkyprecompile "github.com/warden-protocol/wardenprotocol/precompiles/slinky" + wardenprecompile "github.com/warden-protocol/wardenprotocol/precompiles/warden" + actkeeper "github.com/warden-protocol/wardenprotocol/warden/x/act/keeper" + asynckeeper "github.com/warden-protocol/wardenprotocol/warden/x/async/keeper" + wardenkeeper "github.com/warden-protocol/wardenprotocol/warden/x/warden/keeper" +) + +// Single point of all wardenprotocol precompiles initialization, including precompiles and events registry +func NewWardenPrecompiles( + wardenkeeper wardenkeeper.Keeper, + actkeeper actkeeper.Keeper, + oraclekeeper oraclekeeper.Keeper, + asynckeeper asynckeeper.Keeper) (map[ethcmn.Address]vm.PrecompiledContract, error) { + precompiles := make(map[ethcmn.Address]vm.PrecompiledContract) + eventsRegistry := cmn.NewEthEventsRegistry() + + newActPrecompile, err := actprecompile.NewPrecompile(actkeeper, eventsRegistry) + if err != nil { + return nil, err + } + precompiles[newActPrecompile.Address()] = newActPrecompile + + eventsRegistry.RegisterEvent("warden.act.v1beta1.EventActionStateChange", newActPrecompile.GetActionStateChangeEvent) + eventsRegistry.RegisterEvent("warden.act.v1beta1.EventCreateTemplate", newActPrecompile.GetCreateTemplateEvent) + eventsRegistry.RegisterEvent("warden.act.v1beta1.EventActionVoted", newActPrecompile.GetActionVotedEvent) + eventsRegistry.RegisterEvent("warden.act.v1beta1.EventUpdateTemplate", newActPrecompile.GetUpdateTemplateEvent) + eventsRegistry.RegisterEvent("warden.act.v1beta1.EventCreateAction", newActPrecompile.GetCreateActionEvent) + + newWardenPrecompile, err := wardenprecompile.NewPrecompile(wardenkeeper, actkeeper, eventsRegistry) + if err != nil { + return nil, err + } + precompiles[newWardenPrecompile.Address()] = newWardenPrecompile + + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventAddKeychainAdmin", newWardenPrecompile.GetAddKeychainAdminEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventAddKeychainWriter", newWardenPrecompile.GetAddKeychainWriterEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventNewKey", newWardenPrecompile.GetNewKeyEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventRejectKeyRequest", newWardenPrecompile.GetRejectKeyRequestEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventFulfilSignRequest", newWardenPrecompile.GetFulfilSignRequestEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventRejectSignRequest", newWardenPrecompile.GetRejectSignRequestEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventNewKeychain", newWardenPrecompile.GetNewKeychainEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventCreateSpace", newWardenPrecompile.GetNewSpaceEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventRemoveKeychainAdmin", newWardenPrecompile.GetRemoveKeychainAdminEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventUpdateKeychain", newWardenPrecompile.GetUpdateKeychainEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventAddSpaceOwner", newWardenPrecompile.GetAddSpaceOwnerEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventRemoveSpaceOwner", newWardenPrecompile.GetRemoveSpaceOwnerEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventNewKeyRequest", newWardenPrecompile.GetNewKeyRequestEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventNewSignRequest", newWardenPrecompile.GetNewSignRequestEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventUpdateKey", newWardenPrecompile.GetUpdateKeyEvent) + eventsRegistry.RegisterEvent("warden.warden.v1beta3.EventUpdateSpace", newWardenPrecompile.GetUpdateSpaceEvent) + + newSlinkyPrecompile, err := slinkyprecompile.NewPrecompile(oraclekeeper, eventsRegistry) + if err != nil { + return nil, err + } + precompiles[newSlinkyPrecompile.Address()] = newSlinkyPrecompile + + newAsyncPrecompile, err := asyncprecompile.NewPrecompile(asynckeeper, eventsRegistry) + if err != nil { + return nil, err + } + precompiles[newAsyncPrecompile.Address()] = newAsyncPrecompile + + eventsRegistry.RegisterEvent("warden.async.v1beta1.EventCreateFuture", newAsyncPrecompile.GetCreateFutureEvent) + + return precompiles, nil +} diff --git a/src/orders/precompiles/slinky/ISlinky.go b/src/orders/precompiles/slinky/ISlinky.go new file mode 100644 index 0000000..225a796 --- /dev/null +++ b/src/orders/precompiles/slinky/ISlinky.go @@ -0,0 +1,226 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package slinky + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// GetPriceResponse is an auto generated low-level Go binding around an user-defined struct. +type GetPriceResponse struct { + Id uint64 + Nonce uint64 + Decimals uint64 + Price QuotePrice +} + +// QuotePrice is an auto generated low-level Go binding around an user-defined struct. +type QuotePrice struct { + BlockHeight uint64 + BlockTimestamp *big.Int + Price *big.Int +} + +// ISlinkyMetaData contains all meta data concerning the ISlinky contract. +var ISlinkyMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"base\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"quote\",\"type\":\"string\"}],\"name\":\"getPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"decimals\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"blockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"price\",\"type\":\"uint256\"}],\"internalType\":\"structQuotePrice\",\"name\":\"price\",\"type\":\"tuple\"}],\"internalType\":\"structGetPriceResponse\",\"name\":\"response\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// ISlinkyABI is the input ABI used to generate the binding from. +// Deprecated: Use ISlinkyMetaData.ABI instead. +var ISlinkyABI = ISlinkyMetaData.ABI + +// ISlinky is an auto generated Go binding around an Ethereum contract. +type ISlinky struct { + ISlinkyCaller // Read-only binding to the contract + ISlinkyTransactor // Write-only binding to the contract + ISlinkyFilterer // Log filterer for contract events +} + +// ISlinkyCaller is an auto generated read-only Go binding around an Ethereum contract. +type ISlinkyCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ISlinkyTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ISlinkyTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ISlinkyFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ISlinkyFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ISlinkySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ISlinkySession struct { + Contract *ISlinky // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ISlinkyCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ISlinkyCallerSession struct { + Contract *ISlinkyCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ISlinkyTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ISlinkyTransactorSession struct { + Contract *ISlinkyTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ISlinkyRaw is an auto generated low-level Go binding around an Ethereum contract. +type ISlinkyRaw struct { + Contract *ISlinky // Generic contract binding to access the raw methods on +} + +// ISlinkyCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ISlinkyCallerRaw struct { + Contract *ISlinkyCaller // Generic read-only contract binding to access the raw methods on +} + +// ISlinkyTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ISlinkyTransactorRaw struct { + Contract *ISlinkyTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewISlinky creates a new instance of ISlinky, bound to a specific deployed contract. +func NewISlinky(address common.Address, backend bind.ContractBackend) (*ISlinky, error) { + contract, err := bindISlinky(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ISlinky{ISlinkyCaller: ISlinkyCaller{contract: contract}, ISlinkyTransactor: ISlinkyTransactor{contract: contract}, ISlinkyFilterer: ISlinkyFilterer{contract: contract}}, nil +} + +// NewISlinkyCaller creates a new read-only instance of ISlinky, bound to a specific deployed contract. +func NewISlinkyCaller(address common.Address, caller bind.ContractCaller) (*ISlinkyCaller, error) { + contract, err := bindISlinky(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ISlinkyCaller{contract: contract}, nil +} + +// NewISlinkyTransactor creates a new write-only instance of ISlinky, bound to a specific deployed contract. +func NewISlinkyTransactor(address common.Address, transactor bind.ContractTransactor) (*ISlinkyTransactor, error) { + contract, err := bindISlinky(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ISlinkyTransactor{contract: contract}, nil +} + +// NewISlinkyFilterer creates a new log filterer instance of ISlinky, bound to a specific deployed contract. +func NewISlinkyFilterer(address common.Address, filterer bind.ContractFilterer) (*ISlinkyFilterer, error) { + contract, err := bindISlinky(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ISlinkyFilterer{contract: contract}, nil +} + +// bindISlinky binds a generic wrapper to an already deployed contract. +func bindISlinky(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ISlinkyABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ISlinky *ISlinkyRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ISlinky.Contract.ISlinkyCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ISlinky *ISlinkyRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ISlinky.Contract.ISlinkyTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ISlinky *ISlinkyRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ISlinky.Contract.ISlinkyTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ISlinky *ISlinkyCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ISlinky.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ISlinky *ISlinkyTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ISlinky.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ISlinky *ISlinkyTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ISlinky.Contract.contract.Transact(opts, method, params...) +} + +// GetPrice is a free data retrieval call binding the contract method 0x3d0f34da. +// +// Solidity: function getPrice(string base, string quote) view returns((uint64,uint64,uint64,(uint64,uint256,uint256)) response) +func (_ISlinky *ISlinkyCaller) GetPrice(opts *bind.CallOpts, base string, quote string) (GetPriceResponse, error) { + var out []interface{} + err := _ISlinky.contract.Call(opts, &out, "getPrice", base, quote) + + if err != nil { + return *new(GetPriceResponse), err + } + + out0 := *abi.ConvertType(out[0], new(GetPriceResponse)).(*GetPriceResponse) + + return out0, err + +} + +// GetPrice is a free data retrieval call binding the contract method 0x3d0f34da. +// +// Solidity: function getPrice(string base, string quote) view returns((uint64,uint64,uint64,(uint64,uint256,uint256)) response) +func (_ISlinky *ISlinkySession) GetPrice(base string, quote string) (GetPriceResponse, error) { + return _ISlinky.Contract.GetPrice(&_ISlinky.CallOpts, base, quote) +} + +// GetPrice is a free data retrieval call binding the contract method 0x3d0f34da. +// +// Solidity: function getPrice(string base, string quote) view returns((uint64,uint64,uint64,(uint64,uint256,uint256)) response) +func (_ISlinky *ISlinkyCallerSession) GetPrice(base string, quote string) (GetPriceResponse, error) { + return _ISlinky.Contract.GetPrice(&_ISlinky.CallOpts, base, quote) +} diff --git a/src/orders/precompiles/slinky/ISlinky.sol b/src/orders/precompiles/slinky/ISlinky.sol new file mode 100644 index 0000000..74211d8 --- /dev/null +++ b/src/orders/precompiles/slinky/ISlinky.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.18; + +/// @dev The ISlinky contract's address. +address constant ISLINKY_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000902; + +/// @dev The ISlinky contract's instance. +ISlinky constant ISLINKY_CONTRACT = ISlinky(ISLINKY_PRECOMPILE_ADDRESS); + +struct GetPriceResponse { + uint64 id; + uint64 nonce; + uint64 decimals; + QuotePrice price; +} + +struct QuotePrice { + uint64 blockHeight; + uint256 blockTimestamp; + uint256 price; +} + +/** + * @author Warden Team + * @title x/slinky Interface + * @dev The interface through which users and solidity contracts will interact with x/slinky. + * @custom:address 0x0000000000000000000000000000000000000902 + */ +interface ISlinky { + /// @dev Defines a method to query the price of a coin. + /// @param base The base coin name for the price + /// @param quote The quote coin name for the price + /// @return response The coin price if found + function getPrice( + string calldata base, + string calldata quote + ) external view returns (GetPriceResponse memory response); +} diff --git a/src/orders/precompiles/slinky/abi.json b/src/orders/precompiles/slinky/abi.json new file mode 100644 index 0000000..5f86031 --- /dev/null +++ b/src/orders/precompiles/slinky/abi.json @@ -0,0 +1,67 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "base", + "type": "string" + }, + { + "internalType": "string", + "name": "quote", + "type": "string" + } + ], + "name": "getPrice", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "decimals", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockHeight", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "internalType": "struct QuotePrice", + "name": "price", + "type": "tuple" + } + ], + "internalType": "struct GetPriceResponse", + "name": "response", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } + ] +} diff --git a/src/orders/precompiles/slinky/query.go b/src/orders/precompiles/slinky/query.go new file mode 100644 index 0000000..62c1bc8 --- /dev/null +++ b/src/orders/precompiles/slinky/query.go @@ -0,0 +1,90 @@ +package slinky + +import ( + "errors" + "fmt" + "math/big" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + slinkytypes "github.com/skip-mev/slinky/pkg/types" + oracletypes "github.com/skip-mev/slinky/x/oracle/types" + + wardencommon "github.com/warden-protocol/wardenprotocol/precompiles/common" +) + +const ( + GetPrice = "getPrice" +) + +// GetPriceQuery constructs GetPriceRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) GetPriceQuery( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newGetPriceRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.GetPrice(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(GetPriceResponse).FromResponse(response) + if err != nil { + return nil, err + } + + packedOutput, err := method.Outputs.Pack(out) + if err != nil { + return nil, fmt.Errorf("failed to pack output: %w", err) + } + + return packedOutput, nil +} + +func (o *GetPriceResponse) FromResponse(res *oracletypes.GetPriceResponse) (*GetPriceResponse, error) { + if res.Price == nil { + return nil, errors.New("received nil price in get price response") + } + + o.Id = res.Id + o.Nonce = res.Nonce + o.Decimals = res.Decimals + o.Price = QuotePrice{ + BlockHeight: res.Price.BlockHeight, + Price: res.Price.Price.BigInt(), + BlockTimestamp: big.NewInt(res.Price.BlockTimestamp.Unix()), + } + + return o, nil +} + +func newGetPriceRequest(method *abi.Method, args []interface{}) (*oracletypes.GetPriceRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + var input struct { + Base string + Quote string + } + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("failed to unpack arguments into get price input: %w", err) + } + + return &oracletypes.GetPriceRequest{ + CurrencyPair: slinkytypes.CurrencyPair{Base: input.Base, Quote: input.Quote}, + }, nil +} diff --git a/src/orders/precompiles/slinky/slinky.go b/src/orders/precompiles/slinky/slinky.go new file mode 100644 index 0000000..676a22c --- /dev/null +++ b/src/orders/precompiles/slinky/slinky.go @@ -0,0 +1,141 @@ +package slinky + +import ( + "embed" + "fmt" + + "cosmossdk.io/log" + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + cmn "github.com/evmos/evmos/v20/precompiles/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + oraclekeeper "github.com/skip-mev/slinky/x/oracle/keeper" + types "github.com/skip-mev/slinky/x/oracle/types" + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" +) + +var _ vm.PrecompiledContract = &Precompile{} + +// Embed abi json file to the executable binary. Needed when importing as dependency. +// +//go:embed abi.json +var f embed.FS + +// PrecompileAddress defines the contract address of the slinky precompile. +const PrecompileAddress = "0x0000000000000000000000000000000000000902" + +// Precompile defines the precompiled contract for slinky. +type Precompile struct { + cmn.Precompile + oraclekeeper oraclekeeper.Keeper + eventsRegistry *precommon.EthEventsRegistry + queryServer types.QueryServer +} + +// LoadABI loads the slinky ABI from the embedded abi.json file +// for the slinky precompile. +func LoadABI() (abi.ABI, error) { + return cmn.LoadABI(f, "abi.json") +} + +func NewPrecompile( + oraclekee oraclekeeper.Keeper, + eventRegistry *precommon.EthEventsRegistry) (*Precompile, error) { + abi, err := LoadABI() + if err != nil { + return nil, err + } + + p := Precompile{ + Precompile: cmn.Precompile{ + ABI: abi, + KvGasConfig: storetypes.KVGasConfig(), + TransientKVGasConfig: storetypes.TransientGasConfig(), + }, + oraclekeeper: oraclekee, + eventsRegistry: eventRegistry, + queryServer: oraclekeeper.NewQueryServer(oraclekee), + } + + p.SetAddress(common.HexToAddress(PrecompileAddress)) + + return &p, nil +} + +// Address implements vm.PrecompiledContract. +func (*Precompile) Address() common.Address { + return common.HexToAddress(PrecompileAddress) +} + +// RequiredGas returns the required bare minimum gas to execute the precompile. +// Subtle: this method shadows the method (Precompile).RequiredGas of Precompile.Precompile. +func (p *Precompile) RequiredGas(input []byte) uint64 { + // NOTE: This check avoid panicking when trying to decode the method ID + if len(input) < 4 { + return 0 + } + + methodID := input[:4] + + method, err := p.MethodById(methodID) + if err != nil { + // This should never happen since this method is going to fail during Run + return 0 + } + + return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name)) +} + +// Run implements vm.PrecompiledContract. +func (p *Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) { + ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction) + if err != nil { + return nil, err + } + + // This handles any out of gas errors that may occur during the execution of a precompile tx or query. + // It avoids panics and returns the out of gas error so the EVM can continue gracefully. + defer cmn.HandleGasError(ctx, contract, initialGas, &err)() + + switch method.Name { + // queries + case GetPrice: + bz, err = p.GetPriceQuery(ctx, evm.Origin, stateDB, method, args) + + default: + return nil, fmt.Errorf("slinky precompile: method not exists: %s", method.Name) + } + + if err != nil { + return nil, err + } + + cost := ctx.GasMeter().GasConsumed() - initialGas + + if !contract.UseGas(cost) { + return nil, vm.ErrOutOfGas + } + + if err := p.AddJournalEntries(stateDB, snapshot); err != nil { + return nil, err + } + + return bz, nil +} + +// IsTransaction checks if the given method name corresponds to a transaction or query. +func (*Precompile) IsTransaction(method string) bool { + switch method { + case GetPrice: + return false + } + + panic(fmt.Errorf("slinky precompile: method does not exist: %s", method)) +} + +// Logger returns a precompile-specific logger. +func (p *Precompile) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("evm extension", "x/slinky") +} diff --git a/src/orders/precompiles/warden/IWarden.go b/src/orders/precompiles/warden/IWarden.go new file mode 100644 index 0000000..2620723 --- /dev/null +++ b/src/orders/precompiles/warden/IWarden.go @@ -0,0 +1,3428 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package warden + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// AddressesResponse is an auto generated low-level Go binding around an user-defined struct. +type AddressesResponse struct { + AddressValue string + AddressType uint8 +} + +// Key is an auto generated low-level Go binding around an user-defined struct. +type Key struct { + Id uint64 + SpaceId uint64 + KeychainId uint64 + KeyType uint8 + PublicKey []byte + ApproveTemplateId uint64 + RejectTemplateId uint64 +} + +// KeyRequest is an auto generated low-level Go binding around an user-defined struct. +type KeyRequest struct { + Id uint64 + Creator common.Address + SpaceId uint64 + KeychainId uint64 + KeyType uint8 + Status uint8 + RejectReason string + ApproveTemplateId uint64 + RejectTemplateId uint64 + DeductedKeychainFees []TypesCoin +} + +// KeyResponse is an auto generated low-level Go binding around an user-defined struct. +type KeyResponse struct { + Key Key + Addresses []AddressesResponse +} + +// Keychain is an auto generated low-level Go binding around an user-defined struct. +type Keychain struct { + Id uint64 + Creator common.Address + Name string + Admins []common.Address + Writers []common.Address + Fees KeychainFees + Description string + Url string + KeybaseId string +} + +// KeychainFees is an auto generated low-level Go binding around an user-defined struct. +type KeychainFees struct { + KeyReq []TypesCoin + SigReq []TypesCoin +} + +// SignRequest is an auto generated low-level Go binding around an user-defined struct. +type SignRequest struct { + Id uint64 + Creator common.Address + KeyId uint64 + DataForSigning []byte + Status uint8 + Result []byte + EncryptionKey []byte + DeductedKeychainFees []TypesCoin + BroadcastType uint8 +} + +// Space is an auto generated low-level Go binding around an user-defined struct. +type Space struct { + Id uint64 + Creator common.Address + Owners []common.Address + Nonce uint64 + ApproveAdminTemplateId uint64 + RejectAdminTemplateId uint64 + ApproveSignTemplateId uint64 + RejectSignTemplateId uint64 +} + +// TypesCoin is an auto generated low-level Go binding around an user-defined struct. +type TypesCoin struct { + Denom string + Amount *big.Int +} + +// TypesPageRequest is an auto generated low-level Go binding around an user-defined struct. +type TypesPageRequest struct { + Key []byte + Offset uint64 + Limit uint64 + CountTotal bool + Reverse bool +} + +// TypesPageResponse is an auto generated low-level Go binding around an user-defined struct. +type TypesPageResponse struct { + NextKey []byte + Total uint64 +} + +// IWardenMetaData contains all meta data concerning the IWarden contract. +var IWardenMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"adminsCount\",\"type\":\"uint64\"}],\"name\":\"AddKeychainAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newWriter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"writersCount\",\"type\":\"uint64\"}],\"name\":\"AddKeychainWriter\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"AddSpaceOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"FulfilSignRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"}],\"name\":\"NewKey\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"}],\"name\":\"NewKeyRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"}],\"name\":\"NewKeychain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"keyId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enumBroadcastType\",\"name\":\"broadcastType\",\"type\":\"uint8\"}],\"name\":\"NewSignRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"ownersCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"}],\"name\":\"NewSpace\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"RejectKeyRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"RejectSignRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"adminsCount\",\"type\":\"uint64\"}],\"name\":\"RemoveKeychainAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"removedOwner\",\"type\":\"address\"}],\"name\":\"RemoveSpaceOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"}],\"name\":\"UpdateKey\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"keyReq\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"sigReq\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structKeychainFees\",\"name\":\"keychainFees\",\"type\":\"tuple\"}],\"name\":\"UpdateKeychain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"}],\"name\":\"UpdateSpace\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"addKeychainAdmin\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"newWriter\",\"type\":\"address\"}],\"name\":\"addKeychainWriter\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actionTimeoutHeight\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"expectedApproveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expectedRejectExpression\",\"type\":\"string\"}],\"name\":\"addSpaceOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"},{\"internalType\":\"int32[]\",\"name\":\"deriveAddresses\",\"type\":\"int32[]\"}],\"name\":\"allKeys\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"}],\"internalType\":\"structKey\",\"name\":\"key\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"addressValue\",\"type\":\"string\"},{\"internalType\":\"enumAddressType\",\"name\":\"addressType\",\"type\":\"uint8\"}],\"internalType\":\"structAddressesResponse[]\",\"name\":\"addresses\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeyResponse[]\",\"name\":\"keys\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"requestId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"pubKey\",\"type\":\"bytes\"}],\"name\":\"fulfilKeyRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"requestId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"signedData\",\"type\":\"bytes\"}],\"name\":\"fulfilSignRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"int32[]\",\"name\":\"deriveAddresses\",\"type\":\"int32[]\"}],\"name\":\"keyById\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"}],\"internalType\":\"structKey\",\"name\":\"key\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"addressValue\",\"type\":\"string\"},{\"internalType\":\"enumAddressType\",\"name\":\"addressType\",\"type\":\"uint8\"}],\"internalType\":\"structAddressesResponse[]\",\"name\":\"addresses\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeyResponse\",\"name\":\"key\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"keyRequestById\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"internalType\":\"enumKeyRequestStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"rejectReason\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"deductedKeychainFees\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeyRequest\",\"name\":\"keyRequest\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyRequestStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"}],\"name\":\"keyRequests\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"internalType\":\"enumKeyRequestStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"rejectReason\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"deductedKeychainFees\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeyRequest[]\",\"name\":\"keyRequests\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"keychainById\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address[]\",\"name\":\"admins\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"writers\",\"type\":\"address[]\"},{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"keyReq\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"sigReq\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeychainFees\",\"name\":\"fees\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"keybaseId\",\"type\":\"string\"}],\"internalType\":\"structKeychain\",\"name\":\"keychain\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"}],\"name\":\"keychains\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address[]\",\"name\":\"admins\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"writers\",\"type\":\"address[]\"},{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"keyReq\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"sigReq\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeychainFees\",\"name\":\"fees\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"keybaseId\",\"type\":\"string\"}],\"internalType\":\"structKeychain[]\",\"name\":\"keychains\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"int32[]\",\"name\":\"deriveAddresses\",\"type\":\"int32[]\"}],\"name\":\"keysBySpaceId\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"}],\"internalType\":\"structKey\",\"name\":\"key\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"addressValue\",\"type\":\"string\"},{\"internalType\":\"enumAddressType\",\"name\":\"addressType\",\"type\":\"uint8\"}],\"internalType\":\"structAddressesResponse[]\",\"name\":\"addresses\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeyResponse[]\",\"name\":\"keys\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumKeyType\",\"name\":\"keyType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"maxKeychainFees\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actionTimeoutHeight\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"expectedApproveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expectedRejectExpression\",\"type\":\"string\"}],\"name\":\"newKeyRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"keyReq\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"sigReq\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeychainFees\",\"name\":\"keychainFees\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"keybaseId\",\"type\":\"string\"}],\"name\":\"newKeychain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"keyId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"analyzers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"encryptionKey\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"maxKeychainFees\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actionTimeoutHeight\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"expectedApproveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expectedRejectExpression\",\"type\":\"string\"},{\"internalType\":\"enumBroadcastType\",\"name\":\"broadcastType\",\"type\":\"uint8\"}],\"name\":\"newSignRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"address[]\",\"name\":\"additionalOwners\",\"type\":\"address[]\"}],\"name\":\"newSpace\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"requestId\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"rejectReason\",\"type\":\"string\"}],\"name\":\"rejectKeyRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"requestId\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"rejectReason\",\"type\":\"string\"}],\"name\":\"rejectSignRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"removeKeychainAdmin\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actionTimeoutHeight\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"expectedApproveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expectedRejectExpression\",\"type\":\"string\"}],\"name\":\"removeSpaceOwner\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"signRequestById\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"keyId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"dataForSigning\",\"type\":\"bytes\"},{\"internalType\":\"enumSignRequestStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"encryptionKey\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"deductedKeychainFees\",\"type\":\"tuple[]\"},{\"internalType\":\"enumBroadcastType\",\"name\":\"broadcastType\",\"type\":\"uint8\"}],\"internalType\":\"structSignRequest\",\"name\":\"signRequest\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"enumSignRequestStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"enumOptionalBroadcastType\",\"name\":\"optionalBroadcastType\",\"type\":\"uint8\"}],\"name\":\"signRequests\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"keyId\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"dataForSigning\",\"type\":\"bytes\"},{\"internalType\":\"enumSignRequestStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"encryptionKey\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"deductedKeychainFees\",\"type\":\"tuple[]\"},{\"internalType\":\"enumBroadcastType\",\"name\":\"broadcastType\",\"type\":\"uint8\"}],\"internalType\":\"structSignRequest[]\",\"name\":\"signRequests\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"}],\"name\":\"spaceById\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"owners\",\"type\":\"address[]\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"}],\"internalType\":\"structSpace\",\"name\":\"space\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"}],\"name\":\"spaces\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"owners\",\"type\":\"address[]\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"}],\"internalType\":\"structSpace[]\",\"name\":\"spaces\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"key\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offset\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"limit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"countTotal\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reverse\",\"type\":\"bool\"}],\"internalType\":\"structTypes.PageRequest\",\"name\":\"pageRequest\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"spacesByOwner\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"id\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"owners\",\"type\":\"address[]\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"}],\"internalType\":\"structSpace[]\",\"name\":\"spaces\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"nextKey\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"total\",\"type\":\"uint64\"}],\"internalType\":\"structTypes.PageResponse\",\"name\":\"pageResponse\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"keyId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actionTimeoutHeight\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"expectedApproveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expectedRejectExpression\",\"type\":\"string\"}],\"name\":\"updateKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"keychainId\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"components\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"keyReq\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"denom\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structTypes.Coin[]\",\"name\":\"sigReq\",\"type\":\"tuple[]\"}],\"internalType\":\"structKeychainFees\",\"name\":\"keychainFees\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"keybaseId\",\"type\":\"string\"}],\"name\":\"updateKeychain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"spaceId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectAdminTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"approveSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"rejectSignTemplateId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"actionTimeoutHeight\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"expectedApproveExpression\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"expectedRejectExpression\",\"type\":\"string\"}],\"name\":\"updateSpace\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IWardenABI is the input ABI used to generate the binding from. +// Deprecated: Use IWardenMetaData.ABI instead. +var IWardenABI = IWardenMetaData.ABI + +// IWarden is an auto generated Go binding around an Ethereum contract. +type IWarden struct { + IWardenCaller // Read-only binding to the contract + IWardenTransactor // Write-only binding to the contract + IWardenFilterer // Log filterer for contract events +} + +// IWardenCaller is an auto generated read-only Go binding around an Ethereum contract. +type IWardenCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IWardenTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IWardenTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IWardenFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IWardenFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IWardenSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IWardenSession struct { + Contract *IWarden // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IWardenCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IWardenCallerSession struct { + Contract *IWardenCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IWardenTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IWardenTransactorSession struct { + Contract *IWardenTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IWardenRaw is an auto generated low-level Go binding around an Ethereum contract. +type IWardenRaw struct { + Contract *IWarden // Generic contract binding to access the raw methods on +} + +// IWardenCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IWardenCallerRaw struct { + Contract *IWardenCaller // Generic read-only contract binding to access the raw methods on +} + +// IWardenTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IWardenTransactorRaw struct { + Contract *IWardenTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIWarden creates a new instance of IWarden, bound to a specific deployed contract. +func NewIWarden(address common.Address, backend bind.ContractBackend) (*IWarden, error) { + contract, err := bindIWarden(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IWarden{IWardenCaller: IWardenCaller{contract: contract}, IWardenTransactor: IWardenTransactor{contract: contract}, IWardenFilterer: IWardenFilterer{contract: contract}}, nil +} + +// NewIWardenCaller creates a new read-only instance of IWarden, bound to a specific deployed contract. +func NewIWardenCaller(address common.Address, caller bind.ContractCaller) (*IWardenCaller, error) { + contract, err := bindIWarden(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IWardenCaller{contract: contract}, nil +} + +// NewIWardenTransactor creates a new write-only instance of IWarden, bound to a specific deployed contract. +func NewIWardenTransactor(address common.Address, transactor bind.ContractTransactor) (*IWardenTransactor, error) { + contract, err := bindIWarden(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IWardenTransactor{contract: contract}, nil +} + +// NewIWardenFilterer creates a new log filterer instance of IWarden, bound to a specific deployed contract. +func NewIWardenFilterer(address common.Address, filterer bind.ContractFilterer) (*IWardenFilterer, error) { + contract, err := bindIWarden(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IWardenFilterer{contract: contract}, nil +} + +// bindIWarden binds a generic wrapper to an already deployed contract. +func bindIWarden(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(IWardenABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IWarden *IWardenRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IWarden.Contract.IWardenCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IWarden *IWardenRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IWarden.Contract.IWardenTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IWarden *IWardenRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IWarden.Contract.IWardenTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IWarden *IWardenCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IWarden.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IWarden *IWardenTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IWarden.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IWarden *IWardenTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IWarden.Contract.contract.Transact(opts, method, params...) +} + +// AllKeys is a free data retrieval call binding the contract method 0xed65c53c. +// +// Solidity: function allKeys((bytes,uint64,uint64,bool,bool) pageRequest, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[])[] keys, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) AllKeys(opts *bind.CallOpts, pageRequest TypesPageRequest, deriveAddresses []int32) (struct { + Keys []KeyResponse + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "allKeys", pageRequest, deriveAddresses) + + outstruct := new(struct { + Keys []KeyResponse + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Keys = *abi.ConvertType(out[0], new([]KeyResponse)).(*[]KeyResponse) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// AllKeys is a free data retrieval call binding the contract method 0xed65c53c. +// +// Solidity: function allKeys((bytes,uint64,uint64,bool,bool) pageRequest, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[])[] keys, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) AllKeys(pageRequest TypesPageRequest, deriveAddresses []int32) (struct { + Keys []KeyResponse + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.AllKeys(&_IWarden.CallOpts, pageRequest, deriveAddresses) +} + +// AllKeys is a free data retrieval call binding the contract method 0xed65c53c. +// +// Solidity: function allKeys((bytes,uint64,uint64,bool,bool) pageRequest, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[])[] keys, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) AllKeys(pageRequest TypesPageRequest, deriveAddresses []int32) (struct { + Keys []KeyResponse + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.AllKeys(&_IWarden.CallOpts, pageRequest, deriveAddresses) +} + +// KeyById is a free data retrieval call binding the contract method 0x338c1f51. +// +// Solidity: function keyById(uint64 id, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[]) key) +func (_IWarden *IWardenCaller) KeyById(opts *bind.CallOpts, id uint64, deriveAddresses []int32) (KeyResponse, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "keyById", id, deriveAddresses) + + if err != nil { + return *new(KeyResponse), err + } + + out0 := *abi.ConvertType(out[0], new(KeyResponse)).(*KeyResponse) + + return out0, err + +} + +// KeyById is a free data retrieval call binding the contract method 0x338c1f51. +// +// Solidity: function keyById(uint64 id, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[]) key) +func (_IWarden *IWardenSession) KeyById(id uint64, deriveAddresses []int32) (KeyResponse, error) { + return _IWarden.Contract.KeyById(&_IWarden.CallOpts, id, deriveAddresses) +} + +// KeyById is a free data retrieval call binding the contract method 0x338c1f51. +// +// Solidity: function keyById(uint64 id, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[]) key) +func (_IWarden *IWardenCallerSession) KeyById(id uint64, deriveAddresses []int32) (KeyResponse, error) { + return _IWarden.Contract.KeyById(&_IWarden.CallOpts, id, deriveAddresses) +} + +// KeyRequestById is a free data retrieval call binding the contract method 0x69964bd6. +// +// Solidity: function keyRequestById(uint64 id) view returns((uint64,address,uint64,uint64,uint8,uint8,string,uint64,uint64,(string,uint256)[]) keyRequest) +func (_IWarden *IWardenCaller) KeyRequestById(opts *bind.CallOpts, id uint64) (KeyRequest, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "keyRequestById", id) + + if err != nil { + return *new(KeyRequest), err + } + + out0 := *abi.ConvertType(out[0], new(KeyRequest)).(*KeyRequest) + + return out0, err + +} + +// KeyRequestById is a free data retrieval call binding the contract method 0x69964bd6. +// +// Solidity: function keyRequestById(uint64 id) view returns((uint64,address,uint64,uint64,uint8,uint8,string,uint64,uint64,(string,uint256)[]) keyRequest) +func (_IWarden *IWardenSession) KeyRequestById(id uint64) (KeyRequest, error) { + return _IWarden.Contract.KeyRequestById(&_IWarden.CallOpts, id) +} + +// KeyRequestById is a free data retrieval call binding the contract method 0x69964bd6. +// +// Solidity: function keyRequestById(uint64 id) view returns((uint64,address,uint64,uint64,uint8,uint8,string,uint64,uint64,(string,uint256)[]) keyRequest) +func (_IWarden *IWardenCallerSession) KeyRequestById(id uint64) (KeyRequest, error) { + return _IWarden.Contract.KeyRequestById(&_IWarden.CallOpts, id) +} + +// KeyRequests is a free data retrieval call binding the contract method 0x2d10a4d6. +// +// Solidity: function keyRequests((bytes,uint64,uint64,bool,bool) pageRequest, uint64 keychainId, uint8 status, uint64 spaceId) view returns((uint64,address,uint64,uint64,uint8,uint8,string,uint64,uint64,(string,uint256)[])[] keyRequests, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) KeyRequests(opts *bind.CallOpts, pageRequest TypesPageRequest, keychainId uint64, status uint8, spaceId uint64) (struct { + KeyRequests []KeyRequest + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "keyRequests", pageRequest, keychainId, status, spaceId) + + outstruct := new(struct { + KeyRequests []KeyRequest + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.KeyRequests = *abi.ConvertType(out[0], new([]KeyRequest)).(*[]KeyRequest) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// KeyRequests is a free data retrieval call binding the contract method 0x2d10a4d6. +// +// Solidity: function keyRequests((bytes,uint64,uint64,bool,bool) pageRequest, uint64 keychainId, uint8 status, uint64 spaceId) view returns((uint64,address,uint64,uint64,uint8,uint8,string,uint64,uint64,(string,uint256)[])[] keyRequests, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) KeyRequests(pageRequest TypesPageRequest, keychainId uint64, status uint8, spaceId uint64) (struct { + KeyRequests []KeyRequest + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.KeyRequests(&_IWarden.CallOpts, pageRequest, keychainId, status, spaceId) +} + +// KeyRequests is a free data retrieval call binding the contract method 0x2d10a4d6. +// +// Solidity: function keyRequests((bytes,uint64,uint64,bool,bool) pageRequest, uint64 keychainId, uint8 status, uint64 spaceId) view returns((uint64,address,uint64,uint64,uint8,uint8,string,uint64,uint64,(string,uint256)[])[] keyRequests, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) KeyRequests(pageRequest TypesPageRequest, keychainId uint64, status uint8, spaceId uint64) (struct { + KeyRequests []KeyRequest + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.KeyRequests(&_IWarden.CallOpts, pageRequest, keychainId, status, spaceId) +} + +// KeychainById is a free data retrieval call binding the contract method 0xba664dc2. +// +// Solidity: function keychainById(uint64 id) view returns((uint64,address,string,address[],address[],((string,uint256)[],(string,uint256)[]),string,string,string) keychain) +func (_IWarden *IWardenCaller) KeychainById(opts *bind.CallOpts, id uint64) (Keychain, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "keychainById", id) + + if err != nil { + return *new(Keychain), err + } + + out0 := *abi.ConvertType(out[0], new(Keychain)).(*Keychain) + + return out0, err + +} + +// KeychainById is a free data retrieval call binding the contract method 0xba664dc2. +// +// Solidity: function keychainById(uint64 id) view returns((uint64,address,string,address[],address[],((string,uint256)[],(string,uint256)[]),string,string,string) keychain) +func (_IWarden *IWardenSession) KeychainById(id uint64) (Keychain, error) { + return _IWarden.Contract.KeychainById(&_IWarden.CallOpts, id) +} + +// KeychainById is a free data retrieval call binding the contract method 0xba664dc2. +// +// Solidity: function keychainById(uint64 id) view returns((uint64,address,string,address[],address[],((string,uint256)[],(string,uint256)[]),string,string,string) keychain) +func (_IWarden *IWardenCallerSession) KeychainById(id uint64) (Keychain, error) { + return _IWarden.Contract.KeychainById(&_IWarden.CallOpts, id) +} + +// Keychains is a free data retrieval call binding the contract method 0x7e5a6446. +// +// Solidity: function keychains((bytes,uint64,uint64,bool,bool) pageRequest) view returns((uint64,address,string,address[],address[],((string,uint256)[],(string,uint256)[]),string,string,string)[] keychains, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) Keychains(opts *bind.CallOpts, pageRequest TypesPageRequest) (struct { + Keychains []Keychain + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "keychains", pageRequest) + + outstruct := new(struct { + Keychains []Keychain + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Keychains = *abi.ConvertType(out[0], new([]Keychain)).(*[]Keychain) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// Keychains is a free data retrieval call binding the contract method 0x7e5a6446. +// +// Solidity: function keychains((bytes,uint64,uint64,bool,bool) pageRequest) view returns((uint64,address,string,address[],address[],((string,uint256)[],(string,uint256)[]),string,string,string)[] keychains, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) Keychains(pageRequest TypesPageRequest) (struct { + Keychains []Keychain + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.Keychains(&_IWarden.CallOpts, pageRequest) +} + +// Keychains is a free data retrieval call binding the contract method 0x7e5a6446. +// +// Solidity: function keychains((bytes,uint64,uint64,bool,bool) pageRequest) view returns((uint64,address,string,address[],address[],((string,uint256)[],(string,uint256)[]),string,string,string)[] keychains, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) Keychains(pageRequest TypesPageRequest) (struct { + Keychains []Keychain + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.Keychains(&_IWarden.CallOpts, pageRequest) +} + +// KeysBySpaceId is a free data retrieval call binding the contract method 0x8f6c0508. +// +// Solidity: function keysBySpaceId((bytes,uint64,uint64,bool,bool) pageRequest, uint64 spaceId, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[])[] keys, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) KeysBySpaceId(opts *bind.CallOpts, pageRequest TypesPageRequest, spaceId uint64, deriveAddresses []int32) (struct { + Keys []KeyResponse + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "keysBySpaceId", pageRequest, spaceId, deriveAddresses) + + outstruct := new(struct { + Keys []KeyResponse + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Keys = *abi.ConvertType(out[0], new([]KeyResponse)).(*[]KeyResponse) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// KeysBySpaceId is a free data retrieval call binding the contract method 0x8f6c0508. +// +// Solidity: function keysBySpaceId((bytes,uint64,uint64,bool,bool) pageRequest, uint64 spaceId, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[])[] keys, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) KeysBySpaceId(pageRequest TypesPageRequest, spaceId uint64, deriveAddresses []int32) (struct { + Keys []KeyResponse + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.KeysBySpaceId(&_IWarden.CallOpts, pageRequest, spaceId, deriveAddresses) +} + +// KeysBySpaceId is a free data retrieval call binding the contract method 0x8f6c0508. +// +// Solidity: function keysBySpaceId((bytes,uint64,uint64,bool,bool) pageRequest, uint64 spaceId, int32[] deriveAddresses) view returns(((uint64,uint64,uint64,uint8,bytes,uint64,uint64),(string,uint8)[])[] keys, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) KeysBySpaceId(pageRequest TypesPageRequest, spaceId uint64, deriveAddresses []int32) (struct { + Keys []KeyResponse + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.KeysBySpaceId(&_IWarden.CallOpts, pageRequest, spaceId, deriveAddresses) +} + +// SignRequestById is a free data retrieval call binding the contract method 0xa657df94. +// +// Solidity: function signRequestById(uint64 id) view returns((uint64,address,uint64,bytes,uint8,bytes,bytes,(string,uint256)[],uint8) signRequest) +func (_IWarden *IWardenCaller) SignRequestById(opts *bind.CallOpts, id uint64) (SignRequest, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "signRequestById", id) + + if err != nil { + return *new(SignRequest), err + } + + out0 := *abi.ConvertType(out[0], new(SignRequest)).(*SignRequest) + + return out0, err + +} + +// SignRequestById is a free data retrieval call binding the contract method 0xa657df94. +// +// Solidity: function signRequestById(uint64 id) view returns((uint64,address,uint64,bytes,uint8,bytes,bytes,(string,uint256)[],uint8) signRequest) +func (_IWarden *IWardenSession) SignRequestById(id uint64) (SignRequest, error) { + return _IWarden.Contract.SignRequestById(&_IWarden.CallOpts, id) +} + +// SignRequestById is a free data retrieval call binding the contract method 0xa657df94. +// +// Solidity: function signRequestById(uint64 id) view returns((uint64,address,uint64,bytes,uint8,bytes,bytes,(string,uint256)[],uint8) signRequest) +func (_IWarden *IWardenCallerSession) SignRequestById(id uint64) (SignRequest, error) { + return _IWarden.Contract.SignRequestById(&_IWarden.CallOpts, id) +} + +// SignRequests is a free data retrieval call binding the contract method 0xf919b270. +// +// Solidity: function signRequests((bytes,uint64,uint64,bool,bool) pageRequest, uint64 keychainId, uint8 status, uint8 optionalBroadcastType) view returns((uint64,address,uint64,bytes,uint8,bytes,bytes,(string,uint256)[],uint8)[] signRequests, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) SignRequests(opts *bind.CallOpts, pageRequest TypesPageRequest, keychainId uint64, status uint8, optionalBroadcastType uint8) (struct { + SignRequests []SignRequest + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "signRequests", pageRequest, keychainId, status, optionalBroadcastType) + + outstruct := new(struct { + SignRequests []SignRequest + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.SignRequests = *abi.ConvertType(out[0], new([]SignRequest)).(*[]SignRequest) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// SignRequests is a free data retrieval call binding the contract method 0xf919b270. +// +// Solidity: function signRequests((bytes,uint64,uint64,bool,bool) pageRequest, uint64 keychainId, uint8 status, uint8 optionalBroadcastType) view returns((uint64,address,uint64,bytes,uint8,bytes,bytes,(string,uint256)[],uint8)[] signRequests, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) SignRequests(pageRequest TypesPageRequest, keychainId uint64, status uint8, optionalBroadcastType uint8) (struct { + SignRequests []SignRequest + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.SignRequests(&_IWarden.CallOpts, pageRequest, keychainId, status, optionalBroadcastType) +} + +// SignRequests is a free data retrieval call binding the contract method 0xf919b270. +// +// Solidity: function signRequests((bytes,uint64,uint64,bool,bool) pageRequest, uint64 keychainId, uint8 status, uint8 optionalBroadcastType) view returns((uint64,address,uint64,bytes,uint8,bytes,bytes,(string,uint256)[],uint8)[] signRequests, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) SignRequests(pageRequest TypesPageRequest, keychainId uint64, status uint8, optionalBroadcastType uint8) (struct { + SignRequests []SignRequest + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.SignRequests(&_IWarden.CallOpts, pageRequest, keychainId, status, optionalBroadcastType) +} + +// SpaceById is a free data retrieval call binding the contract method 0xe4c1fc79. +// +// Solidity: function spaceById(uint64 id) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64) space) +func (_IWarden *IWardenCaller) SpaceById(opts *bind.CallOpts, id uint64) (Space, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "spaceById", id) + + if err != nil { + return *new(Space), err + } + + out0 := *abi.ConvertType(out[0], new(Space)).(*Space) + + return out0, err + +} + +// SpaceById is a free data retrieval call binding the contract method 0xe4c1fc79. +// +// Solidity: function spaceById(uint64 id) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64) space) +func (_IWarden *IWardenSession) SpaceById(id uint64) (Space, error) { + return _IWarden.Contract.SpaceById(&_IWarden.CallOpts, id) +} + +// SpaceById is a free data retrieval call binding the contract method 0xe4c1fc79. +// +// Solidity: function spaceById(uint64 id) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64) space) +func (_IWarden *IWardenCallerSession) SpaceById(id uint64) (Space, error) { + return _IWarden.Contract.SpaceById(&_IWarden.CallOpts, id) +} + +// Spaces is a free data retrieval call binding the contract method 0x5f73892e. +// +// Solidity: function spaces((bytes,uint64,uint64,bool,bool) pageRequest) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64)[] spaces, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) Spaces(opts *bind.CallOpts, pageRequest TypesPageRequest) (struct { + Spaces []Space + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "spaces", pageRequest) + + outstruct := new(struct { + Spaces []Space + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Spaces = *abi.ConvertType(out[0], new([]Space)).(*[]Space) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// Spaces is a free data retrieval call binding the contract method 0x5f73892e. +// +// Solidity: function spaces((bytes,uint64,uint64,bool,bool) pageRequest) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64)[] spaces, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) Spaces(pageRequest TypesPageRequest) (struct { + Spaces []Space + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.Spaces(&_IWarden.CallOpts, pageRequest) +} + +// Spaces is a free data retrieval call binding the contract method 0x5f73892e. +// +// Solidity: function spaces((bytes,uint64,uint64,bool,bool) pageRequest) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64)[] spaces, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) Spaces(pageRequest TypesPageRequest) (struct { + Spaces []Space + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.Spaces(&_IWarden.CallOpts, pageRequest) +} + +// SpacesByOwner is a free data retrieval call binding the contract method 0x88cd3f61. +// +// Solidity: function spacesByOwner((bytes,uint64,uint64,bool,bool) pageRequest, address owner) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64)[] spaces, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCaller) SpacesByOwner(opts *bind.CallOpts, pageRequest TypesPageRequest, owner common.Address) (struct { + Spaces []Space + PageResponse TypesPageResponse +}, error) { + var out []interface{} + err := _IWarden.contract.Call(opts, &out, "spacesByOwner", pageRequest, owner) + + outstruct := new(struct { + Spaces []Space + PageResponse TypesPageResponse + }) + if err != nil { + return *outstruct, err + } + + outstruct.Spaces = *abi.ConvertType(out[0], new([]Space)).(*[]Space) + outstruct.PageResponse = *abi.ConvertType(out[1], new(TypesPageResponse)).(*TypesPageResponse) + + return *outstruct, err + +} + +// SpacesByOwner is a free data retrieval call binding the contract method 0x88cd3f61. +// +// Solidity: function spacesByOwner((bytes,uint64,uint64,bool,bool) pageRequest, address owner) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64)[] spaces, (bytes,uint64) pageResponse) +func (_IWarden *IWardenSession) SpacesByOwner(pageRequest TypesPageRequest, owner common.Address) (struct { + Spaces []Space + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.SpacesByOwner(&_IWarden.CallOpts, pageRequest, owner) +} + +// SpacesByOwner is a free data retrieval call binding the contract method 0x88cd3f61. +// +// Solidity: function spacesByOwner((bytes,uint64,uint64,bool,bool) pageRequest, address owner) view returns((uint64,address,address[],uint64,uint64,uint64,uint64,uint64)[] spaces, (bytes,uint64) pageResponse) +func (_IWarden *IWardenCallerSession) SpacesByOwner(pageRequest TypesPageRequest, owner common.Address) (struct { + Spaces []Space + PageResponse TypesPageResponse +}, error) { + return _IWarden.Contract.SpacesByOwner(&_IWarden.CallOpts, pageRequest, owner) +} + +// AddKeychainAdmin is a paid mutator transaction binding the contract method 0xdf9c1808. +// +// Solidity: function addKeychainAdmin(uint64 keychainId, address newAdmin) returns(bool success) +func (_IWarden *IWardenTransactor) AddKeychainAdmin(opts *bind.TransactOpts, keychainId uint64, newAdmin common.Address) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "addKeychainAdmin", keychainId, newAdmin) +} + +// AddKeychainAdmin is a paid mutator transaction binding the contract method 0xdf9c1808. +// +// Solidity: function addKeychainAdmin(uint64 keychainId, address newAdmin) returns(bool success) +func (_IWarden *IWardenSession) AddKeychainAdmin(keychainId uint64, newAdmin common.Address) (*types.Transaction, error) { + return _IWarden.Contract.AddKeychainAdmin(&_IWarden.TransactOpts, keychainId, newAdmin) +} + +// AddKeychainAdmin is a paid mutator transaction binding the contract method 0xdf9c1808. +// +// Solidity: function addKeychainAdmin(uint64 keychainId, address newAdmin) returns(bool success) +func (_IWarden *IWardenTransactorSession) AddKeychainAdmin(keychainId uint64, newAdmin common.Address) (*types.Transaction, error) { + return _IWarden.Contract.AddKeychainAdmin(&_IWarden.TransactOpts, keychainId, newAdmin) +} + +// AddKeychainWriter is a paid mutator transaction binding the contract method 0x49fb21b3. +// +// Solidity: function addKeychainWriter(uint64 keychainId, address newWriter) returns(bool success) +func (_IWarden *IWardenTransactor) AddKeychainWriter(opts *bind.TransactOpts, keychainId uint64, newWriter common.Address) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "addKeychainWriter", keychainId, newWriter) +} + +// AddKeychainWriter is a paid mutator transaction binding the contract method 0x49fb21b3. +// +// Solidity: function addKeychainWriter(uint64 keychainId, address newWriter) returns(bool success) +func (_IWarden *IWardenSession) AddKeychainWriter(keychainId uint64, newWriter common.Address) (*types.Transaction, error) { + return _IWarden.Contract.AddKeychainWriter(&_IWarden.TransactOpts, keychainId, newWriter) +} + +// AddKeychainWriter is a paid mutator transaction binding the contract method 0x49fb21b3. +// +// Solidity: function addKeychainWriter(uint64 keychainId, address newWriter) returns(bool success) +func (_IWarden *IWardenTransactorSession) AddKeychainWriter(keychainId uint64, newWriter common.Address) (*types.Transaction, error) { + return _IWarden.Contract.AddKeychainWriter(&_IWarden.TransactOpts, keychainId, newWriter) +} + +// AddSpaceOwner is a paid mutator transaction binding the contract method 0x2bf40208. +// +// Solidity: function addSpaceOwner(uint64 spaceId, address newOwner, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactor) AddSpaceOwner(opts *bind.TransactOpts, spaceId uint64, newOwner common.Address, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "addSpaceOwner", spaceId, newOwner, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// AddSpaceOwner is a paid mutator transaction binding the contract method 0x2bf40208. +// +// Solidity: function addSpaceOwner(uint64 spaceId, address newOwner, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenSession) AddSpaceOwner(spaceId uint64, newOwner common.Address, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.AddSpaceOwner(&_IWarden.TransactOpts, spaceId, newOwner, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// AddSpaceOwner is a paid mutator transaction binding the contract method 0x2bf40208. +// +// Solidity: function addSpaceOwner(uint64 spaceId, address newOwner, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactorSession) AddSpaceOwner(spaceId uint64, newOwner common.Address, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.AddSpaceOwner(&_IWarden.TransactOpts, spaceId, newOwner, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// FulfilKeyRequest is a paid mutator transaction binding the contract method 0x1cf2c987. +// +// Solidity: function fulfilKeyRequest(uint64 requestId, bytes pubKey) returns(bool success) +func (_IWarden *IWardenTransactor) FulfilKeyRequest(opts *bind.TransactOpts, requestId uint64, pubKey []byte) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "fulfilKeyRequest", requestId, pubKey) +} + +// FulfilKeyRequest is a paid mutator transaction binding the contract method 0x1cf2c987. +// +// Solidity: function fulfilKeyRequest(uint64 requestId, bytes pubKey) returns(bool success) +func (_IWarden *IWardenSession) FulfilKeyRequest(requestId uint64, pubKey []byte) (*types.Transaction, error) { + return _IWarden.Contract.FulfilKeyRequest(&_IWarden.TransactOpts, requestId, pubKey) +} + +// FulfilKeyRequest is a paid mutator transaction binding the contract method 0x1cf2c987. +// +// Solidity: function fulfilKeyRequest(uint64 requestId, bytes pubKey) returns(bool success) +func (_IWarden *IWardenTransactorSession) FulfilKeyRequest(requestId uint64, pubKey []byte) (*types.Transaction, error) { + return _IWarden.Contract.FulfilKeyRequest(&_IWarden.TransactOpts, requestId, pubKey) +} + +// FulfilSignRequest is a paid mutator transaction binding the contract method 0x84f61386. +// +// Solidity: function fulfilSignRequest(uint64 requestId, bytes signedData) returns(bool success) +func (_IWarden *IWardenTransactor) FulfilSignRequest(opts *bind.TransactOpts, requestId uint64, signedData []byte) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "fulfilSignRequest", requestId, signedData) +} + +// FulfilSignRequest is a paid mutator transaction binding the contract method 0x84f61386. +// +// Solidity: function fulfilSignRequest(uint64 requestId, bytes signedData) returns(bool success) +func (_IWarden *IWardenSession) FulfilSignRequest(requestId uint64, signedData []byte) (*types.Transaction, error) { + return _IWarden.Contract.FulfilSignRequest(&_IWarden.TransactOpts, requestId, signedData) +} + +// FulfilSignRequest is a paid mutator transaction binding the contract method 0x84f61386. +// +// Solidity: function fulfilSignRequest(uint64 requestId, bytes signedData) returns(bool success) +func (_IWarden *IWardenTransactorSession) FulfilSignRequest(requestId uint64, signedData []byte) (*types.Transaction, error) { + return _IWarden.Contract.FulfilSignRequest(&_IWarden.TransactOpts, requestId, signedData) +} + +// NewKeyRequest is a paid mutator transaction binding the contract method 0x90bfe071. +// +// Solidity: function newKeyRequest(uint64 spaceId, uint64 keychainId, uint8 keyType, uint64 approveTemplateId, uint64 rejectTemplateId, (string,uint256)[] maxKeychainFees, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactor) NewKeyRequest(opts *bind.TransactOpts, spaceId uint64, keychainId uint64, keyType uint8, approveTemplateId uint64, rejectTemplateId uint64, maxKeychainFees []TypesCoin, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "newKeyRequest", spaceId, keychainId, keyType, approveTemplateId, rejectTemplateId, maxKeychainFees, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// NewKeyRequest is a paid mutator transaction binding the contract method 0x90bfe071. +// +// Solidity: function newKeyRequest(uint64 spaceId, uint64 keychainId, uint8 keyType, uint64 approveTemplateId, uint64 rejectTemplateId, (string,uint256)[] maxKeychainFees, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenSession) NewKeyRequest(spaceId uint64, keychainId uint64, keyType uint8, approveTemplateId uint64, rejectTemplateId uint64, maxKeychainFees []TypesCoin, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.NewKeyRequest(&_IWarden.TransactOpts, spaceId, keychainId, keyType, approveTemplateId, rejectTemplateId, maxKeychainFees, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// NewKeyRequest is a paid mutator transaction binding the contract method 0x90bfe071. +// +// Solidity: function newKeyRequest(uint64 spaceId, uint64 keychainId, uint8 keyType, uint64 approveTemplateId, uint64 rejectTemplateId, (string,uint256)[] maxKeychainFees, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactorSession) NewKeyRequest(spaceId uint64, keychainId uint64, keyType uint8, approveTemplateId uint64, rejectTemplateId uint64, maxKeychainFees []TypesCoin, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.NewKeyRequest(&_IWarden.TransactOpts, spaceId, keychainId, keyType, approveTemplateId, rejectTemplateId, maxKeychainFees, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// NewKeychain is a paid mutator transaction binding the contract method 0x7d4c42ad. +// +// Solidity: function newKeychain(string name, ((string,uint256)[],(string,uint256)[]) keychainFees, string description, string url, string keybaseId) returns(uint64 id) +func (_IWarden *IWardenTransactor) NewKeychain(opts *bind.TransactOpts, name string, keychainFees KeychainFees, description string, url string, keybaseId string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "newKeychain", name, keychainFees, description, url, keybaseId) +} + +// NewKeychain is a paid mutator transaction binding the contract method 0x7d4c42ad. +// +// Solidity: function newKeychain(string name, ((string,uint256)[],(string,uint256)[]) keychainFees, string description, string url, string keybaseId) returns(uint64 id) +func (_IWarden *IWardenSession) NewKeychain(name string, keychainFees KeychainFees, description string, url string, keybaseId string) (*types.Transaction, error) { + return _IWarden.Contract.NewKeychain(&_IWarden.TransactOpts, name, keychainFees, description, url, keybaseId) +} + +// NewKeychain is a paid mutator transaction binding the contract method 0x7d4c42ad. +// +// Solidity: function newKeychain(string name, ((string,uint256)[],(string,uint256)[]) keychainFees, string description, string url, string keybaseId) returns(uint64 id) +func (_IWarden *IWardenTransactorSession) NewKeychain(name string, keychainFees KeychainFees, description string, url string, keybaseId string) (*types.Transaction, error) { + return _IWarden.Contract.NewKeychain(&_IWarden.TransactOpts, name, keychainFees, description, url, keybaseId) +} + +// NewSignRequest is a paid mutator transaction binding the contract method 0x07d145e9. +// +// Solidity: function newSignRequest(uint64 keyId, bytes input, bytes[] analyzers, bytes encryptionKey, (string,uint256)[] maxKeychainFees, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression, uint8 broadcastType) returns(bool success) +func (_IWarden *IWardenTransactor) NewSignRequest(opts *bind.TransactOpts, keyId uint64, input []byte, analyzers [][]byte, encryptionKey []byte, maxKeychainFees []TypesCoin, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string, broadcastType uint8) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "newSignRequest", keyId, input, analyzers, encryptionKey, maxKeychainFees, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression, broadcastType) +} + +// NewSignRequest is a paid mutator transaction binding the contract method 0x07d145e9. +// +// Solidity: function newSignRequest(uint64 keyId, bytes input, bytes[] analyzers, bytes encryptionKey, (string,uint256)[] maxKeychainFees, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression, uint8 broadcastType) returns(bool success) +func (_IWarden *IWardenSession) NewSignRequest(keyId uint64, input []byte, analyzers [][]byte, encryptionKey []byte, maxKeychainFees []TypesCoin, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string, broadcastType uint8) (*types.Transaction, error) { + return _IWarden.Contract.NewSignRequest(&_IWarden.TransactOpts, keyId, input, analyzers, encryptionKey, maxKeychainFees, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression, broadcastType) +} + +// NewSignRequest is a paid mutator transaction binding the contract method 0x07d145e9. +// +// Solidity: function newSignRequest(uint64 keyId, bytes input, bytes[] analyzers, bytes encryptionKey, (string,uint256)[] maxKeychainFees, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression, uint8 broadcastType) returns(bool success) +func (_IWarden *IWardenTransactorSession) NewSignRequest(keyId uint64, input []byte, analyzers [][]byte, encryptionKey []byte, maxKeychainFees []TypesCoin, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string, broadcastType uint8) (*types.Transaction, error) { + return _IWarden.Contract.NewSignRequest(&_IWarden.TransactOpts, keyId, input, analyzers, encryptionKey, maxKeychainFees, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression, broadcastType) +} + +// NewSpace is a paid mutator transaction binding the contract method 0xc78f7667. +// +// Solidity: function newSpace(uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId, address[] additionalOwners) returns(uint64 id) +func (_IWarden *IWardenTransactor) NewSpace(opts *bind.TransactOpts, approveAdminTemplateId uint64, rejectAdminTemplateId uint64, approveSignTemplateId uint64, rejectSignTemplateId uint64, additionalOwners []common.Address) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "newSpace", approveAdminTemplateId, rejectAdminTemplateId, approveSignTemplateId, rejectSignTemplateId, additionalOwners) +} + +// NewSpace is a paid mutator transaction binding the contract method 0xc78f7667. +// +// Solidity: function newSpace(uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId, address[] additionalOwners) returns(uint64 id) +func (_IWarden *IWardenSession) NewSpace(approveAdminTemplateId uint64, rejectAdminTemplateId uint64, approveSignTemplateId uint64, rejectSignTemplateId uint64, additionalOwners []common.Address) (*types.Transaction, error) { + return _IWarden.Contract.NewSpace(&_IWarden.TransactOpts, approveAdminTemplateId, rejectAdminTemplateId, approveSignTemplateId, rejectSignTemplateId, additionalOwners) +} + +// NewSpace is a paid mutator transaction binding the contract method 0xc78f7667. +// +// Solidity: function newSpace(uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId, address[] additionalOwners) returns(uint64 id) +func (_IWarden *IWardenTransactorSession) NewSpace(approveAdminTemplateId uint64, rejectAdminTemplateId uint64, approveSignTemplateId uint64, rejectSignTemplateId uint64, additionalOwners []common.Address) (*types.Transaction, error) { + return _IWarden.Contract.NewSpace(&_IWarden.TransactOpts, approveAdminTemplateId, rejectAdminTemplateId, approveSignTemplateId, rejectSignTemplateId, additionalOwners) +} + +// RejectKeyRequest is a paid mutator transaction binding the contract method 0xd9ac97be. +// +// Solidity: function rejectKeyRequest(uint64 requestId, string rejectReason) returns(bool success) +func (_IWarden *IWardenTransactor) RejectKeyRequest(opts *bind.TransactOpts, requestId uint64, rejectReason string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "rejectKeyRequest", requestId, rejectReason) +} + +// RejectKeyRequest is a paid mutator transaction binding the contract method 0xd9ac97be. +// +// Solidity: function rejectKeyRequest(uint64 requestId, string rejectReason) returns(bool success) +func (_IWarden *IWardenSession) RejectKeyRequest(requestId uint64, rejectReason string) (*types.Transaction, error) { + return _IWarden.Contract.RejectKeyRequest(&_IWarden.TransactOpts, requestId, rejectReason) +} + +// RejectKeyRequest is a paid mutator transaction binding the contract method 0xd9ac97be. +// +// Solidity: function rejectKeyRequest(uint64 requestId, string rejectReason) returns(bool success) +func (_IWarden *IWardenTransactorSession) RejectKeyRequest(requestId uint64, rejectReason string) (*types.Transaction, error) { + return _IWarden.Contract.RejectKeyRequest(&_IWarden.TransactOpts, requestId, rejectReason) +} + +// RejectSignRequest is a paid mutator transaction binding the contract method 0xb7cf0661. +// +// Solidity: function rejectSignRequest(uint64 requestId, string rejectReason) returns(bool success) +func (_IWarden *IWardenTransactor) RejectSignRequest(opts *bind.TransactOpts, requestId uint64, rejectReason string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "rejectSignRequest", requestId, rejectReason) +} + +// RejectSignRequest is a paid mutator transaction binding the contract method 0xb7cf0661. +// +// Solidity: function rejectSignRequest(uint64 requestId, string rejectReason) returns(bool success) +func (_IWarden *IWardenSession) RejectSignRequest(requestId uint64, rejectReason string) (*types.Transaction, error) { + return _IWarden.Contract.RejectSignRequest(&_IWarden.TransactOpts, requestId, rejectReason) +} + +// RejectSignRequest is a paid mutator transaction binding the contract method 0xb7cf0661. +// +// Solidity: function rejectSignRequest(uint64 requestId, string rejectReason) returns(bool success) +func (_IWarden *IWardenTransactorSession) RejectSignRequest(requestId uint64, rejectReason string) (*types.Transaction, error) { + return _IWarden.Contract.RejectSignRequest(&_IWarden.TransactOpts, requestId, rejectReason) +} + +// RemoveKeychainAdmin is a paid mutator transaction binding the contract method 0x7225e3fa. +// +// Solidity: function removeKeychainAdmin(uint64 keychainId, address admin) returns(bool success) +func (_IWarden *IWardenTransactor) RemoveKeychainAdmin(opts *bind.TransactOpts, keychainId uint64, admin common.Address) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "removeKeychainAdmin", keychainId, admin) +} + +// RemoveKeychainAdmin is a paid mutator transaction binding the contract method 0x7225e3fa. +// +// Solidity: function removeKeychainAdmin(uint64 keychainId, address admin) returns(bool success) +func (_IWarden *IWardenSession) RemoveKeychainAdmin(keychainId uint64, admin common.Address) (*types.Transaction, error) { + return _IWarden.Contract.RemoveKeychainAdmin(&_IWarden.TransactOpts, keychainId, admin) +} + +// RemoveKeychainAdmin is a paid mutator transaction binding the contract method 0x7225e3fa. +// +// Solidity: function removeKeychainAdmin(uint64 keychainId, address admin) returns(bool success) +func (_IWarden *IWardenTransactorSession) RemoveKeychainAdmin(keychainId uint64, admin common.Address) (*types.Transaction, error) { + return _IWarden.Contract.RemoveKeychainAdmin(&_IWarden.TransactOpts, keychainId, admin) +} + +// RemoveSpaceOwner is a paid mutator transaction binding the contract method 0x60c88db5. +// +// Solidity: function removeSpaceOwner(uint64 spaceId, address owner, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactor) RemoveSpaceOwner(opts *bind.TransactOpts, spaceId uint64, owner common.Address, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "removeSpaceOwner", spaceId, owner, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// RemoveSpaceOwner is a paid mutator transaction binding the contract method 0x60c88db5. +// +// Solidity: function removeSpaceOwner(uint64 spaceId, address owner, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenSession) RemoveSpaceOwner(spaceId uint64, owner common.Address, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.RemoveSpaceOwner(&_IWarden.TransactOpts, spaceId, owner, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// RemoveSpaceOwner is a paid mutator transaction binding the contract method 0x60c88db5. +// +// Solidity: function removeSpaceOwner(uint64 spaceId, address owner, uint64 nonce, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactorSession) RemoveSpaceOwner(spaceId uint64, owner common.Address, nonce uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.RemoveSpaceOwner(&_IWarden.TransactOpts, spaceId, owner, nonce, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// UpdateKey is a paid mutator transaction binding the contract method 0xfecc57ec. +// +// Solidity: function updateKey(uint64 keyId, uint64 approveTemplateId, uint64 rejectTemplateId, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactor) UpdateKey(opts *bind.TransactOpts, keyId uint64, approveTemplateId uint64, rejectTemplateId uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "updateKey", keyId, approveTemplateId, rejectTemplateId, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// UpdateKey is a paid mutator transaction binding the contract method 0xfecc57ec. +// +// Solidity: function updateKey(uint64 keyId, uint64 approveTemplateId, uint64 rejectTemplateId, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenSession) UpdateKey(keyId uint64, approveTemplateId uint64, rejectTemplateId uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.UpdateKey(&_IWarden.TransactOpts, keyId, approveTemplateId, rejectTemplateId, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// UpdateKey is a paid mutator transaction binding the contract method 0xfecc57ec. +// +// Solidity: function updateKey(uint64 keyId, uint64 approveTemplateId, uint64 rejectTemplateId, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactorSession) UpdateKey(keyId uint64, approveTemplateId uint64, rejectTemplateId uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.UpdateKey(&_IWarden.TransactOpts, keyId, approveTemplateId, rejectTemplateId, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// UpdateKeychain is a paid mutator transaction binding the contract method 0x4c683562. +// +// Solidity: function updateKeychain(uint64 keychainId, string name, ((string,uint256)[],(string,uint256)[]) keychainFees, string description, string url, string keybaseId) returns(bool success) +func (_IWarden *IWardenTransactor) UpdateKeychain(opts *bind.TransactOpts, keychainId uint64, name string, keychainFees KeychainFees, description string, url string, keybaseId string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "updateKeychain", keychainId, name, keychainFees, description, url, keybaseId) +} + +// UpdateKeychain is a paid mutator transaction binding the contract method 0x4c683562. +// +// Solidity: function updateKeychain(uint64 keychainId, string name, ((string,uint256)[],(string,uint256)[]) keychainFees, string description, string url, string keybaseId) returns(bool success) +func (_IWarden *IWardenSession) UpdateKeychain(keychainId uint64, name string, keychainFees KeychainFees, description string, url string, keybaseId string) (*types.Transaction, error) { + return _IWarden.Contract.UpdateKeychain(&_IWarden.TransactOpts, keychainId, name, keychainFees, description, url, keybaseId) +} + +// UpdateKeychain is a paid mutator transaction binding the contract method 0x4c683562. +// +// Solidity: function updateKeychain(uint64 keychainId, string name, ((string,uint256)[],(string,uint256)[]) keychainFees, string description, string url, string keybaseId) returns(bool success) +func (_IWarden *IWardenTransactorSession) UpdateKeychain(keychainId uint64, name string, keychainFees KeychainFees, description string, url string, keybaseId string) (*types.Transaction, error) { + return _IWarden.Contract.UpdateKeychain(&_IWarden.TransactOpts, keychainId, name, keychainFees, description, url, keybaseId) +} + +// UpdateSpace is a paid mutator transaction binding the contract method 0x7f903050. +// +// Solidity: function updateSpace(uint64 spaceId, uint64 nonce, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactor) UpdateSpace(opts *bind.TransactOpts, spaceId uint64, nonce uint64, approveAdminTemplateId uint64, rejectAdminTemplateId uint64, approveSignTemplateId uint64, rejectSignTemplateId uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.contract.Transact(opts, "updateSpace", spaceId, nonce, approveAdminTemplateId, rejectAdminTemplateId, approveSignTemplateId, rejectSignTemplateId, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// UpdateSpace is a paid mutator transaction binding the contract method 0x7f903050. +// +// Solidity: function updateSpace(uint64 spaceId, uint64 nonce, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenSession) UpdateSpace(spaceId uint64, nonce uint64, approveAdminTemplateId uint64, rejectAdminTemplateId uint64, approveSignTemplateId uint64, rejectSignTemplateId uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.UpdateSpace(&_IWarden.TransactOpts, spaceId, nonce, approveAdminTemplateId, rejectAdminTemplateId, approveSignTemplateId, rejectSignTemplateId, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// UpdateSpace is a paid mutator transaction binding the contract method 0x7f903050. +// +// Solidity: function updateSpace(uint64 spaceId, uint64 nonce, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId, uint64 actionTimeoutHeight, string expectedApproveExpression, string expectedRejectExpression) returns(bool success) +func (_IWarden *IWardenTransactorSession) UpdateSpace(spaceId uint64, nonce uint64, approveAdminTemplateId uint64, rejectAdminTemplateId uint64, approveSignTemplateId uint64, rejectSignTemplateId uint64, actionTimeoutHeight uint64, expectedApproveExpression string, expectedRejectExpression string) (*types.Transaction, error) { + return _IWarden.Contract.UpdateSpace(&_IWarden.TransactOpts, spaceId, nonce, approveAdminTemplateId, rejectAdminTemplateId, approveSignTemplateId, rejectSignTemplateId, actionTimeoutHeight, expectedApproveExpression, expectedRejectExpression) +} + +// IWardenAddKeychainAdminIterator is returned from FilterAddKeychainAdmin and is used to iterate over the raw logs and unpacked data for AddKeychainAdmin events raised by the IWarden contract. +type IWardenAddKeychainAdminIterator struct { + Event *IWardenAddKeychainAdmin // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenAddKeychainAdminIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenAddKeychainAdmin) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenAddKeychainAdmin) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenAddKeychainAdminIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenAddKeychainAdminIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenAddKeychainAdmin represents a AddKeychainAdmin event raised by the IWarden contract. +type IWardenAddKeychainAdmin struct { + NewAdmin common.Address + Id uint64 + AdminsCount uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddKeychainAdmin is a free log retrieval operation binding the contract event 0x363238dc5ee3ed860e5599b2698d2f74510cedfe6ed9a27eacef2fe5cc46763e. +// +// Solidity: event AddKeychainAdmin(address newAdmin, uint64 indexed id, uint64 adminsCount) +func (_IWarden *IWardenFilterer) FilterAddKeychainAdmin(opts *bind.FilterOpts, id []uint64) (*IWardenAddKeychainAdminIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "AddKeychainAdmin", idRule) + if err != nil { + return nil, err + } + return &IWardenAddKeychainAdminIterator{contract: _IWarden.contract, event: "AddKeychainAdmin", logs: logs, sub: sub}, nil +} + +// WatchAddKeychainAdmin is a free log subscription operation binding the contract event 0x363238dc5ee3ed860e5599b2698d2f74510cedfe6ed9a27eacef2fe5cc46763e. +// +// Solidity: event AddKeychainAdmin(address newAdmin, uint64 indexed id, uint64 adminsCount) +func (_IWarden *IWardenFilterer) WatchAddKeychainAdmin(opts *bind.WatchOpts, sink chan<- *IWardenAddKeychainAdmin, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "AddKeychainAdmin", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenAddKeychainAdmin) + if err := _IWarden.contract.UnpackLog(event, "AddKeychainAdmin", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddKeychainAdmin is a log parse operation binding the contract event 0x363238dc5ee3ed860e5599b2698d2f74510cedfe6ed9a27eacef2fe5cc46763e. +// +// Solidity: event AddKeychainAdmin(address newAdmin, uint64 indexed id, uint64 adminsCount) +func (_IWarden *IWardenFilterer) ParseAddKeychainAdmin(log types.Log) (*IWardenAddKeychainAdmin, error) { + event := new(IWardenAddKeychainAdmin) + if err := _IWarden.contract.UnpackLog(event, "AddKeychainAdmin", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenAddKeychainWriterIterator is returned from FilterAddKeychainWriter and is used to iterate over the raw logs and unpacked data for AddKeychainWriter events raised by the IWarden contract. +type IWardenAddKeychainWriterIterator struct { + Event *IWardenAddKeychainWriter // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenAddKeychainWriterIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenAddKeychainWriter) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenAddKeychainWriter) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenAddKeychainWriterIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenAddKeychainWriterIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenAddKeychainWriter represents a AddKeychainWriter event raised by the IWarden contract. +type IWardenAddKeychainWriter struct { + NewWriter common.Address + Id uint64 + WritersCount uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddKeychainWriter is a free log retrieval operation binding the contract event 0x95209db0173d4ee88ed6a251e6c008e9ef15b765625418c7731c2dad6ba8d008. +// +// Solidity: event AddKeychainWriter(address newWriter, uint64 indexed id, uint64 writersCount) +func (_IWarden *IWardenFilterer) FilterAddKeychainWriter(opts *bind.FilterOpts, id []uint64) (*IWardenAddKeychainWriterIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "AddKeychainWriter", idRule) + if err != nil { + return nil, err + } + return &IWardenAddKeychainWriterIterator{contract: _IWarden.contract, event: "AddKeychainWriter", logs: logs, sub: sub}, nil +} + +// WatchAddKeychainWriter is a free log subscription operation binding the contract event 0x95209db0173d4ee88ed6a251e6c008e9ef15b765625418c7731c2dad6ba8d008. +// +// Solidity: event AddKeychainWriter(address newWriter, uint64 indexed id, uint64 writersCount) +func (_IWarden *IWardenFilterer) WatchAddKeychainWriter(opts *bind.WatchOpts, sink chan<- *IWardenAddKeychainWriter, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "AddKeychainWriter", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenAddKeychainWriter) + if err := _IWarden.contract.UnpackLog(event, "AddKeychainWriter", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddKeychainWriter is a log parse operation binding the contract event 0x95209db0173d4ee88ed6a251e6c008e9ef15b765625418c7731c2dad6ba8d008. +// +// Solidity: event AddKeychainWriter(address newWriter, uint64 indexed id, uint64 writersCount) +func (_IWarden *IWardenFilterer) ParseAddKeychainWriter(log types.Log) (*IWardenAddKeychainWriter, error) { + event := new(IWardenAddKeychainWriter) + if err := _IWarden.contract.UnpackLog(event, "AddKeychainWriter", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenAddSpaceOwnerIterator is returned from FilterAddSpaceOwner and is used to iterate over the raw logs and unpacked data for AddSpaceOwner events raised by the IWarden contract. +type IWardenAddSpaceOwnerIterator struct { + Event *IWardenAddSpaceOwner // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenAddSpaceOwnerIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenAddSpaceOwner) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenAddSpaceOwner) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenAddSpaceOwnerIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenAddSpaceOwnerIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenAddSpaceOwner represents a AddSpaceOwner event raised by the IWarden contract. +type IWardenAddSpaceOwner struct { + SpaceId uint64 + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddSpaceOwner is a free log retrieval operation binding the contract event 0xd5c3b534a5d56cb3bbc8563d5195f83014ec36c258ee04f7add5f4c7518da28b. +// +// Solidity: event AddSpaceOwner(uint64 indexed spaceId, address newOwner) +func (_IWarden *IWardenFilterer) FilterAddSpaceOwner(opts *bind.FilterOpts, spaceId []uint64) (*IWardenAddSpaceOwnerIterator, error) { + + var spaceIdRule []interface{} + for _, spaceIdItem := range spaceId { + spaceIdRule = append(spaceIdRule, spaceIdItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "AddSpaceOwner", spaceIdRule) + if err != nil { + return nil, err + } + return &IWardenAddSpaceOwnerIterator{contract: _IWarden.contract, event: "AddSpaceOwner", logs: logs, sub: sub}, nil +} + +// WatchAddSpaceOwner is a free log subscription operation binding the contract event 0xd5c3b534a5d56cb3bbc8563d5195f83014ec36c258ee04f7add5f4c7518da28b. +// +// Solidity: event AddSpaceOwner(uint64 indexed spaceId, address newOwner) +func (_IWarden *IWardenFilterer) WatchAddSpaceOwner(opts *bind.WatchOpts, sink chan<- *IWardenAddSpaceOwner, spaceId []uint64) (event.Subscription, error) { + + var spaceIdRule []interface{} + for _, spaceIdItem := range spaceId { + spaceIdRule = append(spaceIdRule, spaceIdItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "AddSpaceOwner", spaceIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenAddSpaceOwner) + if err := _IWarden.contract.UnpackLog(event, "AddSpaceOwner", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddSpaceOwner is a log parse operation binding the contract event 0xd5c3b534a5d56cb3bbc8563d5195f83014ec36c258ee04f7add5f4c7518da28b. +// +// Solidity: event AddSpaceOwner(uint64 indexed spaceId, address newOwner) +func (_IWarden *IWardenFilterer) ParseAddSpaceOwner(log types.Log) (*IWardenAddSpaceOwner, error) { + event := new(IWardenAddSpaceOwner) + if err := _IWarden.contract.UnpackLog(event, "AddSpaceOwner", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenFulfilSignRequestIterator is returned from FilterFulfilSignRequest and is used to iterate over the raw logs and unpacked data for FulfilSignRequest events raised by the IWarden contract. +type IWardenFulfilSignRequestIterator struct { + Event *IWardenFulfilSignRequest // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenFulfilSignRequestIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenFulfilSignRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenFulfilSignRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenFulfilSignRequestIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenFulfilSignRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenFulfilSignRequest represents a FulfilSignRequest event raised by the IWarden contract. +type IWardenFulfilSignRequest struct { + Id uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterFulfilSignRequest is a free log retrieval operation binding the contract event 0x4d8a43263e214628c121391980488d29777a4d0160d73b07accb564be2a8db44. +// +// Solidity: event FulfilSignRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) FilterFulfilSignRequest(opts *bind.FilterOpts, id []uint64) (*IWardenFulfilSignRequestIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "FulfilSignRequest", idRule) + if err != nil { + return nil, err + } + return &IWardenFulfilSignRequestIterator{contract: _IWarden.contract, event: "FulfilSignRequest", logs: logs, sub: sub}, nil +} + +// WatchFulfilSignRequest is a free log subscription operation binding the contract event 0x4d8a43263e214628c121391980488d29777a4d0160d73b07accb564be2a8db44. +// +// Solidity: event FulfilSignRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) WatchFulfilSignRequest(opts *bind.WatchOpts, sink chan<- *IWardenFulfilSignRequest, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "FulfilSignRequest", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenFulfilSignRequest) + if err := _IWarden.contract.UnpackLog(event, "FulfilSignRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseFulfilSignRequest is a log parse operation binding the contract event 0x4d8a43263e214628c121391980488d29777a4d0160d73b07accb564be2a8db44. +// +// Solidity: event FulfilSignRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) ParseFulfilSignRequest(log types.Log) (*IWardenFulfilSignRequest, error) { + event := new(IWardenFulfilSignRequest) + if err := _IWarden.contract.UnpackLog(event, "FulfilSignRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenNewKeyIterator is returned from FilterNewKey and is used to iterate over the raw logs and unpacked data for NewKey events raised by the IWarden contract. +type IWardenNewKeyIterator struct { + Event *IWardenNewKey // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenNewKeyIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenNewKey) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenNewKey) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenNewKeyIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenNewKeyIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenNewKey represents a NewKey event raised by the IWarden contract. +type IWardenNewKey struct { + Id uint64 + KeyType uint8 + SpaceId uint64 + KeychainId uint64 + ApproveTemplateId uint64 + RejectTemplateId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewKey is a free log retrieval operation binding the contract event 0x49d9097e1d60d8d284c2449adb78b4b296b693d824d18097a2998a8da970aa10. +// +// Solidity: event NewKey(uint64 indexed id, uint8 keyType, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId) +func (_IWarden *IWardenFilterer) FilterNewKey(opts *bind.FilterOpts, id []uint64) (*IWardenNewKeyIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "NewKey", idRule) + if err != nil { + return nil, err + } + return &IWardenNewKeyIterator{contract: _IWarden.contract, event: "NewKey", logs: logs, sub: sub}, nil +} + +// WatchNewKey is a free log subscription operation binding the contract event 0x49d9097e1d60d8d284c2449adb78b4b296b693d824d18097a2998a8da970aa10. +// +// Solidity: event NewKey(uint64 indexed id, uint8 keyType, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId) +func (_IWarden *IWardenFilterer) WatchNewKey(opts *bind.WatchOpts, sink chan<- *IWardenNewKey, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "NewKey", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenNewKey) + if err := _IWarden.contract.UnpackLog(event, "NewKey", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNewKey is a log parse operation binding the contract event 0x49d9097e1d60d8d284c2449adb78b4b296b693d824d18097a2998a8da970aa10. +// +// Solidity: event NewKey(uint64 indexed id, uint8 keyType, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId) +func (_IWarden *IWardenFilterer) ParseNewKey(log types.Log) (*IWardenNewKey, error) { + event := new(IWardenNewKey) + if err := _IWarden.contract.UnpackLog(event, "NewKey", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenNewKeyRequestIterator is returned from FilterNewKeyRequest and is used to iterate over the raw logs and unpacked data for NewKeyRequest events raised by the IWarden contract. +type IWardenNewKeyRequestIterator struct { + Event *IWardenNewKeyRequest // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenNewKeyRequestIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenNewKeyRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenNewKeyRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenNewKeyRequestIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenNewKeyRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenNewKeyRequest represents a NewKeyRequest event raised by the IWarden contract. +type IWardenNewKeyRequest struct { + Id uint64 + SpaceId uint64 + KeychainId uint64 + ApproveTemplateId uint64 + RejectTemplateId uint64 + KeyType uint8 + Creator common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewKeyRequest is a free log retrieval operation binding the contract event 0xac8bd313e734c94dfb2ebe4e42d211d311c4106025a2c6002955c3f8dd593733. +// +// Solidity: event NewKeyRequest(uint64 indexed id, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId, uint8 keyType, address creator) +func (_IWarden *IWardenFilterer) FilterNewKeyRequest(opts *bind.FilterOpts, id []uint64) (*IWardenNewKeyRequestIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "NewKeyRequest", idRule) + if err != nil { + return nil, err + } + return &IWardenNewKeyRequestIterator{contract: _IWarden.contract, event: "NewKeyRequest", logs: logs, sub: sub}, nil +} + +// WatchNewKeyRequest is a free log subscription operation binding the contract event 0xac8bd313e734c94dfb2ebe4e42d211d311c4106025a2c6002955c3f8dd593733. +// +// Solidity: event NewKeyRequest(uint64 indexed id, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId, uint8 keyType, address creator) +func (_IWarden *IWardenFilterer) WatchNewKeyRequest(opts *bind.WatchOpts, sink chan<- *IWardenNewKeyRequest, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "NewKeyRequest", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenNewKeyRequest) + if err := _IWarden.contract.UnpackLog(event, "NewKeyRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNewKeyRequest is a log parse operation binding the contract event 0xac8bd313e734c94dfb2ebe4e42d211d311c4106025a2c6002955c3f8dd593733. +// +// Solidity: event NewKeyRequest(uint64 indexed id, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId, uint8 keyType, address creator) +func (_IWarden *IWardenFilterer) ParseNewKeyRequest(log types.Log) (*IWardenNewKeyRequest, error) { + event := new(IWardenNewKeyRequest) + if err := _IWarden.contract.UnpackLog(event, "NewKeyRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenNewKeychainIterator is returned from FilterNewKeychain and is used to iterate over the raw logs and unpacked data for NewKeychain events raised by the IWarden contract. +type IWardenNewKeychainIterator struct { + Event *IWardenNewKeychain // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenNewKeychainIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenNewKeychain) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenNewKeychain) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenNewKeychainIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenNewKeychainIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenNewKeychain represents a NewKeychain event raised by the IWarden contract. +type IWardenNewKeychain struct { + Id uint64 + Creator common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewKeychain is a free log retrieval operation binding the contract event 0xbf4749d4199931cc72db43a71a673c8a5d90a98fedbea9c172788448b61a8f8d. +// +// Solidity: event NewKeychain(uint64 indexed id, address creator) +func (_IWarden *IWardenFilterer) FilterNewKeychain(opts *bind.FilterOpts, id []uint64) (*IWardenNewKeychainIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "NewKeychain", idRule) + if err != nil { + return nil, err + } + return &IWardenNewKeychainIterator{contract: _IWarden.contract, event: "NewKeychain", logs: logs, sub: sub}, nil +} + +// WatchNewKeychain is a free log subscription operation binding the contract event 0xbf4749d4199931cc72db43a71a673c8a5d90a98fedbea9c172788448b61a8f8d. +// +// Solidity: event NewKeychain(uint64 indexed id, address creator) +func (_IWarden *IWardenFilterer) WatchNewKeychain(opts *bind.WatchOpts, sink chan<- *IWardenNewKeychain, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "NewKeychain", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenNewKeychain) + if err := _IWarden.contract.UnpackLog(event, "NewKeychain", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNewKeychain is a log parse operation binding the contract event 0xbf4749d4199931cc72db43a71a673c8a5d90a98fedbea9c172788448b61a8f8d. +// +// Solidity: event NewKeychain(uint64 indexed id, address creator) +func (_IWarden *IWardenFilterer) ParseNewKeychain(log types.Log) (*IWardenNewKeychain, error) { + event := new(IWardenNewKeychain) + if err := _IWarden.contract.UnpackLog(event, "NewKeychain", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenNewSignRequestIterator is returned from FilterNewSignRequest and is used to iterate over the raw logs and unpacked data for NewSignRequest events raised by the IWarden contract. +type IWardenNewSignRequestIterator struct { + Event *IWardenNewSignRequest // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenNewSignRequestIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenNewSignRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenNewSignRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenNewSignRequestIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenNewSignRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenNewSignRequest represents a NewSignRequest event raised by the IWarden contract. +type IWardenNewSignRequest struct { + Id uint64 + KeyId uint64 + Creator common.Address + BroadcastType uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewSignRequest is a free log retrieval operation binding the contract event 0x3187426ba54d86726fad12c0e947eaca12d8d04cb8e5a97f1a48e4277d63005f. +// +// Solidity: event NewSignRequest(uint64 indexed id, uint64 keyId, address creator, uint8 broadcastType) +func (_IWarden *IWardenFilterer) FilterNewSignRequest(opts *bind.FilterOpts, id []uint64) (*IWardenNewSignRequestIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "NewSignRequest", idRule) + if err != nil { + return nil, err + } + return &IWardenNewSignRequestIterator{contract: _IWarden.contract, event: "NewSignRequest", logs: logs, sub: sub}, nil +} + +// WatchNewSignRequest is a free log subscription operation binding the contract event 0x3187426ba54d86726fad12c0e947eaca12d8d04cb8e5a97f1a48e4277d63005f. +// +// Solidity: event NewSignRequest(uint64 indexed id, uint64 keyId, address creator, uint8 broadcastType) +func (_IWarden *IWardenFilterer) WatchNewSignRequest(opts *bind.WatchOpts, sink chan<- *IWardenNewSignRequest, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "NewSignRequest", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenNewSignRequest) + if err := _IWarden.contract.UnpackLog(event, "NewSignRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNewSignRequest is a log parse operation binding the contract event 0x3187426ba54d86726fad12c0e947eaca12d8d04cb8e5a97f1a48e4277d63005f. +// +// Solidity: event NewSignRequest(uint64 indexed id, uint64 keyId, address creator, uint8 broadcastType) +func (_IWarden *IWardenFilterer) ParseNewSignRequest(log types.Log) (*IWardenNewSignRequest, error) { + event := new(IWardenNewSignRequest) + if err := _IWarden.contract.UnpackLog(event, "NewSignRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenNewSpaceIterator is returned from FilterNewSpace and is used to iterate over the raw logs and unpacked data for NewSpace events raised by the IWarden contract. +type IWardenNewSpaceIterator struct { + Event *IWardenNewSpace // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenNewSpaceIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenNewSpace) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenNewSpace) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenNewSpaceIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenNewSpaceIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenNewSpace represents a NewSpace event raised by the IWarden contract. +type IWardenNewSpace struct { + Id uint64 + Creator common.Address + OwnersCount uint64 + ApproveAdminTemplateId uint64 + RejectAdminTemplateId uint64 + ApproveSignTemplateId uint64 + RejectSignTemplateId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewSpace is a free log retrieval operation binding the contract event 0x1d673e16d9a82fd9a44a946aea320be2cdc951dc51ecb22fbde2396d9c49b4a7. +// +// Solidity: event NewSpace(uint64 indexed id, address creator, uint64 ownersCount, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId) +func (_IWarden *IWardenFilterer) FilterNewSpace(opts *bind.FilterOpts, id []uint64) (*IWardenNewSpaceIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "NewSpace", idRule) + if err != nil { + return nil, err + } + return &IWardenNewSpaceIterator{contract: _IWarden.contract, event: "NewSpace", logs: logs, sub: sub}, nil +} + +// WatchNewSpace is a free log subscription operation binding the contract event 0x1d673e16d9a82fd9a44a946aea320be2cdc951dc51ecb22fbde2396d9c49b4a7. +// +// Solidity: event NewSpace(uint64 indexed id, address creator, uint64 ownersCount, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId) +func (_IWarden *IWardenFilterer) WatchNewSpace(opts *bind.WatchOpts, sink chan<- *IWardenNewSpace, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "NewSpace", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenNewSpace) + if err := _IWarden.contract.UnpackLog(event, "NewSpace", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNewSpace is a log parse operation binding the contract event 0x1d673e16d9a82fd9a44a946aea320be2cdc951dc51ecb22fbde2396d9c49b4a7. +// +// Solidity: event NewSpace(uint64 indexed id, address creator, uint64 ownersCount, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId) +func (_IWarden *IWardenFilterer) ParseNewSpace(log types.Log) (*IWardenNewSpace, error) { + event := new(IWardenNewSpace) + if err := _IWarden.contract.UnpackLog(event, "NewSpace", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenRejectKeyRequestIterator is returned from FilterRejectKeyRequest and is used to iterate over the raw logs and unpacked data for RejectKeyRequest events raised by the IWarden contract. +type IWardenRejectKeyRequestIterator struct { + Event *IWardenRejectKeyRequest // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenRejectKeyRequestIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenRejectKeyRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenRejectKeyRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenRejectKeyRequestIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenRejectKeyRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenRejectKeyRequest represents a RejectKeyRequest event raised by the IWarden contract. +type IWardenRejectKeyRequest struct { + Id uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRejectKeyRequest is a free log retrieval operation binding the contract event 0xeb94cbafda4c7f6a07cd1d92397097ac757e494d72e3e3cabb3c618ca559a720. +// +// Solidity: event RejectKeyRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) FilterRejectKeyRequest(opts *bind.FilterOpts, id []uint64) (*IWardenRejectKeyRequestIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "RejectKeyRequest", idRule) + if err != nil { + return nil, err + } + return &IWardenRejectKeyRequestIterator{contract: _IWarden.contract, event: "RejectKeyRequest", logs: logs, sub: sub}, nil +} + +// WatchRejectKeyRequest is a free log subscription operation binding the contract event 0xeb94cbafda4c7f6a07cd1d92397097ac757e494d72e3e3cabb3c618ca559a720. +// +// Solidity: event RejectKeyRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) WatchRejectKeyRequest(opts *bind.WatchOpts, sink chan<- *IWardenRejectKeyRequest, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "RejectKeyRequest", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenRejectKeyRequest) + if err := _IWarden.contract.UnpackLog(event, "RejectKeyRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRejectKeyRequest is a log parse operation binding the contract event 0xeb94cbafda4c7f6a07cd1d92397097ac757e494d72e3e3cabb3c618ca559a720. +// +// Solidity: event RejectKeyRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) ParseRejectKeyRequest(log types.Log) (*IWardenRejectKeyRequest, error) { + event := new(IWardenRejectKeyRequest) + if err := _IWarden.contract.UnpackLog(event, "RejectKeyRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenRejectSignRequestIterator is returned from FilterRejectSignRequest and is used to iterate over the raw logs and unpacked data for RejectSignRequest events raised by the IWarden contract. +type IWardenRejectSignRequestIterator struct { + Event *IWardenRejectSignRequest // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenRejectSignRequestIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenRejectSignRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenRejectSignRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenRejectSignRequestIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenRejectSignRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenRejectSignRequest represents a RejectSignRequest event raised by the IWarden contract. +type IWardenRejectSignRequest struct { + Id uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRejectSignRequest is a free log retrieval operation binding the contract event 0x9876fe372fa159e1ec936e70ab5196b67d4f8ea9b99022ea49f9e3770237e205. +// +// Solidity: event RejectSignRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) FilterRejectSignRequest(opts *bind.FilterOpts, id []uint64) (*IWardenRejectSignRequestIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "RejectSignRequest", idRule) + if err != nil { + return nil, err + } + return &IWardenRejectSignRequestIterator{contract: _IWarden.contract, event: "RejectSignRequest", logs: logs, sub: sub}, nil +} + +// WatchRejectSignRequest is a free log subscription operation binding the contract event 0x9876fe372fa159e1ec936e70ab5196b67d4f8ea9b99022ea49f9e3770237e205. +// +// Solidity: event RejectSignRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) WatchRejectSignRequest(opts *bind.WatchOpts, sink chan<- *IWardenRejectSignRequest, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "RejectSignRequest", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenRejectSignRequest) + if err := _IWarden.contract.UnpackLog(event, "RejectSignRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRejectSignRequest is a log parse operation binding the contract event 0x9876fe372fa159e1ec936e70ab5196b67d4f8ea9b99022ea49f9e3770237e205. +// +// Solidity: event RejectSignRequest(uint64 indexed id) +func (_IWarden *IWardenFilterer) ParseRejectSignRequest(log types.Log) (*IWardenRejectSignRequest, error) { + event := new(IWardenRejectSignRequest) + if err := _IWarden.contract.UnpackLog(event, "RejectSignRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenRemoveKeychainAdminIterator is returned from FilterRemoveKeychainAdmin and is used to iterate over the raw logs and unpacked data for RemoveKeychainAdmin events raised by the IWarden contract. +type IWardenRemoveKeychainAdminIterator struct { + Event *IWardenRemoveKeychainAdmin // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenRemoveKeychainAdminIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenRemoveKeychainAdmin) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenRemoveKeychainAdmin) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenRemoveKeychainAdminIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenRemoveKeychainAdminIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenRemoveKeychainAdmin represents a RemoveKeychainAdmin event raised by the IWarden contract. +type IWardenRemoveKeychainAdmin struct { + KeychainId uint64 + Admin common.Address + AdminsCount uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRemoveKeychainAdmin is a free log retrieval operation binding the contract event 0x8e8e92a5097448dcaea8690cf868dc7bdab4f7d72cff973706bb57a6d15ba681. +// +// Solidity: event RemoveKeychainAdmin(uint64 indexed keychainId, address admin, uint64 adminsCount) +func (_IWarden *IWardenFilterer) FilterRemoveKeychainAdmin(opts *bind.FilterOpts, keychainId []uint64) (*IWardenRemoveKeychainAdminIterator, error) { + + var keychainIdRule []interface{} + for _, keychainIdItem := range keychainId { + keychainIdRule = append(keychainIdRule, keychainIdItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "RemoveKeychainAdmin", keychainIdRule) + if err != nil { + return nil, err + } + return &IWardenRemoveKeychainAdminIterator{contract: _IWarden.contract, event: "RemoveKeychainAdmin", logs: logs, sub: sub}, nil +} + +// WatchRemoveKeychainAdmin is a free log subscription operation binding the contract event 0x8e8e92a5097448dcaea8690cf868dc7bdab4f7d72cff973706bb57a6d15ba681. +// +// Solidity: event RemoveKeychainAdmin(uint64 indexed keychainId, address admin, uint64 adminsCount) +func (_IWarden *IWardenFilterer) WatchRemoveKeychainAdmin(opts *bind.WatchOpts, sink chan<- *IWardenRemoveKeychainAdmin, keychainId []uint64) (event.Subscription, error) { + + var keychainIdRule []interface{} + for _, keychainIdItem := range keychainId { + keychainIdRule = append(keychainIdRule, keychainIdItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "RemoveKeychainAdmin", keychainIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenRemoveKeychainAdmin) + if err := _IWarden.contract.UnpackLog(event, "RemoveKeychainAdmin", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRemoveKeychainAdmin is a log parse operation binding the contract event 0x8e8e92a5097448dcaea8690cf868dc7bdab4f7d72cff973706bb57a6d15ba681. +// +// Solidity: event RemoveKeychainAdmin(uint64 indexed keychainId, address admin, uint64 adminsCount) +func (_IWarden *IWardenFilterer) ParseRemoveKeychainAdmin(log types.Log) (*IWardenRemoveKeychainAdmin, error) { + event := new(IWardenRemoveKeychainAdmin) + if err := _IWarden.contract.UnpackLog(event, "RemoveKeychainAdmin", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenRemoveSpaceOwnerIterator is returned from FilterRemoveSpaceOwner and is used to iterate over the raw logs and unpacked data for RemoveSpaceOwner events raised by the IWarden contract. +type IWardenRemoveSpaceOwnerIterator struct { + Event *IWardenRemoveSpaceOwner // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenRemoveSpaceOwnerIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenRemoveSpaceOwner) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenRemoveSpaceOwner) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenRemoveSpaceOwnerIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenRemoveSpaceOwnerIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenRemoveSpaceOwner represents a RemoveSpaceOwner event raised by the IWarden contract. +type IWardenRemoveSpaceOwner struct { + SpaceId uint64 + RemovedOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRemoveSpaceOwner is a free log retrieval operation binding the contract event 0xfe361f4258d2e824c88b5eff2a6158a8195a8e287d5ed09535d5c682af00de56. +// +// Solidity: event RemoveSpaceOwner(uint64 indexed spaceId, address removedOwner) +func (_IWarden *IWardenFilterer) FilterRemoveSpaceOwner(opts *bind.FilterOpts, spaceId []uint64) (*IWardenRemoveSpaceOwnerIterator, error) { + + var spaceIdRule []interface{} + for _, spaceIdItem := range spaceId { + spaceIdRule = append(spaceIdRule, spaceIdItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "RemoveSpaceOwner", spaceIdRule) + if err != nil { + return nil, err + } + return &IWardenRemoveSpaceOwnerIterator{contract: _IWarden.contract, event: "RemoveSpaceOwner", logs: logs, sub: sub}, nil +} + +// WatchRemoveSpaceOwner is a free log subscription operation binding the contract event 0xfe361f4258d2e824c88b5eff2a6158a8195a8e287d5ed09535d5c682af00de56. +// +// Solidity: event RemoveSpaceOwner(uint64 indexed spaceId, address removedOwner) +func (_IWarden *IWardenFilterer) WatchRemoveSpaceOwner(opts *bind.WatchOpts, sink chan<- *IWardenRemoveSpaceOwner, spaceId []uint64) (event.Subscription, error) { + + var spaceIdRule []interface{} + for _, spaceIdItem := range spaceId { + spaceIdRule = append(spaceIdRule, spaceIdItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "RemoveSpaceOwner", spaceIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenRemoveSpaceOwner) + if err := _IWarden.contract.UnpackLog(event, "RemoveSpaceOwner", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRemoveSpaceOwner is a log parse operation binding the contract event 0xfe361f4258d2e824c88b5eff2a6158a8195a8e287d5ed09535d5c682af00de56. +// +// Solidity: event RemoveSpaceOwner(uint64 indexed spaceId, address removedOwner) +func (_IWarden *IWardenFilterer) ParseRemoveSpaceOwner(log types.Log) (*IWardenRemoveSpaceOwner, error) { + event := new(IWardenRemoveSpaceOwner) + if err := _IWarden.contract.UnpackLog(event, "RemoveSpaceOwner", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenUpdateKeyIterator is returned from FilterUpdateKey and is used to iterate over the raw logs and unpacked data for UpdateKey events raised by the IWarden contract. +type IWardenUpdateKeyIterator struct { + Event *IWardenUpdateKey // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenUpdateKeyIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenUpdateKey) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenUpdateKey) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenUpdateKeyIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenUpdateKeyIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenUpdateKey represents a UpdateKey event raised by the IWarden contract. +type IWardenUpdateKey struct { + Id uint64 + ApproveTemplateId uint64 + RejectTemplateId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdateKey is a free log retrieval operation binding the contract event 0x9a8c43b6ec36deb25cf6dab899dda357fa9d946a014ff68363773222e83467f2. +// +// Solidity: event UpdateKey(uint64 indexed id, uint64 approveTemplateId, uint64 rejectTemplateId) +func (_IWarden *IWardenFilterer) FilterUpdateKey(opts *bind.FilterOpts, id []uint64) (*IWardenUpdateKeyIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "UpdateKey", idRule) + if err != nil { + return nil, err + } + return &IWardenUpdateKeyIterator{contract: _IWarden.contract, event: "UpdateKey", logs: logs, sub: sub}, nil +} + +// WatchUpdateKey is a free log subscription operation binding the contract event 0x9a8c43b6ec36deb25cf6dab899dda357fa9d946a014ff68363773222e83467f2. +// +// Solidity: event UpdateKey(uint64 indexed id, uint64 approveTemplateId, uint64 rejectTemplateId) +func (_IWarden *IWardenFilterer) WatchUpdateKey(opts *bind.WatchOpts, sink chan<- *IWardenUpdateKey, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "UpdateKey", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenUpdateKey) + if err := _IWarden.contract.UnpackLog(event, "UpdateKey", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpdateKey is a log parse operation binding the contract event 0x9a8c43b6ec36deb25cf6dab899dda357fa9d946a014ff68363773222e83467f2. +// +// Solidity: event UpdateKey(uint64 indexed id, uint64 approveTemplateId, uint64 rejectTemplateId) +func (_IWarden *IWardenFilterer) ParseUpdateKey(log types.Log) (*IWardenUpdateKey, error) { + event := new(IWardenUpdateKey) + if err := _IWarden.contract.UnpackLog(event, "UpdateKey", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenUpdateKeychainIterator is returned from FilterUpdateKeychain and is used to iterate over the raw logs and unpacked data for UpdateKeychain events raised by the IWarden contract. +type IWardenUpdateKeychainIterator struct { + Event *IWardenUpdateKeychain // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenUpdateKeychainIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenUpdateKeychain) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenUpdateKeychain) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenUpdateKeychainIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenUpdateKeychainIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenUpdateKeychain represents a UpdateKeychain event raised by the IWarden contract. +type IWardenUpdateKeychain struct { + Id uint64 + KeychainFees KeychainFees + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdateKeychain is a free log retrieval operation binding the contract event 0x66076723d87c639e1336db5ad634dc4108ca17079e7352fe66e06067c453b8b0. +// +// Solidity: event UpdateKeychain(uint64 indexed id, ((string,uint256)[],(string,uint256)[]) keychainFees) +func (_IWarden *IWardenFilterer) FilterUpdateKeychain(opts *bind.FilterOpts, id []uint64) (*IWardenUpdateKeychainIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "UpdateKeychain", idRule) + if err != nil { + return nil, err + } + return &IWardenUpdateKeychainIterator{contract: _IWarden.contract, event: "UpdateKeychain", logs: logs, sub: sub}, nil +} + +// WatchUpdateKeychain is a free log subscription operation binding the contract event 0x66076723d87c639e1336db5ad634dc4108ca17079e7352fe66e06067c453b8b0. +// +// Solidity: event UpdateKeychain(uint64 indexed id, ((string,uint256)[],(string,uint256)[]) keychainFees) +func (_IWarden *IWardenFilterer) WatchUpdateKeychain(opts *bind.WatchOpts, sink chan<- *IWardenUpdateKeychain, id []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "UpdateKeychain", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenUpdateKeychain) + if err := _IWarden.contract.UnpackLog(event, "UpdateKeychain", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpdateKeychain is a log parse operation binding the contract event 0x66076723d87c639e1336db5ad634dc4108ca17079e7352fe66e06067c453b8b0. +// +// Solidity: event UpdateKeychain(uint64 indexed id, ((string,uint256)[],(string,uint256)[]) keychainFees) +func (_IWarden *IWardenFilterer) ParseUpdateKeychain(log types.Log) (*IWardenUpdateKeychain, error) { + event := new(IWardenUpdateKeychain) + if err := _IWarden.contract.UnpackLog(event, "UpdateKeychain", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IWardenUpdateSpaceIterator is returned from FilterUpdateSpace and is used to iterate over the raw logs and unpacked data for UpdateSpace events raised by the IWarden contract. +type IWardenUpdateSpaceIterator struct { + Event *IWardenUpdateSpace // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IWardenUpdateSpaceIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IWardenUpdateSpace) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IWardenUpdateSpace) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IWardenUpdateSpaceIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IWardenUpdateSpaceIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IWardenUpdateSpace represents a UpdateSpace event raised by the IWarden contract. +type IWardenUpdateSpace struct { + SpaceId uint64 + ApproveAdminTemplateId uint64 + RejectAdminTemplateId uint64 + ApproveSignTemplateId uint64 + RejectSignTemplateId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdateSpace is a free log retrieval operation binding the contract event 0xacab71b9a81541b5ce6900189882a3a6ee548e353e6644143c3b919924c0ac69. +// +// Solidity: event UpdateSpace(uint64 indexed spaceId, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId) +func (_IWarden *IWardenFilterer) FilterUpdateSpace(opts *bind.FilterOpts, spaceId []uint64) (*IWardenUpdateSpaceIterator, error) { + + var spaceIdRule []interface{} + for _, spaceIdItem := range spaceId { + spaceIdRule = append(spaceIdRule, spaceIdItem) + } + + logs, sub, err := _IWarden.contract.FilterLogs(opts, "UpdateSpace", spaceIdRule) + if err != nil { + return nil, err + } + return &IWardenUpdateSpaceIterator{contract: _IWarden.contract, event: "UpdateSpace", logs: logs, sub: sub}, nil +} + +// WatchUpdateSpace is a free log subscription operation binding the contract event 0xacab71b9a81541b5ce6900189882a3a6ee548e353e6644143c3b919924c0ac69. +// +// Solidity: event UpdateSpace(uint64 indexed spaceId, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId) +func (_IWarden *IWardenFilterer) WatchUpdateSpace(opts *bind.WatchOpts, sink chan<- *IWardenUpdateSpace, spaceId []uint64) (event.Subscription, error) { + + var spaceIdRule []interface{} + for _, spaceIdItem := range spaceId { + spaceIdRule = append(spaceIdRule, spaceIdItem) + } + + logs, sub, err := _IWarden.contract.WatchLogs(opts, "UpdateSpace", spaceIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IWardenUpdateSpace) + if err := _IWarden.contract.UnpackLog(event, "UpdateSpace", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpdateSpace is a log parse operation binding the contract event 0xacab71b9a81541b5ce6900189882a3a6ee548e353e6644143c3b919924c0ac69. +// +// Solidity: event UpdateSpace(uint64 indexed spaceId, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId) +func (_IWarden *IWardenFilterer) ParseUpdateSpace(log types.Log) (*IWardenUpdateSpace, error) { + event := new(IWardenUpdateSpace) + if err := _IWarden.contract.UnpackLog(event, "UpdateSpace", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/src/orders/precompiles/warden/IWarden.sol b/src/orders/precompiles/warden/IWarden.sol new file mode 100644 index 0000000..e5c6afc --- /dev/null +++ b/src/orders/precompiles/warden/IWarden.sol @@ -0,0 +1,574 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.18; + +import "../common/Types.sol"; + +/// @dev The IWarden contract's address. +address constant IWARDEN_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000900; + +/// @dev The IWarden contract's instance. +IWarden constant IWARDEN_CONTRACT = IWarden(IWARDEN_PRECOMPILE_ADDRESS); + +struct KeychainFees { + Types.Coin[] keyReq; + Types.Coin[] sigReq; +} + +struct Key { + uint64 id; + uint64 spaceId; + uint64 keychainId; + KeyType keyType; + bytes publicKey; + uint64 approveTemplateId; + uint64 rejectTemplateId; +} + +struct KeyResponse { + Key key; + AddressesResponse[] addresses; +} + +struct AddressesResponse { + string addressValue; + AddressType addressType; +} + +struct KeyRequest { + uint64 id; + address creator; + uint64 spaceId; + uint64 keychainId; + KeyType keyType; + KeyRequestStatus status; + string rejectReason; + uint64 approveTemplateId; + uint64 rejectTemplateId; + Types.Coin[] deductedKeychainFees; +} + +struct Keychain { + uint64 id; + address creator; + string name; + address[] admins; + address[] writers; + KeychainFees fees; + string description; + string url; + string keybaseId; +} + +struct SignRequest { + uint64 id; + address creator; + uint64 keyId; + bytes dataForSigning; + SignRequestStatus status; + bytes result; + bytes encryptionKey; + Types.Coin[] deductedKeychainFees; + BroadcastType broadcastType; +} + +struct Space { + uint64 id; + address creator; + address[] owners; + uint64 nonce; + uint64 approveAdminTemplateId; + uint64 rejectAdminTemplateId; + uint64 approveSignTemplateId; + uint64 rejectSignTemplateId; +} + +enum AddressType { + Unspecified, + Ethereum, + Osmosis +} + +enum KeyType { + Unspecified, + EcdsaSecp256k1, + EddsaEd25519 +} + +enum KeyRequestStatus { + Unspecified, + Pending, + Fulfilled, + Rejected +} + +enum SignRequestStatus { + Unspecified, + Pending, + Fulfilled, + Rejected +} + +enum BroadcastType { + Disabled, + Automatic +} + +enum OptionalBroadcastType { + Nonspecified, + Disabled, + Automatic +} + +/** + * @author Warden Team + * @title x/warden Interface + * @dev The interface through which users and solidity contracts will interact with x/warden. + * @custom:address 0x0000000000000000000000000000000000000900 + */ +interface IWarden { + /// @dev Defines a method for adding a new admin to a keychain. + /// @param keychainId The keychain id + /// @param newAdmin The new admin's address + /// @return success If execution was successful + function addKeychainAdmin( + uint64 keychainId, + address newAdmin + ) external returns (bool success); + + /// @dev Defines a method for adding a new writer to a keychain. + /// @param keychainId The keychain id + /// @param newWriter The new writer's address + /// @return success If execution was successful + function addKeychainWriter( + uint64 keychainId, + address newWriter + ) external returns (bool success); + + /// @dev Defines a method to fulfil a key request. + /// @param requestId The request id + /// @param pubKey The new created public key + /// @return success If execution was successful + function fulfilKeyRequest( + uint64 requestId, + bytes calldata pubKey + ) external returns (bool success); + + /// @dev Defines a method to reject a key request. + /// @param requestId The request id + /// @param rejectReason The reject reason + /// @return success If execution was successful + function rejectKeyRequest( + uint64 requestId, + string calldata rejectReason + ) external returns (bool success); + + /// @dev Defines a method to fulfil a sign request. + /// @param requestId The request id + /// @param signedData The signed data + /// @return success If execution was successful + function fulfilSignRequest( + uint64 requestId, + bytes calldata signedData + ) external returns (bool success); + + /// @dev Defines a method to reject a sign request. + /// @param requestId The request id + /// @param rejectReason The reject reason + /// @return success If execution was successful + function rejectSignRequest( + uint64 requestId, + string calldata rejectReason + ) external returns (bool success); + + /// @dev Defines a method to create a new keychain. + /// @param name The keychain name + /// @param keychainFees The keychain fees + /// @param description The keychain description + /// @param url The keychain url + /// @param keybaseId The keychain keybase id + /// @return id The id of the keychain + function newKeychain( + string calldata name, + KeychainFees calldata keychainFees, + string calldata description, + string calldata url, + string calldata keybaseId + ) external returns (uint64 id); + + /// @dev Defines a method to create a new space. + /// @param approveAdminTemplateId The template id of approve admin action + /// @param rejectAdminTemplateId The template id of reject admin action + /// @param approveSignTemplateId The template id of approve sign action + /// @param rejectSignTemplateId The template id of reject sign action + /// @param additionalOwners Additional space owners + /// @return id The id of the space + function newSpace( + uint64 approveAdminTemplateId, + uint64 rejectAdminTemplateId, + uint64 approveSignTemplateId, + uint64 rejectSignTemplateId, + address[] calldata additionalOwners + ) external returns (uint64 id); + + /// @dev Defines a method to remove an admin from keychain. + /// @param keychainId The id of the keychain + /// @param admin The admin address + /// @return success If execution was successful + function removeKeychainAdmin( + uint64 keychainId, + address admin + ) external returns (bool success); + + /// @dev Defines a method to update a keychain. + /// @param keychainId The keychain id + /// @param name The keychain name + /// @param keychainFees The keychain fees + /// @param description The keychain description + /// @param url The keychain url + /// @param keybaseId The keychain keybase id + /// @return success If execution was successful + function updateKeychain( + uint64 keychainId, + string calldata name, + KeychainFees calldata keychainFees, + string calldata description, + string calldata url, + string calldata keybaseId + ) external returns (bool success); + + /// @dev Defines a method to add a space owner. + /// @param spaceId The space id + /// @param newOwner The new owner + /// @param nonce The nonce + /// @param actionTimeoutHeight The block height up until this action can be executed + /// @param expectedApproveExpression The definition of expected approval expression the action is created with + /// @param expectedRejectExpression The definition of expected reject expression the action is created with + /// @return success If execution was successful + function addSpaceOwner( + uint64 spaceId, + address newOwner, + uint64 nonce, + uint64 actionTimeoutHeight, + string calldata expectedApproveExpression, + string calldata expectedRejectExpression + ) external returns (bool success); + + /// @dev Defines a method to remove a space owner. + /// @param spaceId The space id + /// @param owner The owner + /// @param nonce The nonce + /// @param actionTimeoutHeight The block height up until this action can be executed + /// @param expectedApproveExpression The definition of expected approval expression the action is created with + /// @param expectedRejectExpression The definition of expected reject expression the action is created with + /// @return success If execution was successful + function removeSpaceOwner( + uint64 spaceId, + address owner, + uint64 nonce, + uint64 actionTimeoutHeight, + string calldata expectedApproveExpression, + string calldata expectedRejectExpression + ) external returns (bool success); + + /// @dev Defines a method to create a new key request. + /// @param spaceId The space id + /// @param keychainId The keychain id + /// @param keyType The key type + /// @param approveTemplateId The approve template id + /// @param rejectTemplateId The reject template id + /// @param maxKeychainFees The max keychain fees + /// @param nonce The nonce + /// @param actionTimeoutHeight The block height up until this action can be executed + /// @param expectedApproveExpression The definition of expected approval expression the action is created with + /// @param expectedRejectExpression The definition of expected reject expression the action is created with + /// @return success If execution was successful + function newKeyRequest( + uint64 spaceId, + uint64 keychainId, + KeyType keyType, + uint64 approveTemplateId, + uint64 rejectTemplateId, + Types.Coin[] calldata maxKeychainFees, + uint64 nonce, + uint64 actionTimeoutHeight, + string calldata expectedApproveExpression, + string calldata expectedRejectExpression + ) external returns (bool success); + + /// @dev Defines a method to create a new signature request. + /// @param keyId The key id + /// @param input The input + /// @param analyzers The analyzers + /// @param encryptionKey The encryption key + /// @param maxKeychainFees The max keychain fees + /// @param nonce The nonce + /// @param actionTimeoutHeight The block height up until this action can be executed + /// @param expectedApproveExpression The definition of expected approval expression the action is created with + /// @param expectedRejectExpression The definition of expected reject expression the action is created with + /// @param broadcastType The broadcast type + /// @return success If execution was successful + function newSignRequest( + uint64 keyId, + bytes calldata input, + bytes[] calldata analyzers, + bytes calldata encryptionKey, + Types.Coin[] calldata maxKeychainFees, + uint64 nonce, + uint64 actionTimeoutHeight, + string calldata expectedApproveExpression, + string calldata expectedRejectExpression, + BroadcastType broadcastType + ) external returns (bool success); + + /// @dev Defines a method to update a key. + /// @param keyId The key id + /// @param approveTemplateId The approve template id + /// @param rejectTemplateId The reject template id + /// @param actionTimeoutHeight The block height up until this action can be executed + /// @param expectedApproveExpression The definition of expected approval expression the action is created with + /// @param expectedRejectExpression The definition of expected reject expression the action is created with + /// @return success If execution was successful + function updateKey( + uint64 keyId, + uint64 approveTemplateId, + uint64 rejectTemplateId, + uint64 actionTimeoutHeight, + string calldata expectedApproveExpression, + string calldata expectedRejectExpression + ) external returns (bool success); + + /// @dev Defines a method to update a space. + /// @param spaceId The space id + /// @param nonce The nonce + /// @param approveAdminTemplateId The template id of approve admin action + /// @param rejectAdminTemplateId The template id of reject admin action + /// @param approveSignTemplateId The template id of approve sign action + /// @param rejectSignTemplateId The template id of reject sign action + /// @param actionTimeoutHeight The block height up until this action can be executed + /// @param expectedApproveExpression The definition of expected approval expression the action is created with + /// @param expectedRejectExpression The definition of expected reject expression the action is created with + /// @return success If execution was successful + function updateSpace( + uint64 spaceId, + uint64 nonce, + uint64 approveAdminTemplateId, + uint64 rejectAdminTemplateId, + uint64 approveSignTemplateId, + uint64 rejectSignTemplateId, + uint64 actionTimeoutHeight, + string calldata expectedApproveExpression, + string calldata expectedRejectExpression + ) external returns (bool success); + + /// @dev Defines a method to query keys. + /// @param pageRequest The pagination details + /// @return keys An array of `KeyResponse` structs containing the retrieved keys + /// @return pageResponse pagination details + function allKeys( + Types.PageRequest calldata pageRequest, + int32[] calldata deriveAddresses + ) external view returns(KeyResponse[] memory keys, Types.PageResponse memory pageResponse); + + /// @dev Defines a method to query key by id. + /// @param id The id of the key + /// @param deriveAddresses The array of address types to derive + /// @return key `KeyResponse` struct containing the retrieved key + function keyById( + uint64 id, + int32[] calldata deriveAddresses + ) external view returns(KeyResponse memory key); + + /// @dev Defines a method to query keys by space id. + /// @param pageRequest The pagination details + /// @param spaceId The id of the space + /// @param deriveAddresses The array of address types to derive + /// @return keys An array of `KeyResponse` structs containing the retrieved keys + /// @return pageResponse pagination details + function keysBySpaceId( + Types.PageRequest calldata pageRequest, + uint64 spaceId, + int32[] calldata deriveAddresses + ) external view returns(KeyResponse[] memory keys, Types.PageResponse memory pageResponse); + + /// @dev Defines a method to query keyRequest by id. + /// @param id The id of the keyRequest + /// @return keyRequest The key request + function keyRequestById( + uint64 id + ) external view returns(KeyRequest memory keyRequest); + + /// @dev Defines a method to query keyRequests. + /// @param pageRequest The pagination details + /// @param keychainId The id of the keychain + /// @param status The key requests status + /// @param spaceId The id of the space + /// @return keyRequests An array of `KeyRequest` structs containing the retrieved key requests + /// @return pageResponse pagination details + function keyRequests( + Types.PageRequest calldata pageRequest, + uint64 keychainId, + KeyRequestStatus status, + uint64 spaceId + ) external view returns(KeyRequest[] memory keyRequests, Types.PageResponse memory pageResponse); + + /// @dev Defines a method to query keychain by id. + /// @param id The id of the keychain + /// @return keychain The keychain + function keychainById( + uint64 id + ) external view returns(Keychain memory keychain); + + /// @dev Defines a method to query keychains. + /// @param pageRequest The pagination details + /// @return keychains An array of `Keychain` structs containing the retrieved key requests + /// @return pageResponse pagination details + function keychains( + Types.PageRequest calldata pageRequest + ) external view returns(Keychain[] memory keychains, Types.PageResponse memory pageResponse); + + /// @dev Defines a method to query sign request by id. + /// @param id The id of the sign request + /// @return signRequest The sign request + function signRequestById( + uint64 id + ) external view returns(SignRequest memory signRequest); + + /// @dev Defines a method to query sign requests. + /// @param pageRequest The pagination details + /// @param keychainId The id of the keychain + /// @param status The sign requests status + /// @param optionalBroadcastType The optional broadcast type to query + /// @return signRequests An array of `SignRequest` structs containing the retrieved sign requests + /// @return pageResponse pagination details + function signRequests( + Types.PageRequest calldata pageRequest, + uint64 keychainId, + SignRequestStatus status, + OptionalBroadcastType optionalBroadcastType + ) external view returns(SignRequest[] memory signRequests, Types.PageResponse memory pageResponse); + + /// @dev Defines a method to query space by id. + /// @param id The id of the space + /// @return space The space + function spaceById( + uint64 id + ) external view returns(Space memory space); + + /// @dev Defines a method to query spaces. + /// @param pageRequest The pagination details + /// @return spaces An array of `Space` structs containing the retrieved sign requests + /// @return pageResponse pagination details + function spaces( + Types.PageRequest calldata pageRequest + ) external view returns(Space[] memory spaces, Types.PageResponse memory pageResponse); + + /// @dev Defines a method to query spaces by owner. + /// @param pageRequest The pagination details + /// @param owner The owner address + /// @return spaces An array of `Space` structs containing the retrieved sign requests + /// @return pageResponse pagination details + function spacesByOwner( + Types.PageRequest calldata pageRequest, + address owner + ) external view returns(Space[] memory spaces, Types.PageResponse memory pageResponse); + + /// @dev AddKeychainAdmin defines an Event emitted when add a new admin to a keychain. + /// @param newAdmin The address of the admin + /// @param id The keychain id + /// @param adminsCount The new count of admins + event AddKeychainAdmin(address newAdmin, uint64 indexed id, uint64 adminsCount); + + /// @dev AddKeychainWriter defines an Event emitted when add a new writer to a keychain. + /// @param newWriter The address of the writer + /// @param id The keychain id + /// @param writersCount The new count of writers + event AddKeychainWriter(address newWriter, uint64 indexed id, uint64 writersCount); + + /// @dev NewKey defines an Event emitted when a key request fulfilled. + /// @param id The key id + /// @param keyType The key type + /// @param spaceId The space id + /// @param keychainId The keychain id + /// @param approveTemplateId The approve template id + /// @param rejectTemplateId The reject template id + event NewKey(uint64 indexed id, KeyType keyType, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId); + + /// @dev RejectKeyRequest defines an Event emitted when a key request rejected. + /// @param id The request id + event RejectKeyRequest(uint64 indexed id); + + /// @dev FulfilSignRequest defines an Event emitted when a sign request fulfilled. + /// @param id The request id + event FulfilSignRequest(uint64 indexed id); + + /// @dev RejectSignRequest defines an Event emitted when a sign request rejected. + /// @param id The request id + event RejectSignRequest(uint64 indexed id); + + /// @dev NewKeychain defines an Event emitted when a new keychain is created. + /// @param id The keychain id + /// @param creator The creator address + event NewKeychain(uint64 indexed id, address creator); + + /// @dev NewSpace defines an Event emitted when a new space is created. + /// @param id The space id + /// @param creator The creator address + /// @param ownersCount The count of space owners + /// @param approveAdminTemplateId The template id of approve admin action + /// @param rejectAdminTemplateId The template id of reject admin action + /// @param approveSignTemplateId The template id of approve sign action + /// @param rejectSignTemplateId The template id of reject sign action + event NewSpace(uint64 indexed id, address creator, uint64 ownersCount, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId); + + /// @dev RemoveKeychainAdmin defines an Event emitted when an admin removed from keychain. + /// @param keychainId The keychain id + /// @param admin The admin address + /// @param adminsCount The count of keychain admins + event RemoveKeychainAdmin(uint64 indexed keychainId, address admin, uint64 adminsCount); + + /// @dev UpdateKeychain defines an Event emitted when a keychain is updated. + /// @param id The keychain id + /// @param keychainFees The keychain fees + event UpdateKeychain(uint64 indexed id, KeychainFees keychainFees); + + /// @dev AddSpaceOwner defines an Event emitted when a new space owner is added. + /// @param spaceId The space id + /// @param newOwner The new owner address + event AddSpaceOwner(uint64 indexed spaceId, address newOwner); + + /// @dev RemoveSpaceOwner defines an Event emitted when a space owner is removed. + /// @param spaceId The space id + /// @param removedOwner The removed owner address + event RemoveSpaceOwner(uint64 indexed spaceId, address removedOwner); + + /// @dev NewKeyRequest defines an Event emitted when a new key request is created. + /// @param id The id of the created key request + /// @param spaceId The space id + /// @param keychainId The keychain id + /// @param approveTemplateId The approve template id + /// @param rejectTemplateId The reject template id + /// @param keyType The key type + /// @param creator The creator address + event NewKeyRequest(uint64 indexed id, uint64 spaceId, uint64 keychainId, uint64 approveTemplateId, uint64 rejectTemplateId, KeyType keyType, address creator); + + /// @dev NewSignRequest defines an Event emitted when a new signature request is created. + /// @param id The id of the signature request + /// @param keyId The id of the Key to be used for signing + /// @param creator The creator address + /// @param broadcastType The broadcast type + event NewSignRequest(uint64 indexed id, uint64 keyId, address creator, BroadcastType broadcastType); + + /// @dev UpdateKey defines an Event emitted when a key is updated. + /// @param id The id of the key + /// @param approveTemplateId The approve template id + /// @param rejectTemplateId The reject template id + event UpdateKey(uint64 indexed id, uint64 approveTemplateId, uint64 rejectTemplateId); + + /// @dev UpdateSpace defines an Event emitted when a space is updated. + /// @param spaceId The id of the space being updated + /// @param approveAdminTemplateId The id of the template to be applied to every approve admin operation + /// @param rejectAdminTemplateId The id of the template to be applied to every reject admin operation + /// @param approveSignTemplateId The id of the template to be applied to every approve sign operation + /// @param rejectSignTemplateId The id of the template to be applied to every reject sign operation + event UpdateSpace(uint64 indexed spaceId, uint64 approveAdminTemplateId, uint64 rejectAdminTemplateId, uint64 approveSignTemplateId, uint64 rejectSignTemplateId); +} diff --git a/src/orders/precompiles/warden/Types.abi b/src/orders/precompiles/warden/Types.abi new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/src/orders/precompiles/warden/Types.abi @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/orders/precompiles/warden/abi.json b/src/orders/precompiles/warden/abi.json new file mode 100644 index 0000000..2e854b2 --- /dev/null +++ b/src/orders/precompiles/warden/abi.json @@ -0,0 +1,2481 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "adminsCount", + "type": "uint64" + } + ], + "name": "AddKeychainAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newWriter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "writersCount", + "type": "uint64" + } + ], + "name": "AddKeychainWriter", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "AddSpaceOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "FulfilSignRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + } + ], + "name": "NewKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + } + ], + "name": "NewKeyRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + } + ], + "name": "NewKeychain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "keyId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum BroadcastType", + "name": "broadcastType", + "type": "uint8" + } + ], + "name": "NewSignRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "ownersCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + } + ], + "name": "NewSpace", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "RejectKeyRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "RejectSignRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "adminsCount", + "type": "uint64" + } + ], + "name": "RemoveKeychainAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "removedOwner", + "type": "address" + } + ], + "name": "RemoveSpaceOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + } + ], + "name": "UpdateKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "keyReq", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "sigReq", + "type": "tuple[]" + } + ], + "indexed": false, + "internalType": "struct KeychainFees", + "name": "keychainFees", + "type": "tuple" + } + ], + "name": "UpdateKeychain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + } + ], + "name": "UpdateSpace", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "addKeychainAdmin", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newWriter", + "type": "address" + } + ], + "name": "addKeychainWriter", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actionTimeoutHeight", + "type": "uint64" + }, + { + "internalType": "string", + "name": "expectedApproveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "expectedRejectExpression", + "type": "string" + } + ], + "name": "addSpaceOwner", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + }, + { + "internalType": "int32[]", + "name": "deriveAddresses", + "type": "int32[]" + } + ], + "name": "allKeys", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + } + ], + "internalType": "struct Key", + "name": "key", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "addressValue", + "type": "string" + }, + { + "internalType": "enum AddressType", + "name": "addressType", + "type": "uint8" + } + ], + "internalType": "struct AddressesResponse[]", + "name": "addresses", + "type": "tuple[]" + } + ], + "internalType": "struct KeyResponse[]", + "name": "keys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "requestId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "pubKey", + "type": "bytes" + } + ], + "name": "fulfilKeyRequest", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "requestId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "signedData", + "type": "bytes" + } + ], + "name": "fulfilSignRequest", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "int32[]", + "name": "deriveAddresses", + "type": "int32[]" + } + ], + "name": "keyById", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + } + ], + "internalType": "struct Key", + "name": "key", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "addressValue", + "type": "string" + }, + { + "internalType": "enum AddressType", + "name": "addressType", + "type": "uint8" + } + ], + "internalType": "struct AddressesResponse[]", + "name": "addresses", + "type": "tuple[]" + } + ], + "internalType": "struct KeyResponse", + "name": "key", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "keyRequestById", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "internalType": "enum KeyRequestStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "string", + "name": "rejectReason", + "type": "string" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "deductedKeychainFees", + "type": "tuple[]" + } + ], + "internalType": "struct KeyRequest", + "name": "keyRequest", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyRequestStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + } + ], + "name": "keyRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "internalType": "enum KeyRequestStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "string", + "name": "rejectReason", + "type": "string" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "deductedKeychainFees", + "type": "tuple[]" + } + ], + "internalType": "struct KeyRequest[]", + "name": "keyRequests", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "keychainById", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address[]", + "name": "admins", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "writers", + "type": "address[]" + }, + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "keyReq", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "sigReq", + "type": "tuple[]" + } + ], + "internalType": "struct KeychainFees", + "name": "fees", + "type": "tuple" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "keybaseId", + "type": "string" + } + ], + "internalType": "struct Keychain", + "name": "keychain", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "keychains", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address[]", + "name": "admins", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "writers", + "type": "address[]" + }, + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "keyReq", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "sigReq", + "type": "tuple[]" + } + ], + "internalType": "struct KeychainFees", + "name": "fees", + "type": "tuple" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "keybaseId", + "type": "string" + } + ], + "internalType": "struct Keychain[]", + "name": "keychains", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "int32[]", + "name": "deriveAddresses", + "type": "int32[]" + } + ], + "name": "keysBySpaceId", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + } + ], + "internalType": "struct Key", + "name": "key", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "addressValue", + "type": "string" + }, + { + "internalType": "enum AddressType", + "name": "addressType", + "type": "uint8" + } + ], + "internalType": "struct AddressesResponse[]", + "name": "addresses", + "type": "tuple[]" + } + ], + "internalType": "struct KeyResponse[]", + "name": "keys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum KeyType", + "name": "keyType", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "maxKeychainFees", + "type": "tuple[]" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actionTimeoutHeight", + "type": "uint64" + }, + { + "internalType": "string", + "name": "expectedApproveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "expectedRejectExpression", + "type": "string" + } + ], + "name": "newKeyRequest", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "keyReq", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "sigReq", + "type": "tuple[]" + } + ], + "internalType": "struct KeychainFees", + "name": "keychainFees", + "type": "tuple" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "keybaseId", + "type": "string" + } + ], + "name": "newKeychain", + "outputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "keyId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "input", + "type": "bytes" + }, + { + "internalType": "bytes[]", + "name": "analyzers", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "encryptionKey", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "maxKeychainFees", + "type": "tuple[]" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actionTimeoutHeight", + "type": "uint64" + }, + { + "internalType": "string", + "name": "expectedApproveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "expectedRejectExpression", + "type": "string" + }, + { + "internalType": "enum BroadcastType", + "name": "broadcastType", + "type": "uint8" + } + ], + "name": "newSignRequest", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + }, + { + "internalType": "address[]", + "name": "additionalOwners", + "type": "address[]" + } + ], + "name": "newSpace", + "outputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "requestId", + "type": "uint64" + }, + { + "internalType": "string", + "name": "rejectReason", + "type": "string" + } + ], + "name": "rejectKeyRequest", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "requestId", + "type": "uint64" + }, + { + "internalType": "string", + "name": "rejectReason", + "type": "string" + } + ], + "name": "rejectSignRequest", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "removeKeychainAdmin", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actionTimeoutHeight", + "type": "uint64" + }, + { + "internalType": "string", + "name": "expectedApproveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "expectedRejectExpression", + "type": "string" + } + ], + "name": "removeSpaceOwner", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "signRequestById", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "keyId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "dataForSigning", + "type": "bytes" + }, + { + "internalType": "enum SignRequestStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "result", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "encryptionKey", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "deductedKeychainFees", + "type": "tuple[]" + }, + { + "internalType": "enum BroadcastType", + "name": "broadcastType", + "type": "uint8" + } + ], + "internalType": "struct SignRequest", + "name": "signRequest", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "enum SignRequestStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "enum OptionalBroadcastType", + "name": "optionalBroadcastType", + "type": "uint8" + } + ], + "name": "signRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "keyId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "dataForSigning", + "type": "bytes" + }, + { + "internalType": "enum SignRequestStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "result", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "encryptionKey", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "deductedKeychainFees", + "type": "tuple[]" + }, + { + "internalType": "enum BroadcastType", + "name": "broadcastType", + "type": "uint8" + } + ], + "internalType": "struct SignRequest[]", + "name": "signRequests", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + } + ], + "name": "spaceById", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + } + ], + "internalType": "struct Space", + "name": "space", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + } + ], + "name": "spaces", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + } + ], + "internalType": "struct Space[]", + "name": "spaces", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offset", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "countTotal", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reverse", + "type": "bool" + } + ], + "internalType": "struct Types.PageRequest", + "name": "pageRequest", + "type": "tuple" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "spacesByOwner", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "id", + "type": "uint64" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + } + ], + "internalType": "struct Space[]", + "name": "spaces", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "nextKey", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "total", + "type": "uint64" + } + ], + "internalType": "struct Types.PageResponse", + "name": "pageResponse", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "keyId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actionTimeoutHeight", + "type": "uint64" + }, + { + "internalType": "string", + "name": "expectedApproveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "expectedRejectExpression", + "type": "string" + } + ], + "name": "updateKey", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "keychainId", + "type": "uint64" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "keyReq", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "denom", + "type": "string" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Types.Coin[]", + "name": "sigReq", + "type": "tuple[]" + } + ], + "internalType": "struct KeychainFees", + "name": "keychainFees", + "type": "tuple" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "keybaseId", + "type": "string" + } + ], + "name": "updateKeychain", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "spaceId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectAdminTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "approveSignTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rejectSignTemplateId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "actionTimeoutHeight", + "type": "uint64" + }, + { + "internalType": "string", + "name": "expectedApproveExpression", + "type": "string" + }, + { + "internalType": "string", + "name": "expectedRejectExpression", + "type": "string" + } + ], + "name": "updateSpace", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/src/orders/precompiles/warden/events.go b/src/orders/precompiles/warden/events.go new file mode 100644 index 0000000..e26ba00 --- /dev/null +++ b/src/orders/precompiles/warden/events.go @@ -0,0 +1,675 @@ +package warden + +import ( + "bytes" + "fmt" + "reflect" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + evmoscmn "github.com/evmos/evmos/v20/precompiles/common" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + wardentypes "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" +) + +const ( + // EventTypeAddKeychainAdmin defines the event type for the x/warden AddKeychainAdmin transaction. + EventTypeAddKeychainAdmin = "AddKeychainAdmin" + // EventTypeAddKeychainWriter defines the event type for the x/warden AddKeychainWriter transaction. + EventTypeAddKeychainWriter = "AddKeychainWriter" + // EventTypeNewKey defines the event type for the fulfil branch of x/warden FulfilKeyRequest transaction. + EventTypeNewKey = "NewKey" + // EventRejectKeyRequest defines the event type for the reject branch of x/warden FulfilKeyRequest transaction. + EventRejectKeyRequest = "RejectKeyRequest" + // EventFulfilSignRequest defines the event type for the fulfil branch of x/warden FulfilSignRequest transaction. + EventFulfilSignRequest = "FulfilSignRequest" + // EventRejectSignRequest defines the event type for the reject branch of x/warden FulfilSignRequest transaction. + EventRejectSignRequest = "RejectSignRequest" + // EventNewKeychain defines the event type for the x/warden NewKeychain transaction. + EventNewKeychain = "NewKeychain" + // EventNewSpace defines the event type for the x/warden NewSpace transaction. + EventNewSpace = "NewSpace" + // EventRemoveKeychainAdmin defines the event type for the x/warden RemoveKeychainAdmin transaction. + EventRemoveKeychainAdmin = "RemoveKeychainAdmin" + // EventUpdateKeychain defines the event type for the x/warden UpdateKeychain transaction. + EventUpdateKeychain = "UpdateKeychain" + // EventAddSpaceOwner defines the event type for the x/warden AddSpaceOwner transaction. + EventAddSpaceOwner = "AddSpaceOwner" + // EventRemoveSpaceOwner defines the event type for the x/warden RemoveSpaceOwner transaction. + EventRemoveSpaceOwner = "RemoveSpaceOwner" + // EventNewKeyRequest defines the event type for the x/warden NewKeyRequest transaction. + EventNewKeyRequest = "NewKeyRequest" + // EventNewSignRequest defines the event type for the x/warden NewSignRequest transaction. + EventNewSignRequest = "NewSignRequest" + // EventUpdateKey defines the event type for the x/warden UpdateKey transaction. + EventUpdateKey = "UpdateKey" + // EventUpdateSpace defines the event type for the x/warden UpdateSpace transaction. + EventUpdateSpace = "UpdateSpace" +) + +// GetAddKeychainAdminEvent maps EventAddKeychainAdmin to eth AddKeychainAdmin event and write to eth log +func (p Precompile) GetAddKeychainAdminEvent(ctx sdk.Context, adminAddress *common.Address, eventAddKeychainAdmin sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventTypeAddKeychainAdmin] + + if adminAddress == nil { + return nil, fmt.Errorf("adminAddress is nil") + } + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventAddKeychainAdmin{} + if err := precommon.ParseSdkEvent(eventAddKeychainAdmin, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + newAdminAddress, err := precommon.AddressFromBech32Str(typedEvent.GetNewAdmin()) + if err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), newAdminAddress.Bytes()...)) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetAdminsCount()))) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetAddKeychainWriterEvent maps EventAddKeychainWriter to eth AddKeychainWriter event and write to eth log +func (p Precompile) GetAddKeychainWriterEvent(ctx sdk.Context, writerAddress *common.Address, eventAddKeychainWriter sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventTypeAddKeychainWriter] + + if writerAddress == nil { + return nil, fmt.Errorf("writerAddress is nil") + } + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventAddKeychainWriter{} + if err := precommon.ParseSdkEvent(eventAddKeychainWriter, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + newWriterAddress, err := precommon.AddressFromBech32Str(typedEvent.GetNewWriter()) + if err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), newWriterAddress.Bytes()...)) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetWritersCount()))) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetNewKeyEvent maps EventNewKey to eth NewKey event and write to eth log +func (p Precompile) GetNewKeyEvent(ctx sdk.Context, _ *common.Address, eventNewKey sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventTypeNewKey] + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + typedEvent := wardentypes.EventNewKey{} + if err := precommon.ParseSdkEvent(eventNewKey, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + packed, err := event.Inputs.NonIndexed().Pack( + uint8(typedEvent.GetKeyType()), + typedEvent.GetSpaceId(), + typedEvent.GetKeychainId(), + typedEvent.GetApproveTemplateId(), + typedEvent.GetRejectTemplateId(), + ) + + if err != nil { + return nil, err + } + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: packed, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetRejectKeyRequestEvent maps EventRejectKeyRequest to eth RejectKeyRequest event and write to eth log +func (p Precompile) GetRejectKeyRequestEvent(ctx sdk.Context, _ *common.Address, eventRejectKeyRequest sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventRejectKeyRequest] + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + typedEvent := wardentypes.EventRejectKeyRequest{} + if err := precommon.ParseSdkEvent(eventRejectKeyRequest, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + var err error + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: []byte{}, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetFulfilSignRequestEvent maps EventFulfilSignRequest to eth FulfilSignRequest event and write to eth log +func (p Precompile) GetFulfilSignRequestEvent(ctx sdk.Context, _ *common.Address, eventFulfilSignRequest sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventFulfilSignRequest] + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + typedEvent := wardentypes.EventFulfilSignRequest{} + if err := precommon.ParseSdkEvent(eventFulfilSignRequest, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + var err error + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: []byte{}, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetRejectSignRequestEvent maps EventRejectSignRequest to eth RejectSignRequest event and write to eth log +func (p Precompile) GetRejectSignRequestEvent(ctx sdk.Context, _ *common.Address, eventRejectSignRequest sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventRejectSignRequest] + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + typedEvent := wardentypes.EventRejectSignRequest{} + if err := precommon.ParseSdkEvent(eventRejectSignRequest, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + var err error + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: []byte{}, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetNewKeychainEvent maps EventNewKeychain to eth NewKeychain event and write to eth log +func (p Precompile) GetNewKeychainEvent(ctx sdk.Context, creator *common.Address, eventNewKeychain sdk.Event) (*ethtypes.Log, error) { + var err error + // Prepare the event topics + event := p.ABI.Events[EventNewKeychain] + + if creator == nil { + return nil, fmt.Errorf("creator is nil") + } + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventNewKeychain{} + if err = precommon.ParseSdkEvent(eventNewKeychain, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), creator.Bytes()...)) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetNewSpaceEvent maps EventNewSpace to eth NewSpace event and writes to eth log +func (p Precompile) GetNewSpaceEvent(ctx sdk.Context, creator *common.Address, eventNewSpace sdk.Event) (*ethtypes.Log, error) { + var err error + // Prepare the event topics + event := p.ABI.Events[EventNewSpace] + + if creator == nil { + return nil, fmt.Errorf("creator is nil") + } + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventCreateSpace{} + if err = precommon.ParseSdkEvent(eventNewSpace, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), creator.Bytes()...)) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetOwnersCount()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetApproveAdminTemplateId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetRejectAdminTemplateId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetApproveSignTemplateId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetRejectSignTemplateId()))) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetRemoveKeychainAdminEvent maps EventRemoveKeychainAdmin to eth RemoveKeychainAdmin event and write to eth log +func (p Precompile) GetRemoveKeychainAdminEvent(ctx sdk.Context, admin *common.Address, eventRemoveKeychainAdmin sdk.Event) (*ethtypes.Log, error) { + var err error + // Prepare the event topics + event := p.ABI.Events[EventRemoveKeychainAdmin] + + if admin == nil { + return nil, fmt.Errorf("admin is nil") + } + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventRemoveKeychainAdmin{} + if err = precommon.ParseSdkEvent(eventRemoveKeychainAdmin, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + adminAddress, err := precommon.AddressFromBech32Str(typedEvent.GetAdmin()) + if err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), adminAddress.Bytes()...)) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetAdminsCount()))) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetUpdateKeychainEvent maps EventUpdateKeychain to eth UpdateKeychain event and write to eth log +func (p Precompile) GetUpdateKeychainEvent(ctx sdk.Context, _ *common.Address, eventUpdateKeychain sdk.Event) (*ethtypes.Log, error) { + // Prepare the event topics + event := p.ABI.Events[EventUpdateKeychain] + + topics := make([]common.Hash, 2) + // The first topic is always the signature of the event. + topics[0] = event.ID + var b bytes.Buffer + typedEvent := wardentypes.EventUpdateKeychain{} + + // use Marshal/Unmarshal here cause big.Word=uint inside big.Int is not correctly merged in cosmos.gogoproto + var err error + var marshaled []byte + if err := precommon.ParseSdkEvent(eventUpdateKeychain, func(m proto.Message) { + marshaled, err = proto.Marshal(m) + typedEvent.Unmarshal(marshaled) + }); err != nil { + return nil, err + } + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + packedKeychainFees, err := event.Inputs.NonIndexed().Pack( + mapSdkKeychainFees(typedEvent.GetKeychainFees()), + ) + if err != nil { + return nil, err + } + b.Write(packedKeychainFees) + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetAddSpaceOwnerEvent maps EventAddSpaceOwner to eth AddSpaceOwner event and write to eth log +func (p Precompile) GetAddSpaceOwnerEvent(ctx sdk.Context, _ *common.Address, addSpaceOwnerEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventAddSpaceOwner] + + topics := make([]common.Hash, 2) + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventAddSpaceOwner{} + if err := precommon.ParseSdkEvent(addSpaceOwnerEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + newOwner, err := precommon.AddressFromBech32Str(typedEvent.GetNewOwner()) + if err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), newOwner.Bytes()...)) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetSpaceId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetRemoveSpaceOwnerEvent maps EventRemoveSpaceOwner to eth RemoveSpaceOwner event and write to eth log +func (p Precompile) GetRemoveSpaceOwnerEvent(ctx sdk.Context, _ *common.Address, removeSpaceOwnerEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventRemoveSpaceOwner] + + topics := make([]common.Hash, 2) + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventRemoveSpaceOwner{} + if err := precommon.ParseSdkEvent(removeSpaceOwnerEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + removedOwnerAddress, err := precommon.AddressFromBech32Str(typedEvent.GetRemovedOwner()) + if err != nil { + return nil, err + } + + b.Write(append(make([]byte, 12), removedOwnerAddress.Bytes()...)) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetSpaceId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetNewKeyRequestEvent maps EventNewKeyRequest to eth NewKeyRequest event and write to eth log +func (p Precompile) GetNewKeyRequestEvent(ctx sdk.Context, _ *common.Address, newKeyRequestEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventNewKeyRequest] + + topics := make([]common.Hash, 2) + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventNewKeyRequest{} + if err := precommon.ParseSdkEvent(newKeyRequestEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + creatorAddress, err := precommon.AddressFromBech32Str(typedEvent.GetCreator()) + if err != nil { + return nil, err + } + + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetSpaceId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetKeychainId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetApproveTemplateId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetRejectTemplateId()))) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetKeyType()))) + b.Write(append(make([]byte, 12), creatorAddress.Bytes()...)) + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetNewSignRequestEvent maps EventNewSignRequest to eth NewSignRequest event and write to eth log +func (p Precompile) GetNewSignRequestEvent(ctx sdk.Context, _ *common.Address, newSignRequestEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventNewSignRequest] + + topics := make([]common.Hash, 2) + topics[0] = event.ID + + var b bytes.Buffer + + typedEvent := wardentypes.EventNewSignRequest{} + if err := precommon.ParseSdkEvent(newSignRequestEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + creatorAddress, err := precommon.AddressFromBech32Str(typedEvent.GetCreator()) + if err != nil { + return nil, err + } + + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetKeyId()))) + b.Write(append(make([]byte, 12), creatorAddress.Bytes()...)) + b.Write(evmoscmn.PackNum(reflect.ValueOf(typedEvent.GetBroadcastType()))) + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: b.Bytes(), + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetUpdateKeyEvent maps EventUpdateKey to eth UpdateKey event and write to eth log +func (p Precompile) GetUpdateKeyEvent(ctx sdk.Context, _ *common.Address, updateKeyEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventUpdateKey] + + topics := make([]common.Hash, 2) + topics[0] = event.ID + + typedEvent := wardentypes.EventUpdateKey{} + if err := precommon.ParseSdkEvent(updateKeyEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + packed, err := event.Inputs.NonIndexed().Pack( + typedEvent.GetApproveTemplateId(), + typedEvent.GetRejectTemplateId(), + ) + if err != nil { + return nil, err + } + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: packed, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} + +// GetUpdateSpaceEvent maps EventUpdateSpace to eth UpdateSpace event and write to eth log +func (p Precompile) GetUpdateSpaceEvent(ctx sdk.Context, _ *common.Address, updateSpaceEvent sdk.Event) (*ethtypes.Log, error) { + event := p.ABI.Events[EventUpdateSpace] + + topics := make([]common.Hash, 2) + topics[0] = event.ID + + typedEvent := wardentypes.EventUpdateSpace{} + if err := precommon.ParseSdkEvent(updateSpaceEvent, typedEvent.XXX_Merge); err != nil { + return nil, err + } + + packed, err := event.Inputs.NonIndexed().Pack( + typedEvent.GetApproveAdminTemplateId(), + typedEvent.GetRejectAdminTemplateId(), + typedEvent.GetApproveSignTemplateId(), + typedEvent.GetRejectSignTemplateId(), + ) + if err != nil { + return nil, err + } + + topics[1], err = evmoscmn.MakeTopic(typedEvent.GetSpaceId()) + + if err != nil { + return nil, err + } + + log := ethtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: packed, + BlockNumber: uint64(ctx.BlockHeight()), + } + + return &log, nil +} diff --git a/src/orders/precompiles/warden/query.go b/src/orders/precompiles/warden/query.go new file mode 100644 index 0000000..dbb0ac3 --- /dev/null +++ b/src/orders/precompiles/warden/query.go @@ -0,0 +1,373 @@ +package warden + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +const ( + AllKeysMethod = "allKeys" + KeyByIdMethod = "keyById" + KeysBySpaceIdMethod = "keysBySpaceId" + KeyRequestMethod = "keyRequestById" + KeyRequestsMethod = "keyRequests" + KeychainMethod = "keychainById" + KeychainsMethod = "keychains" + SignRequestByIdMethod = "signRequestById" + SignRequestsMethod = "signRequests" + SpaceByIdMethod = "spaceById" + SpacesMethod = "spaces" + SpacesByOwnerMethod = "spacesByOwner" +) + +// AllKeysMethod constructs QueryAllKeysRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) AllKeysMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newAllKeysRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.AllKeys(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(keysOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// KeyByIdMethod constructs QueryKeyByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) KeyByIdMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newKeyByIdRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.KeyById(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(KeyResponse).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// KeysBySpaceIdMethod constructs QueryKeysBySpaceIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) KeysBySpaceIdMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newKeysBySpaceIdRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.KeysBySpaceId(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(keysOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// KeyRequestMethod constructs QueryKeyRequestByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) KeyRequestMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newKeyRequestByIdRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.KeyRequestById(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(KeyRequest).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// KeyRequestsMethod constructs QueryKeyRequestsRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) KeyRequestsMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newKeyRequestsRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.KeyRequests(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(keyRequestsOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// KeychainMethod constructs QueryKeychainByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) KeychainMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newKeychainRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.KeychainById(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(Keychain).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// KeychainsMethod constructs QueryKeychainsRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) KeychainsMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newKeychainsRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.Keychains(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(keychainsOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// SignRequestByIdMethod constructs QuerySignRequestByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) SignRequestByIdMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newSignRequestByIdRequest(args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.SignRequestById(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(SignRequest).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// SignRequestsMethod constructs QuerySignRequestsRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) SignRequestsMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newSignRequestsRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.SignRequests(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(signRequestsOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// SpaceByIdMethod constructs QuerySpaceByIdRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) SpaceByIdMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newSpaceByIdRequest(args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.SpaceById(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(Space).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// SpacesMethod constructs QuerySpacesRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) SpacesMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newSpacesRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.Spaces(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(spacesOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} + +// SpacesByOwnerMethod constructs QuerySpacesByOwnerRequest from args, passes it to query server and packs response into corresponding abi output. +func (p Precompile) SpacesByOwnerMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + req, err := newSpacesByOwnerRequest(method, args) + if err != nil { + return nil, err + } + + response, err := p.queryServer.SpacesByOwner(ctx, req) + if err != nil { + return nil, err + } + if response == nil { + return nil, fmt.Errorf("received nil response from query server") + } + + out, err := new(spacesOutput).FromResponse(response) + if err != nil { + return nil, err + } + + return out.Pack(method.Outputs) +} diff --git a/src/orders/precompiles/warden/query_types.go b/src/orders/precompiles/warden/query_types.go new file mode 100644 index 0000000..f690c24 --- /dev/null +++ b/src/orders/precompiles/warden/query_types.go @@ -0,0 +1,648 @@ +package warden + +import ( + "errors" + "fmt" + + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + wardencommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + types "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" +) + +func newAllKeysRequest(method *abi.Method, args []interface{}) (*types.QueryAllKeysRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + var input allKeysInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to allKeysInput struct: %w", err) + } + + deriveAddresses := []types.AddressType{} + for _, da := range input.DeriveAddresses { + deriveAddresses = append(deriveAddresses, types.AddressType(da)) + } + + pagination := mapEthPageRequest(input.PageRequest) + return &types.QueryAllKeysRequest{ + Pagination: &pagination, + DeriveAddresses: deriveAddresses, + }, nil +} + +type allKeysInput struct { + PageRequest TypesPageRequest + DeriveAddresses []int32 +} + +func (o *KeyResponse) FromResponse(res *types.QueryKeyResponse) (*KeyResponse, error) { + if res == nil { + return nil, errors.New("received nil QueryKeyResponse") + } + + key := Key{ + Id: res.Key.Id, + SpaceId: res.Key.SpaceId, + KeychainId: res.Key.KeychainId, + KeyType: uint8(res.Key.Type), + PublicKey: res.Key.PublicKey, + ApproveTemplateId: res.Key.ApproveTemplateId, + RejectTemplateId: res.Key.RejectTemplateId, + } + + addresses := make([]AddressesResponse, len(res.Addresses)) + for j, a := range res.Addresses { + addresses[j] = AddressesResponse{ + AddressValue: a.GetAddress(), + AddressType: uint8(a.Type), + } + } + + return &KeyResponse{ + Key: key, + Addresses: addresses, + }, nil +} + +func (o *KeyResponse) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o) +} + +type keysOutput struct { + KeysResponse []KeyResponse + PageResponse TypesPageResponse +} + +func (o *keysOutput) FromResponse(res *types.QueryKeysResponse) (*keysOutput, error) { + if res == nil { + return nil, errors.New("received nil QueryKeyResponse") + } + + o.KeysResponse = make([]KeyResponse, len(res.Keys)) + for i, k := range res.Keys { + keyResponse, err := new(KeyResponse).FromResponse(&k) + if err != nil { + return nil, err + } + + o.KeysResponse[i] = *keyResponse + } + + if res.Pagination != nil { + o.PageResponse.Total = res.Pagination.Total + o.PageResponse.NextKey = res.Pagination.NextKey + } + + return o, nil +} + +func (o *keysOutput) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o.KeysResponse, o.PageResponse) +} + +func newKeyByIdRequest(method *abi.Method, args []interface{}) (*types.QueryKeyByIdRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + var input keyByIdInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to keyByIdInput struct: %w", err) + } + + deriveAddresses := []types.AddressType{} + for _, da := range input.DeriveAddresses { + deriveAddresses = append(deriveAddresses, types.AddressType(da)) + } + + return &types.QueryKeyByIdRequest{ + Id: input.Id, + DeriveAddresses: deriveAddresses, + }, nil +} + +type keyByIdInput struct { + Id uint64 + DeriveAddresses []int32 +} + +func newKeysBySpaceIdRequest(method *abi.Method, args []interface{}) (*types.QueryKeysBySpaceIdRequest, error) { + if len(args) != 3 { + return nil, wardencommon.WrongArgsNumber{Expected: 3, Got: len(args)} + } + + var input keysBySpaceIdInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to keysBySpaceIdInput struct: %w", err) + } + + deriveAddresses := []types.AddressType{} + for _, da := range input.DeriveAddresses { + deriveAddresses = append(deriveAddresses, types.AddressType(da)) + } + + return &types.QueryKeysBySpaceIdRequest{ + Pagination: &input.PageRequest, + SpaceId: input.SpaceId, + DeriveAddresses: deriveAddresses, + }, nil +} + +type keysBySpaceIdInput struct { + PageRequest query.PageRequest + SpaceId uint64 + DeriveAddresses []int32 +} + +func newKeyRequestByIdRequest(method *abi.Method, args []interface{}) (*types.QueryKeyRequestByIdRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input struct{ Id uint64 } + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("failed to unpack arguments into key request id input: %w", err) + } + + return &types.QueryKeyRequestByIdRequest{ + Id: input.Id, + }, nil +} + +func (kr *KeyRequest) FromResponse(res *types.QueryKeyRequestByIdResponse) (*KeyRequest, error) { + if res == nil || res.KeyRequest == nil { + return nil, errors.New("received nil response or key request") + } + return kr.mapKeyRequest(*res.KeyRequest) +} + +func (kr *KeyRequest) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(kr) +} + +func newKeyRequestsRequest(method *abi.Method, args []interface{}) (*types.QueryKeyRequestsRequest, error) { + if len(args) != 4 { + return nil, wardencommon.WrongArgsNumber{Expected: 4, Got: len(args)} + } + + var input keyRequestsInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to keyRequestsInput struct: %w", err) + } + + if _, ok := types.KeyRequestStatus_name[int32(input.Status)]; !ok { + return nil, fmt.Errorf("invalid Status value: %d", input.Status) + } + + return &types.QueryKeyRequestsRequest{ + Pagination: &input.PageRequest, + KeychainId: input.KeychainId, + Status: types.KeyRequestStatus(int32(input.Status)), + SpaceId: input.SpaceId, + }, nil +} + +type keyRequestsInput struct { + PageRequest query.PageRequest + KeychainId uint64 + Status uint8 + SpaceId uint64 +} + +type keyRequestsOutput struct { + Pagination TypesPageResponse + KeyRequests []KeyRequest +} + +func (o *keyRequestsOutput) FromResponse(res *types.QueryKeyRequestsResponse) (*keyRequestsOutput, error) { + if res == nil || res.KeyRequests == nil { + return nil, errors.New("received nil QueryKeyRequestsResponse") + } + + o.KeyRequests = make([]KeyRequest, len(res.KeyRequests)) + for i, k := range res.KeyRequests { + keyRequestResponse, err := new(KeyRequest).mapKeyRequest(*k) + + if err != nil { + return nil, err + } + + o.KeyRequests[i] = *keyRequestResponse + } + + if res.Pagination != nil { + o.Pagination = mapSdkPageResponse(*res.Pagination) + } + + return o, nil +} + +func (o *keyRequestsOutput) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o.KeyRequests, o.Pagination) +} + +func newKeychainRequest(method *abi.Method, args []interface{}) (*types.QueryKeychainByIdRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input struct{ Id uint64 } + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("failed to unpack arguments into keychain id input: %w", err) + } + + return &types.QueryKeychainByIdRequest{ + Id: input.Id, + }, nil +} + +func (k *Keychain) FromResponse(res *types.QueryKeychainByIdResponse) (*Keychain, error) { + if res == nil || res.Keychain == nil { + return nil, errors.New("received nil response or keychain") + } + return k.mapKeychain(*res.Keychain) +} + +func (k *Keychain) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(k) +} + +func newKeychainsRequest(method *abi.Method, args []interface{}) (*types.QueryKeychainsRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input keychainsRequestsInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to keychainsRequestsInput struct: %w", err) + } + + return &types.QueryKeychainsRequest{ + Pagination: &input.PageRequest, + }, nil +} + +type keychainsRequestsInput struct { + PageRequest query.PageRequest +} + +type keychainsOutput struct { + Pagination query.PageResponse + Keychains []Keychain +} + +func (o *keychainsOutput) FromResponse(res *types.QueryKeychainsResponse) (*keychainsOutput, error) { + if res == nil || res.Keychains == nil { + return nil, errors.New("received nil QueryKeychainsResponse") + } + + o.Keychains = make([]Keychain, len(res.Keychains)) + + for i, k := range res.Keychains { + keychain, err := new(Keychain).mapKeychain(k) + if err != nil { + return nil, err + } + o.Keychains[i] = *keychain + } + + if res.Pagination != nil { + o.Pagination = *res.Pagination + } + + return o, nil +} + +func (o *keychainsOutput) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o.Keychains, o.Pagination) +} + +func newSignRequestByIdRequest(args []interface{}) (*types.QuerySignRequestByIdRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + id, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for id, got %T", args[0]) + } + + return &types.QuerySignRequestByIdRequest{ + Id: id, + }, nil +} + +func (o *SignRequest) FromResponse(res *types.QuerySignRequestByIdResponse) (*SignRequest, error) { + if res == nil || res.SignRequest == nil { + return nil, errors.New("received nil QuerySignRequestByIdResponse") + } + return o.mapSignRequest(res.SignRequest) +} + +func (o *SignRequest) mapSignRequest(signRequest *types.SignRequest) (*SignRequest, error) { + ethCreator, err := wardencommon.AddressFromBech32Str(signRequest.Creator) + if err != nil { + return nil, err + } + + o.Creator = ethCreator + + o.Id = signRequest.Id + o.KeyId = signRequest.KeyId + o.DataForSigning = signRequest.DataForSigning + o.Status = uint8(signRequest.Status) + + result := signRequest.Result + if signRequest.Status == types.SignRequestStatus_SIGN_REQUEST_STATUS_FULFILLED { + if signedData, ok := result.(*types.SignRequest_SignedData); ok { + o.Result = signedData.SignedData + } else { + return nil, errors.New("unexpected result type for fulfilled sign request") + } + } else if signRequest.Status == types.SignRequestStatus_SIGN_REQUEST_STATUS_REJECTED { + if rejectReason, ok := result.(*types.SignRequest_RejectReason); ok { + o.Result = []byte(rejectReason.RejectReason) + } else { + return nil, errors.New("unexpected result type for rejected sign request") + } + } + + o.EncryptionKey = signRequest.EncryptionKey + o.DeductedKeychainFees = mapSdkCoins(signRequest.DeductedKeychainFees) + o.BroadcastType = uint8(signRequest.BroadcastType) + + return o, nil +} + +func (o *SignRequest) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o) +} + +func newSignRequestsRequest(method *abi.Method, args []interface{}) (*types.QuerySignRequestsRequest, error) { + if len(args) != 4 { + return nil, wardencommon.WrongArgsNumber{Expected: 4, Got: len(args)} + } + + var input signRequestsInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to signRequestsInput struct: %w", err) + } + + if _, ok := types.SignRequestStatus_name[int32(input.Status)]; !ok { + return nil, fmt.Errorf("invalid Status value: %d", input.Status) + } + + broadcastType := convertToBroadcastType(input.OptionalBroadcastType) + if broadcastType != nil { + if _, ok := types.BroadcastType_name[int32(*broadcastType)]; !ok { + return nil, fmt.Errorf("invalid BroadcastType value: %d", *broadcastType) + } + + querySignRequestBroadcastType := types.QuerySignRequestsRequest_BroadcastType{ + BroadcastType: *convertToBroadcastType(input.OptionalBroadcastType), + } + return &types.QuerySignRequestsRequest{ + Pagination: &input.PageRequest, + KeychainId: input.KeychainId, + Status: types.SignRequestStatus(int32(input.Status)), + OptionalBroadcastType: &querySignRequestBroadcastType, + }, nil + } else { + return &types.QuerySignRequestsRequest{ + Pagination: &input.PageRequest, + KeychainId: input.KeychainId, + Status: types.SignRequestStatus(int32(input.Status)), + OptionalBroadcastType: nil, + }, nil + } +} + +type optionalBroadcastType = uint8 + +func convertToBroadcastType(obt optionalBroadcastType) *types.BroadcastType { + if obt == 0 { + return nil + } + + broadcastType := types.BroadcastType(int32(obt - 1)) + return &broadcastType +} + +type signRequestsInput struct { + PageRequest query.PageRequest + KeychainId uint64 + Status uint8 + OptionalBroadcastType optionalBroadcastType +} + +type signRequestsOutput struct { + SignRequests []SignRequest + Pagination query.PageResponse +} + +func (o *signRequestsOutput) FromResponse(res *types.QuerySignRequestsResponse) (*signRequestsOutput, error) { + if res == nil { + return nil, errors.New("received nil QuerySignRequestsResponse") + } + + o.SignRequests = make([]SignRequest, len(res.SignRequests)) + for i, k := range res.SignRequests { + signRequest, err := new(SignRequest).mapSignRequest(k) + if err != nil { + return nil, err + } + o.SignRequests[i] = *signRequest + } + + if res.Pagination != nil { + o.Pagination = *res.Pagination + } + + return o, nil +} + +func (o *signRequestsOutput) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o.SignRequests, o.Pagination) +} + +func newSpaceByIdRequest(args []interface{}) (*types.QuerySpaceByIdRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + id, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for id, got %T", args[0]) + } + + return &types.QuerySpaceByIdRequest{ + Id: id, + }, nil +} + +func (o *Space) FromResponse(res *types.QuerySpaceByIdResponse) (*Space, error) { + if res == nil || res.Space == nil { + return nil, errors.New("received nil QuerySpaceByIdResponse") + } + return o.mapSpace(res.Space) +} + +func (o *Space) mapSpace(space *types.Space) (*Space, error) { + ethCreator, err := wardencommon.AddressFromBech32Str(space.Creator) + if err != nil { + return nil, err + } + + ethOwners, err := wardencommon.AddressesFromBech32StrArray(space.Owners) + if err != nil { + return nil, err + } + + o.Id = space.Id + o.Creator = ethCreator + o.Owners = ethOwners + o.Nonce = space.Nonce + o.ApproveAdminTemplateId = space.ApproveAdminTemplateId + o.RejectAdminTemplateId = space.RejectAdminTemplateId + o.ApproveSignTemplateId = space.ApproveSignTemplateId + o.RejectSignTemplateId = space.RejectSignTemplateId + + return o, nil +} + +func (o *Space) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o) +} + +func newSpacesRequest(method *abi.Method, args []interface{}) (*types.QuerySpacesRequest, error) { + if len(args) != 1 { + return nil, wardencommon.WrongArgsNumber{Expected: 1, Got: len(args)} + } + + var input spacesInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to spacesInput struct: %w", err) + } + + return &types.QuerySpacesRequest{ + Pagination: &input.PageRequest, + }, nil +} + +type spacesInput struct { + PageRequest query.PageRequest +} + +type spacesOutput struct { + Pagination query.PageResponse + Spaces []Space +} + +func (o *spacesOutput) FromResponse(res *types.QuerySpacesResponse) (*spacesOutput, error) { + if res == nil { + return nil, errors.New("received nil QuerySpacesResponse") + } + o.Spaces = make([]Space, len(res.Spaces)) + for i, k := range res.Spaces { + space, err := new(Space).mapSpace(&k) + if err != nil { + return nil, err + } + + o.Spaces[i] = *space + } + + if res.Pagination != nil { + o.Pagination = *res.Pagination + } + + return o, nil +} + +func (o *spacesOutput) Pack(args abi.Arguments) ([]byte, error) { + return args.Pack(o.Spaces, o.Pagination) +} + +func newSpacesByOwnerRequest(method *abi.Method, args []interface{}) (*types.QuerySpacesByOwnerRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + var input spacesByOwnerInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to spacesInput struct: %w", err) + } + + return &types.QuerySpacesByOwnerRequest{ + Pagination: &input.PageRequest, + Owner: wardencommon.Bech32StrFromAddress(input.Owner), + }, nil +} + +type spacesByOwnerInput struct { + PageRequest query.PageRequest + Owner common.Address +} + +func (kr *KeyRequest) mapKeyRequest(keyRequest types.KeyRequest) (*KeyRequest, error) { + if keyRequest.Creator == "" { + return nil, errors.New("keyRequest.Creator is empty") + } + + ethCreator, err := wardencommon.AddressFromBech32Str(keyRequest.Creator) + + if err != nil { + return nil, err + } + + kr.Id = keyRequest.Id + kr.Creator = ethCreator + kr.SpaceId = keyRequest.SpaceId + kr.KeychainId = keyRequest.KeychainId + kr.KeyType = uint8(keyRequest.KeyType) + kr.Status = uint8(keyRequest.Status) + kr.RejectReason = keyRequest.RejectReason + kr.ApproveTemplateId = keyRequest.ApproveTemplateId + kr.RejectTemplateId = keyRequest.RejectTemplateId + kr.DeductedKeychainFees = mapSdkCoins(keyRequest.DeductedKeychainFees) + + return kr, nil +} + +func (k *Keychain) mapKeychain(keychain types.Keychain) (*Keychain, error) { + var keybaseId string + if keychain.KeybaseId != nil { + keybaseId = keychain.KeybaseId.Value + } + + ethCreator, err := wardencommon.AddressFromBech32Str(keychain.Creator) + if err != nil { + return nil, err + } + + ethAdmins, err := wardencommon.AddressesFromBech32StrArray(keychain.Admins) + if err != nil { + return nil, err + } + + ethWriters, err := wardencommon.AddressesFromBech32StrArray(keychain.Writers) + if err != nil { + return nil, err + } + + k.Id = keychain.Id + k.Creator = ethCreator + k.Name = keychain.Name + k.Admins = ethAdmins + k.Writers = ethWriters + k.Fees = mapSdkKeychainFees(keychain.Fees) + k.Description = keychain.Description + k.Url = keychain.Url + k.KeybaseId = keybaseId + + return k, nil +} diff --git a/src/orders/precompiles/warden/tx.go b/src/orders/precompiles/warden/tx.go new file mode 100644 index 0000000..eed23fb --- /dev/null +++ b/src/orders/precompiles/warden/tx.go @@ -0,0 +1,576 @@ +package warden + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + wardencommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + actkeeper "github.com/warden-protocol/wardenprotocol/warden/x/act/keeper" + "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" + wardenkeeper "github.com/warden-protocol/wardenprotocol/warden/x/warden/keeper" + wardentypes "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" +) + +const ( + AddKeychainAdminMethod = "addKeychainAdmin" + AddKeychainWriterMethod = "addKeychainWriter" + FulfilKeyRequestMethod = "fulfilKeyRequest" + RejectKeyRequestMethod = "rejectKeyRequest" + FulfilSignRequestMethod = "fulfilSignRequest" + RejectSignRequestMethod = "rejectSignRequest" + NewKeychainMethod = "newKeychain" + NewSpaceMethod = "newSpace" + RemoveKeychainAdminMethod = "removeKeychainAdmin" + UpdateKeychainMethod = "updateKeychain" + AddSpaceOwnerMethod = "addSpaceOwner" + RemoveSpaceOwnerMethod = "removeSpaceOwner" + NewKeyRequestMethod = "newKeyRequest" + NewSignRequestMethod = "newSignRequest" + UpdateKeyMethod = "updateKey" + UpdateSpaceMethod = "updateSpace" +) + +// AddKeychainAdminMethod constructs MsgAddKeychainAdminRequest from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) AddKeychainAdminMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgAddKeychainAdmin, newAdmin, err := newMsgAddKeychainAdmin(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + if _, err := msgServer.AddKeychainAdmin(ctx, msgAddKeychainAdmin); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, newAdmin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// AddKeychainWriterMethod constructs MsgAddKeychainWriter from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) AddKeychainWriterMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgAddKeychainWriter, newWriterAddress, err := newMsgAddKeychainWriter(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + if _, err = msgServer.AddKeychainWriter(ctx, msgAddKeychainWriter); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, newWriterAddress); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// FulfilKeyRequestMethod constructs MsgFulfilKeyRequest from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) FulfilKeyRequestMethod( + ctx sdk.Context, + origin common.Address, + keyRequestStatus wardentypes.KeyRequestStatus, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgFulfilKeyRequest, err := newMsgFulfilKeyRequest(args, keyRequestStatus, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + if _, err = msgServer.FulfilKeyRequest(ctx, msgFulfilKeyRequest); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, nil); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// FulfilSignRequestMethod constructs MsgFulfilSignRequest from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) FulfilSignRequestMethod( + ctx sdk.Context, + origin common.Address, + signRequestStatus wardentypes.SignRequestStatus, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgFulfilSignRequest, err := newMsgFulfilSignRequest(args, signRequestStatus, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + if _, err = msgServer.FulfilSignRequest(ctx, msgFulfilSignRequest); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, nil); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// NewKeychainMethod constructs MsgNewKeychain from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) NewKeychainMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgNewKeychain, err := newMsgNewKeychain(method, args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + msgNewKeychainResponse, err := msgServer.NewKeychain(ctx, msgNewKeychain) + + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(msgNewKeychainResponse.Id) +} + +// NewSpaceMethod constructs MsgNewSpace from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) NewSpaceMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgNewSpace, err := newMsgNewSpace(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + msgNewSpaceResponse, err := msgServer.NewSpace(ctx, msgNewSpace) + + if err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(msgNewSpaceResponse.Id) +} + +// RemoveKeychainAdminMethod constructs MsgRemoveKeychainAdminRequest from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) RemoveKeychainAdminMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgRemoveKeychainAdmin, admin, err := newMsgRemoveKeychainAdmin(args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + if _, err := msgServer.RemoveKeychainAdmin(ctx, msgRemoveKeychainAdmin); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, admin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// UpdateKeychainMethod constructs MsgUpdateKeychain from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) UpdateKeychainMethod( + ctx sdk.Context, + origin common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := wardenkeeper.NewMsgServerImpl(p.wardenkeeper) + + msgUpdateKeychain, err := newMsgUpdateKeychain(method, args, origin) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + if _, err = msgServer.UpdateKeychain(ctx, msgUpdateKeychain); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// AddSpaceOwnerMethod constructs MsgAddSpaceOwner wrapped by MsgNewAction from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) AddSpaceOwnerMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actkeeper.NewMsgServerImpl(p.actkeeper) + + msgNewAction, err := newMsgAddSpaceOwner(args, origin, p.actkeeper.GetModuleAddress()) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + newActResult, err := msgServer.NewAction(ctx, msgNewAction) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, newActResult.Id, caller); err != nil { + return nil, err + } + + if err := p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// tryVoteAsSender attempts to vote for an action as the sender of the action. +// This is useful if the contract attempts to vote for an action. +// If the action is not in the pending state, this function does nothing. +// If the action is in the pending state, it attempts to vote for the action +// with an approved vote type. If the vote is successful, this function returns +// nil. If the vote fails, this function returns the error. +func (p Precompile) tryVoteAsSender( + ctx sdk.Context, + msgServer v1beta1.MsgServer, + actionId uint64, + caller common.Address) error { + + actionResponse, err := p.actQueryServer.ActionById(ctx, &v1beta1.QueryActionByIdRequest{ + Id: actionId, + }) + if err != nil { + return err + } + + action := actionResponse.Action + + if action.GetStatus() != v1beta1.ActionStatus_ACTION_STATUS_PENDING { + return nil + } + + participant := wardencommon.Bech32StrFromAddress(caller) + + _, err = msgServer.VoteForAction(ctx, &v1beta1.MsgVoteForAction{ + Participant: participant, + ActionId: action.GetId(), + VoteType: v1beta1.ActionVoteType_VOTE_TYPE_APPROVED, + }) + if err != nil { + return err + } + + return nil +} + +// RemoveSpaceOwnerMethod constructs MsgRemoveSpaceOwner wrapped by MsgNewAction from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) RemoveSpaceOwnerMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actkeeper.NewMsgServerImpl(p.actkeeper) + + msgNewAction, err := newMsgRemoveSpaceOwner(args, origin, p.actkeeper.GetModuleAddress()) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + newActResult, err := msgServer.NewAction(ctx, msgNewAction) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, newActResult.Id, caller); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// NewKeyRequestMethod constructs MsgNewKeyRequest wrapped by MsgNewAction from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) NewKeyRequestMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actkeeper.NewMsgServerImpl(p.actkeeper) + + msgNewAction, err := newMsgNewKeyRequest(method, args, origin, p.actkeeper.GetModuleAddress()) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + newActResult, err := msgServer.NewAction(ctx, msgNewAction) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, newActResult.Id, caller); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// NewSignRequestMethod constructs MsgNewSignRequest wrapped by MsgNewAction from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) NewSignRequestMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actkeeper.NewMsgServerImpl(p.actkeeper) + + msgNewAction, err := newMsgNewSignRequest(method, args, origin, p.actkeeper.GetModuleAddress()) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + newActResult, err := msgServer.NewAction(ctx, msgNewAction) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, newActResult.Id, caller); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// UpdateKeyMethod constructs MsgUpdateKey wrapped by MsgNewAction from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) UpdateKeyMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actkeeper.NewMsgServerImpl(p.actkeeper) + + msgNewAction, err := newMsgUpdateKey(args, origin, p.actkeeper.GetModuleAddress()) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + newActResult, err := msgServer.NewAction(ctx, msgNewAction) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, newActResult.Id, caller); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} + +// UpdateSpaceMethod constructs MsgUpdateSpace wrapped by MsgNewAction from args, passes it to msg server and packs corresponding abi output. +func (p Precompile) UpdateSpaceMethod( + ctx sdk.Context, + origin common.Address, + caller common.Address, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) ([]byte, error) { + msgServer := actkeeper.NewMsgServerImpl(p.actkeeper) + + msgNewAction, err := newMsgUpdateSpace(args, origin, p.actkeeper.GetModuleAddress()) + + if err != nil { + return nil, err + } + + p.Logger(ctx).Debug( + "tx called", + "method", method.Name, + "args", args, + ) + + newActResult, err := msgServer.NewAction(ctx, msgNewAction) + if err != nil { + return nil, err + } + + if err := p.tryVoteAsSender(ctx, msgServer, newActResult.Id, caller); err != nil { + return nil, err + } + + if err = p.eventsRegistry.EmitEvents(ctx, stateDB, &origin); err != nil { + return nil, err + } + + return method.Outputs.Pack(true) +} diff --git a/src/orders/precompiles/warden/tx_types.go b/src/orders/precompiles/warden/tx_types.go new file mode 100644 index 0000000..48a9283 --- /dev/null +++ b/src/orders/precompiles/warden/tx_types.go @@ -0,0 +1,684 @@ +package warden + +import ( + "fmt" + + codecTypes "github.com/cosmos/cosmos-sdk/codec/types" + cosmosTypes "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + wardencommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + actTypes "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" + types "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" +) + +func newMsgAddKeychainAdmin(args []interface{}, origin common.Address) (*types.MsgAddKeychainAdminRequest, *common.Address, error) { + if len(args) != 2 { + return nil, nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + keychainId, ok := args[0].(uint64) + if !ok { + return nil, nil, fmt.Errorf("expected uint64 for keychainId, got %T", args[0]) + } + + newAdminAddress, ok := args[1].(common.Address) + if !ok { + return nil, nil, fmt.Errorf("expected common.Address for newAdminAddress, got %T", args[1]) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + newAdmin := wardencommon.Bech32StrFromAddress(newAdminAddress) + + return &types.MsgAddKeychainAdminRequest{ + Authority: authority, + KeychainId: keychainId, + NewAdmin: newAdmin, + }, &newAdminAddress, nil +} + +func newMsgAddKeychainWriter(args []interface{}, origin common.Address) (*types.MsgAddKeychainWriter, *common.Address, error) { + if len(args) != 2 { + return nil, nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + keychainId, ok := args[0].(uint64) + if !ok { + return nil, nil, fmt.Errorf("expected uint64 for keychainId, got %T", args[0]) + } + + newWriterAddress, ok := args[1].(common.Address) + if !ok { + return nil, nil, fmt.Errorf("expected common.Address for newWriterAddress, got %T", args[1]) + } + + creator := wardencommon.Bech32StrFromAddress(origin) + newWriter := wardencommon.Bech32StrFromAddress(newWriterAddress) + + return &types.MsgAddKeychainWriter{ + Creator: creator, + KeychainId: keychainId, + Writer: newWriter, + }, &newWriterAddress, nil +} + +func newMsgFulfilKeyRequest(args []interface{}, keyRequestStatus types.KeyRequestStatus, origin common.Address) (*types.MsgFulfilKeyRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + requestId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for requestId, got %T", args[0]) + } + + creator := wardencommon.Bech32StrFromAddress(origin) + + if keyRequestStatus == types.KeyRequestStatus_KEY_REQUEST_STATUS_FULFILLED { + key, ok1 := args[1].([]byte) + if !ok1 { + return nil, fmt.Errorf("expected []byte for key, got %T", args[1]) + } + + result := &types.MsgFulfilKeyRequest_Key{ + Key: &types.MsgNewKey{ + PublicKey: key, + }, + } + + return &types.MsgFulfilKeyRequest{ + Creator: creator, + RequestId: requestId, + Status: keyRequestStatus, + Result: result, + }, nil + } else { + rejectReason, ok1 := args[1].(string) + if !ok1 { + return nil, fmt.Errorf("expected string for rejectReason, got %T", args[1]) + } + + result := &types.MsgFulfilKeyRequest_RejectReason{ + RejectReason: rejectReason, + } + + return &types.MsgFulfilKeyRequest{ + Creator: creator, + RequestId: requestId, + Status: keyRequestStatus, + Result: result, + }, nil + } +} + +func newMsgFulfilSignRequest(args []interface{}, signRequestStatus types.SignRequestStatus, origin common.Address) (*types.MsgFulfilSignRequest, error) { + if len(args) != 2 { + return nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + creator := wardencommon.Bech32StrFromAddress(origin) + + requestId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for requestId, got %T", args[0]) + } + + if signRequestStatus == types.SignRequestStatus_SIGN_REQUEST_STATUS_FULFILLED { + signedData, ok1 := args[1].([]byte) + if !ok1 { + return nil, fmt.Errorf("expected []byte for signedData, got %T", args[1]) + } + + result := &types.MsgFulfilSignRequest_Payload{ + Payload: &types.MsgSignedData{ + SignedData: signedData, + }, + } + + return &types.MsgFulfilSignRequest{ + Creator: creator, + RequestId: requestId, + Status: types.SignRequestStatus_SIGN_REQUEST_STATUS_FULFILLED, + Result: result, + }, nil + } else { + rejectReason, ok1 := args[1].(string) + if !ok1 { + return nil, fmt.Errorf("expected string for rejectReason, got %T", args[1]) + } + + result := &types.MsgFulfilSignRequest_RejectReason{ + RejectReason: rejectReason, + } + + return &types.MsgFulfilSignRequest{ + Creator: creator, + RequestId: requestId, + Status: signRequestStatus, + Result: result, + }, nil + } +} + +func newMsgNewKeychain(method *abi.Method, args []interface{}, origin common.Address) (*types.MsgNewKeychain, error) { + if len(args) != 5 { + return nil, wardencommon.WrongArgsNumber{Expected: 5, Got: len(args)} + } + + creator := wardencommon.Bech32StrFromAddress(origin) + var input newKeyChainInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to newKeyChainInput struct: %w", err) + } + + return &types.MsgNewKeychain{ + Creator: creator, + Name: input.Name, + KeychainFees: input.KeychainFees, + Description: input.Description, + Url: input.Url, + KeybaseId: input.KeybaseId, + }, nil +} + +type newKeyChainInput struct { + Name string + KeychainFees types.KeychainFees + Description string + Url string + KeybaseId string +} + +func newMsgNewSpace(args []interface{}, origin common.Address) (*types.MsgNewSpace, error) { + if len(args) != 5 { + return nil, wardencommon.WrongArgsNumber{Expected: 5, Got: len(args)} + } + + creator := wardencommon.Bech32StrFromAddress(origin) + + approveAdminTemplateId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for approveAdminTemplateId, got %T", args[0]) + } + + rejectAdminTemplateId, ok := args[1].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for rejectAdminTemplateId, got %T", args[1]) + } + + approveSignTemplateId, ok := args[2].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for approveSignTemplateId, got %T", args[2]) + } + + rejectSignTemplateId, ok := args[3].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for rejectSignTemplateId, got %T", args[3]) + } + + owners, ok := args[4].([]common.Address) + if !ok { + return nil, fmt.Errorf("expected []common.Address for owners, got %T", args[4]) + } + + var additionalOwners []string + for _, a := range owners { + additionalOwners = append(additionalOwners, wardencommon.Bech32StrFromAddress(a)) + } + + return &types.MsgNewSpace{ + Creator: creator, + ApproveAdminTemplateId: approveAdminTemplateId, + RejectAdminTemplateId: rejectAdminTemplateId, + ApproveSignTemplateId: approveSignTemplateId, + RejectSignTemplateId: rejectSignTemplateId, + AdditionalOwners: additionalOwners, + }, nil +} + +func newMsgRemoveKeychainAdmin(args []interface{}, origin common.Address) (*types.MsgRemoveKeychainAdminRequest, *common.Address, error) { + if len(args) != 2 { + return nil, nil, wardencommon.WrongArgsNumber{Expected: 2, Got: len(args)} + } + + creator := wardencommon.Bech32StrFromAddress(origin) + + keychainId, ok := args[0].(uint64) + if !ok { + return nil, nil, fmt.Errorf("expected uint64 for keychainId, got %T", args[0]) + } + + admin, ok := args[1].(common.Address) + if !ok { + return nil, nil, fmt.Errorf("expected common.Address for admin, got %T", args[1]) + } + + return &types.MsgRemoveKeychainAdminRequest{ + Authority: creator, + KeychainId: keychainId, + Admin: wardencommon.Bech32StrFromAddress(admin), + }, &admin, nil +} + +func newMsgUpdateKeychain(method *abi.Method, args []interface{}, origin common.Address) (*types.MsgUpdateKeychain, error) { + if len(args) != 6 { + return nil, wardencommon.WrongArgsNumber{Expected: 6, Got: len(args)} + } + + creator := wardencommon.Bech32StrFromAddress(origin) + var input updateKeyChainInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to updateKeyChainInput struct: %w", err) + } + + return &types.MsgUpdateKeychain{ + Creator: creator, + KeychainId: input.KeychainId, + Name: input.Name, + KeychainFees: mapEthKeychainFees(input.KeychainFees), + Description: input.Description, + Url: input.Url, + KeybaseId: input.KeybaseId, + }, nil +} + +type updateKeyChainInput struct { + KeychainId uint64 + Name string + KeychainFees KeychainFees + Description string + Url string + KeybaseId string +} + +func newMsgAddSpaceOwner(args []interface{}, origin common.Address, act string) (*actTypes.MsgNewAction, error) { + if len(args) != 6 { + return nil, wardencommon.WrongArgsNumber{Expected: 6, Got: len(args)} + } + + spaceId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for spaceId, got %T", args[0]) + } + + newOwnerAddress, ok := args[1].(common.Address) + if !ok { + return nil, fmt.Errorf("expected common.Address for newOwnerAddress, got %T", args[1]) + } + + nonce, ok := args[2].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for nonce, got %T", args[2]) + } + + actionTimeoutHeight, ok := args[3].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionTimeoutHeight, got %T", args[3]) + } + + expectedApproveExpression, ok := args[4].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedApproveExpression, got %T", args[4]) + } + + expectedRejectExpression, ok := args[5].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedRejectExpression, got %T", args[5]) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + newOwner := wardencommon.Bech32StrFromAddress(newOwnerAddress) + + msgAddSpaceOwner := types.MsgAddSpaceOwner{ + Authority: act, + SpaceId: spaceId, + NewOwner: newOwner, + Nonce: nonce, + } + + anyMsg, err := codecTypes.NewAnyWithValue(&msgAddSpaceOwner) + if err != nil { + return nil, err + } + + return &actTypes.MsgNewAction{ + Creator: authority, + Message: anyMsg, + ActionTimeoutHeight: actionTimeoutHeight, + ExpectedApproveExpression: expectedApproveExpression, + ExpectedRejectExpression: expectedRejectExpression, + }, nil +} + +func newMsgRemoveSpaceOwner(args []interface{}, origin common.Address, act string) (*actTypes.MsgNewAction, error) { + if len(args) != 6 { + return nil, wardencommon.WrongArgsNumber{Expected: 6, Got: len(args)} + } + + spaceId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for spaceId, got %T", args[0]) + } + + ownerAddress, ok := args[1].(common.Address) + if !ok { + return nil, fmt.Errorf("expected common.Address for ownerAddress, got %T", args[1]) + } + + nonce, ok := args[2].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for nonce, got %T", args[2]) + } + + actionTimeoutHeight, ok := args[3].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionTimeoutHeight, got %T", args[3]) + } + + expectedApproveExpression, ok := args[4].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedApproveExpression, got %T", args[4]) + } + + expectedRejectExpression, ok := args[5].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedRejectExpression, got %T", args[5]) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + owner := wardencommon.Bech32StrFromAddress(ownerAddress) + + msgRemoveSpaceOwner := types.MsgRemoveSpaceOwner{ + Authority: act, + SpaceId: spaceId, + Owner: owner, + Nonce: nonce, + } + + anyMsg, err := codecTypes.NewAnyWithValue(&msgRemoveSpaceOwner) + if err != nil { + return nil, err + } + + return &actTypes.MsgNewAction{ + Creator: authority, + Message: anyMsg, + ActionTimeoutHeight: actionTimeoutHeight, + ExpectedApproveExpression: expectedApproveExpression, + ExpectedRejectExpression: expectedRejectExpression, + }, nil +} + +type newKeyRequestInput struct { + SpaceId uint64 + KeychainId uint64 + KeyType uint8 + ApproveTemplateId uint64 + RejectTemplateId uint64 + MaxKeychainFees []cosmosTypes.Coin + Nonce uint64 + ActionTimeoutHeight uint64 + ExpectedApproveExpression string + ExpectedRejectExpression string +} + +func newMsgNewKeyRequest(method *abi.Method, args []interface{}, origin common.Address, act string) (*actTypes.MsgNewAction, error) { + if len(args) != 10 { + return nil, wardencommon.WrongArgsNumber{Expected: 10, Got: len(args)} + } + + var input newKeyRequestInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to newMsgNewKeyRequest struct: %w", err) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + + mapKeyType := func(keyType uint8) (types.KeyType, error) { + switch keyType { + case uint8(types.KeyType_KEY_TYPE_UNSPECIFIED): + return types.KeyType_KEY_TYPE_UNSPECIFIED, nil + case uint8(types.KeyType_KEY_TYPE_ECDSA_SECP256K1): + return types.KeyType_KEY_TYPE_ECDSA_SECP256K1, nil + case uint8(types.KeyType_KEY_TYPE_EDDSA_ED25519): + return types.KeyType_KEY_TYPE_EDDSA_ED25519, nil + default: + return -1, fmt.Errorf("key type is not supported: %v", keyType) + } + } + + keyType, err := mapKeyType(input.KeyType) + if err != nil { + return nil, err + } + + msgNewKeyRequest := types.MsgNewKeyRequest{ + Authority: act, + SpaceId: input.SpaceId, + KeychainId: input.KeychainId, + KeyType: keyType, + ApproveTemplateId: input.ApproveTemplateId, + RejectTemplateId: input.RejectTemplateId, + MaxKeychainFees: input.MaxKeychainFees, + Nonce: input.Nonce, + } + + anyMsg, err := codecTypes.NewAnyWithValue(&msgNewKeyRequest) + if err != nil { + return nil, err + } + + return &actTypes.MsgNewAction{ + Creator: authority, + Message: anyMsg, + ActionTimeoutHeight: input.ActionTimeoutHeight, + ExpectedApproveExpression: input.ExpectedApproveExpression, + ExpectedRejectExpression: input.ExpectedRejectExpression, + }, nil +} + +type newSignRequestInput struct { + KeyId uint64 + Input []byte + Analyzers [][]byte + EncryptionKey []byte + MaxKeychainFees []cosmosTypes.Coin + Nonce uint64 + ActionTimeoutHeight uint64 + ExpectedApproveExpression string + ExpectedRejectExpression string + BroadcastType uint8 +} + +func newMsgNewSignRequest(method *abi.Method, args []interface{}, origin common.Address, act string) (*actTypes.MsgNewAction, error) { + if len(args) != 10 { + return nil, wardencommon.WrongArgsNumber{Expected: 10, Got: len(args)} + } + + var input newSignRequestInput + if err := method.Inputs.Copy(&input, args); err != nil { + return nil, fmt.Errorf("error while unpacking args to newSignRequestInput struct: %w", err) + } + + var analyzers []string + for _, a := range input.Analyzers { + analyzers = append(analyzers, wardencommon.Bech32StrFromBytes(a)) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + + mapBroadcastType := func(broadcastType uint8) (types.BroadcastType, error) { + switch broadcastType { + case uint8(types.BroadcastType_BROADCAST_TYPE_DISABLED): + return types.BroadcastType_BROADCAST_TYPE_DISABLED, nil + case uint8(types.BroadcastType_BROADCAST_TYPE_AUTOMATIC): + return types.BroadcastType_BROADCAST_TYPE_AUTOMATIC, nil + default: + return -1, fmt.Errorf("broadcast type is not supported: %v", broadcastType) + } + } + + broadcastType, err := mapBroadcastType(input.BroadcastType) + if err != nil { + return nil, err + } + + msgNewSignRequest := types.MsgNewSignRequest{ + Authority: act, + KeyId: input.KeyId, + Input: input.Input, + Analyzers: analyzers, + EncryptionKey: input.EncryptionKey, + MaxKeychainFees: input.MaxKeychainFees, + Nonce: input.Nonce, + BroadcastType: broadcastType, + } + + anyMsg, err := codecTypes.NewAnyWithValue(&msgNewSignRequest) + if err != nil { + return nil, err + } + + return &actTypes.MsgNewAction{ + Creator: authority, + Message: anyMsg, + ActionTimeoutHeight: input.ActionTimeoutHeight, + ExpectedApproveExpression: input.ExpectedApproveExpression, + ExpectedRejectExpression: input.ExpectedRejectExpression, + }, nil +} + +func newMsgUpdateKey(args []interface{}, origin common.Address, act string) (*actTypes.MsgNewAction, error) { + if len(args) != 6 { + return nil, wardencommon.WrongArgsNumber{Expected: 6, Got: len(args)} + } + + keyId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for keyId, got %T", args[0]) + } + + approveTemplateId, ok := args[1].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for approveTemplateId, got %T", args[1]) + } + + rejectTemplateId, ok := args[2].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for rejectTemplateId, got %T", args[2]) + } + + actionTimeoutHeight, ok := args[3].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionTimeoutHeight, got %T", args[3]) + } + + expectedApproveExpression, ok := args[4].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedApproveExpression, got %T", args[4]) + } + + expectedRejectExpression, ok := args[5].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedRejectExpression, got %T", args[5]) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + + msgUpdateKey := types.MsgUpdateKey{ + Authority: act, + KeyId: keyId, + ApproveTemplateId: approveTemplateId, + RejectTemplateId: rejectTemplateId, + } + + anyMsg, err := codecTypes.NewAnyWithValue(&msgUpdateKey) + if err != nil { + return nil, err + } + + return &actTypes.MsgNewAction{ + Creator: authority, + Message: anyMsg, + ActionTimeoutHeight: actionTimeoutHeight, + ExpectedApproveExpression: expectedApproveExpression, + ExpectedRejectExpression: expectedRejectExpression, + }, nil +} + +func newMsgUpdateSpace(args []interface{}, origin common.Address, act string) (*actTypes.MsgNewAction, error) { + if len(args) != 9 { + return nil, wardencommon.WrongArgsNumber{Expected: 9, Got: len(args)} + } + + spaceId, ok := args[0].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for spaceId, got %T", args[0]) + } + + nonce, ok := args[1].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for nonce, got %T", args[1]) + } + + approveAdminTemplateId, ok := args[2].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for approveAdminTemplateId, got %T", args[2]) + } + + rejectAdminTemplateId, ok := args[3].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for rejectAdminTemplateId, got %T", args[3]) + } + + approveSignTemplateId, ok := args[4].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for approveSignTemplateId, got %T", args[4]) + } + + rejectSignTemplateId, ok := args[5].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for rejectSignTemplateId, got %T", args[5]) + } + + actionTimeoutHeight, ok := args[6].(uint64) + if !ok { + return nil, fmt.Errorf("expected uint64 for actionTimeoutHeight, got %T", args[6]) + } + + expectedApproveExpression, ok := args[7].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedApproveExpression, got %T", args[7]) + } + + expectedRejectExpression, ok := args[8].(string) + if !ok { + return nil, fmt.Errorf("expected string for expectedRejectExpression, got %T", args[8]) + } + + authority := wardencommon.Bech32StrFromAddress(origin) + + msgUpdateSpace := types.MsgUpdateSpace{ + Authority: act, + SpaceId: spaceId, + Nonce: nonce, + ApproveAdminTemplateId: approveAdminTemplateId, + RejectAdminTemplateId: rejectAdminTemplateId, + ApproveSignTemplateId: approveSignTemplateId, + RejectSignTemplateId: rejectSignTemplateId, + } + + anyMsg, err := codecTypes.NewAnyWithValue(&msgUpdateSpace) + if err != nil { + return nil, err + } + + return &actTypes.MsgNewAction{ + Creator: authority, + Message: anyMsg, + ActionTimeoutHeight: actionTimeoutHeight, + ExpectedApproveExpression: expectedApproveExpression, + ExpectedRejectExpression: expectedRejectExpression, + }, nil +} diff --git a/src/orders/precompiles/warden/types.go b/src/orders/precompiles/warden/types.go new file mode 100644 index 0000000..3c64970 --- /dev/null +++ b/src/orders/precompiles/warden/types.go @@ -0,0 +1,63 @@ +package warden + +import ( + "cosmossdk.io/math" + + sdkTypes "github.com/cosmos/cosmos-sdk/types" + sdkQuery "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" +) + +func mapSdkKeychainFees(keychainFees v1beta3.KeychainFees) KeychainFees { + keyReq := mapSdkCoins(keychainFees.KeyReq) + sigReq := mapSdkCoins(keychainFees.SigReq) + + return KeychainFees{ + KeyReq: keyReq, + SigReq: sigReq, + } +} + +func mapEthKeychainFees(keychainFees KeychainFees) v1beta3.KeychainFees { + keyReq := make([]sdkTypes.Coin, 0, len(keychainFees.KeyReq)) + for _, kr := range keychainFees.KeyReq { + keyReq = append(keyReq, sdkTypes.NewCoin(kr.Denom, math.NewIntFromBigInt(kr.Amount))) + } + + sigReq := make([]sdkTypes.Coin, 0, len(keychainFees.SigReq)) + for _, sr := range keychainFees.SigReq { + sigReq = append(sigReq, sdkTypes.NewCoin(sr.Denom, math.NewIntFromBigInt(sr.Amount))) + } + + return v1beta3.KeychainFees{ + KeyReq: keyReq, + SigReq: sigReq, + } +} + +func mapSdkCoins(coins sdkTypes.Coins) []TypesCoin { + c := make([]TypesCoin, 0, len(coins)) + for _, sdkCoin := range coins { + c = append(c, TypesCoin{Denom: sdkCoin.GetDenom(), Amount: sdkCoin.Amount.BigInt()}) + } + + return c +} + +func mapSdkPageResponse(pageResponse sdkQuery.PageResponse) TypesPageResponse { + return TypesPageResponse{ + NextKey: pageResponse.GetNextKey(), + Total: pageResponse.GetTotal(), + } +} + +func mapEthPageRequest(pageRequest TypesPageRequest) sdkQuery.PageRequest { + return sdkQuery.PageRequest{ + Key: pageRequest.Key, + Offset: pageRequest.Offset, + Limit: pageRequest.Limit, + CountTotal: pageRequest.CountTotal, + Reverse: pageRequest.Reverse, + } +} diff --git a/src/orders/precompiles/warden/warden.go b/src/orders/precompiles/warden/warden.go new file mode 100644 index 0000000..8a67c37 --- /dev/null +++ b/src/orders/precompiles/warden/warden.go @@ -0,0 +1,236 @@ +package warden + +import ( + "embed" + "fmt" + + "cosmossdk.io/log" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + cmn "github.com/evmos/evmos/v20/precompiles/common" + "github.com/evmos/evmos/v20/x/evm/core/vm" + + precommon "github.com/warden-protocol/wardenprotocol/precompiles/common" + actmodulekeeper "github.com/warden-protocol/wardenprotocol/warden/x/act/keeper" + acttypes "github.com/warden-protocol/wardenprotocol/warden/x/act/types/v1beta1" + wardenmodulekeeper "github.com/warden-protocol/wardenprotocol/warden/x/warden/keeper" + "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" + types "github.com/warden-protocol/wardenprotocol/warden/x/warden/types/v1beta3" +) + +var _ vm.PrecompiledContract = &Precompile{} + +// Embed abi json file to the executable binary. Needed when importing as dependency. +// +//go:embed abi.json +var f embed.FS + +// PrecompileAddress defines the contract address of the x/warden precompile. +const PrecompileAddress = "0x0000000000000000000000000000000000000900" + +// Precompile defines the precompiled contract for x/warden. +type Precompile struct { + cmn.Precompile + wardenkeeper wardenmodulekeeper.Keeper + actkeeper actmodulekeeper.Keeper + eventsRegistry *precommon.EthEventsRegistry + queryServer types.QueryServer + actQueryServer acttypes.QueryServer +} + +// LoadABI loads the x/warden ABI from the embedded abi.json file +// for the x/warden precompile. +func LoadABI() (abi.ABI, error) { + return cmn.LoadABI(f, "abi.json") +} + +func NewPrecompile( + wardenkeeper wardenmodulekeeper.Keeper, + actkeeper actmodulekeeper.Keeper, + e *precommon.EthEventsRegistry) (*Precompile, error) { + abi, err := LoadABI() + if err != nil { + return nil, err + } + + p := Precompile{ + Precompile: cmn.Precompile{ + ABI: abi, + KvGasConfig: storetypes.KVGasConfig(), + TransientKVGasConfig: storetypes.TransientGasConfig(), + }, + wardenkeeper: wardenkeeper, + actkeeper: actkeeper, + eventsRegistry: e, + queryServer: wardenmodulekeeper.NewQueryServerImpl(wardenkeeper), + actQueryServer: actmodulekeeper.NewQueryServerImpl(actkeeper), + } + + p.SetAddress(common.HexToAddress(PrecompileAddress)) + + return &p, nil +} + +// Address implements vm.PrecompiledContract. +func (*Precompile) Address() common.Address { + return common.HexToAddress(PrecompileAddress) +} + +// RequiredGas returns the required bare minimum gas to execute the precompile. +// Subtle: this method shadows the method (Precompile).RequiredGas of Precompile.Precompile. +func (p *Precompile) RequiredGas(input []byte) uint64 { + // NOTE: This check avoid panicking when trying to decode the method ID + if len(input) < 4 { + return 0 + } + + methodID := input[:4] + + method, err := p.MethodById(methodID) + if err != nil { + // This should never happen since this method is going to fail during Run + return 0 + } + + return p.Precompile.RequiredGas(input, p.IsTransaction(method.Name)) +} + +// Run implements vm.PrecompiledContract. +func (p *Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) { + ctx, stateDB, snapshot, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction) + if err != nil { + return nil, err + } + + // This handles any out of gas errors that may occur during the execution of a precompile tx or query. + // It avoids panics and returns the out of gas error so the EVM can continue gracefully. + defer cmn.HandleGasError(ctx, contract, initialGas, &err)() + + switch method.Name { + // transactions + case AddKeychainAdminMethod: + bz, err = p.AddKeychainAdminMethod(ctx, evm.Origin, stateDB, method, args) + case AddKeychainWriterMethod: + bz, err = p.AddKeychainWriterMethod(ctx, evm.Origin, stateDB, method, args) + case FulfilKeyRequestMethod: + bz, err = p.FulfilKeyRequestMethod(ctx, evm.Origin, v1beta3.KeyRequestStatus_KEY_REQUEST_STATUS_FULFILLED, stateDB, method, args) + case RejectKeyRequestMethod: + bz, err = p.FulfilKeyRequestMethod(ctx, evm.Origin, v1beta3.KeyRequestStatus_KEY_REQUEST_STATUS_REJECTED, stateDB, method, args) + case FulfilSignRequestMethod: + bz, err = p.FulfilSignRequestMethod(ctx, evm.Origin, v1beta3.SignRequestStatus_SIGN_REQUEST_STATUS_FULFILLED, stateDB, method, args) + case RejectSignRequestMethod: + bz, err = p.FulfilSignRequestMethod(ctx, evm.Origin, v1beta3.SignRequestStatus_SIGN_REQUEST_STATUS_REJECTED, stateDB, method, args) + case NewKeychainMethod: + bz, err = p.NewKeychainMethod(ctx, evm.Origin, stateDB, method, args) + case NewSpaceMethod: + bz, err = p.NewSpaceMethod(ctx, evm.Origin, stateDB, method, args) + case RemoveKeychainAdminMethod: + bz, err = p.RemoveKeychainAdminMethod(ctx, evm.Origin, stateDB, method, args) + case UpdateKeychainMethod: + bz, err = p.UpdateKeychainMethod(ctx, evm.Origin, stateDB, method, args) + case AddSpaceOwnerMethod: + bz, err = p.AddSpaceOwnerMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + case RemoveSpaceOwnerMethod: + bz, err = p.RemoveSpaceOwnerMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + case NewKeyRequestMethod: + bz, err = p.NewKeyRequestMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + case NewSignRequestMethod: + bz, err = p.NewSignRequestMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + case UpdateKeyMethod: + bz, err = p.UpdateKeyMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + case UpdateSpaceMethod: + bz, err = p.UpdateSpaceMethod(ctx, evm.Origin, contract.CallerAddress, stateDB, method, args) + + // queries + case AllKeysMethod: + bz, err = p.AllKeysMethod(ctx, evm.Origin, stateDB, method, args) + case KeyByIdMethod: + bz, err = p.KeyByIdMethod(ctx, evm.Origin, stateDB, method, args) + case KeysBySpaceIdMethod: + bz, err = p.KeysBySpaceIdMethod(ctx, evm.Origin, stateDB, method, args) + case KeyRequestMethod: + bz, err = p.KeyRequestMethod(ctx, evm.Origin, stateDB, method, args) + case KeyRequestsMethod: + bz, err = p.KeyRequestsMethod(ctx, evm.Origin, stateDB, method, args) + case KeychainMethod: + bz, err = p.KeychainMethod(ctx, evm.Origin, stateDB, method, args) + case KeychainsMethod: + bz, err = p.KeychainsMethod(ctx, evm.Origin, stateDB, method, args) + case SignRequestByIdMethod: + bz, err = p.SignRequestByIdMethod(ctx, evm.Origin, stateDB, method, args) + case SignRequestsMethod: + bz, err = p.SignRequestsMethod(ctx, evm.Origin, stateDB, method, args) + case SpaceByIdMethod: + bz, err = p.SpaceByIdMethod(ctx, evm.Origin, stateDB, method, args) + case SpacesMethod: + bz, err = p.SpacesMethod(ctx, evm.Origin, stateDB, method, args) + case SpacesByOwnerMethod: + bz, err = p.SpacesByOwnerMethod(ctx, evm.Origin, stateDB, method, args) + } + + if err != nil { + return nil, err + } + + cost := ctx.GasMeter().GasConsumed() - initialGas + + if !contract.UseGas(cost) { + return nil, vm.ErrOutOfGas + } + + if err := p.AddJournalEntries(stateDB, snapshot); err != nil { + return nil, err + } + + return bz, nil +} + +// IsTransaction checks if the given method name corresponds to a transaction or query. +// +// Available warden transactions are: +// +// - +func (*Precompile) IsTransaction(method string) bool { + switch method { + case AddKeychainAdminMethod, + AddKeychainWriterMethod, + FulfilKeyRequestMethod, + RejectKeyRequestMethod, + FulfilSignRequestMethod, + RejectSignRequestMethod, + NewKeychainMethod, + NewSpaceMethod, + RemoveKeychainAdminMethod, + UpdateKeychainMethod, + AddSpaceOwnerMethod, + RemoveSpaceOwnerMethod, + NewKeyRequestMethod, + NewSignRequestMethod, + UpdateKeyMethod, + UpdateSpaceMethod: + return true + case AllKeysMethod, + KeyByIdMethod, + KeysBySpaceIdMethod, + KeyRequestMethod, + KeyRequestsMethod, + KeychainMethod, + KeychainsMethod, + SignRequestByIdMethod, + SignRequestsMethod, + SpaceByIdMethod, + SpacesMethod, + SpacesByOwnerMethod: + return false + } + + panic(fmt.Errorf("warden precompile: method not exists: %s", method)) +} + +// Logger returns a precompile-specific logger. +func (p *Precompile) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("evm extension", "x/warden") +} diff --git a/src/orders/remappings.txt b/src/orders/remappings.txt new file mode 100644 index 0000000..550f908 --- /dev/null +++ b/src/orders/remappings.txt @@ -0,0 +1,2 @@ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ +forge-std/=node_modules/forge-std/ diff --git a/src/orders/script/CreateOrder.s.sol b/src/orders/script/CreateOrder.s.sol new file mode 100644 index 0000000..f0873ce --- /dev/null +++ b/src/orders/script/CreateOrder.s.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { IWARDEN_PRECOMPILE_ADDRESS } from "../precompiles/warden/IWarden.sol"; +import { ISLINKY_PRECOMPILE_ADDRESS } from "../precompiles/slinky/ISlinky.sol"; +import { IASYNC_PRECOMPILE_ADDRESS } from "../precompiles/async/IAsync.sol"; +import { Script } from "forge-std/src/Script.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { MockWardenPrecompile } from "../mocks/MockWardenPrecompile.sol"; +import { MockSlinkyPrecompile } from "../mocks/MockSlinkyPrecompile.sol"; +import { MockAsyncPrecompile } from "../mocks/MockAsyncPrecompile.sol"; +import { OrderFactory, OrderType } from "../src/OrderFactory.sol"; +import { Types } from "../src/Types.sol"; + +contract CreateOrder is Script { + address internal broadcaster; + OrderFactory private immutable FACTORY; + + error InvalidFactory(); + + constructor() { + (broadcaster,) = deriveRememberKey({ mnemonic: vm.envString("MNEMONIC"), index: 0 }); + address factory = vm.envAddress("FACTORY_ADDRESS"); + if (factory == address(0)) { + revert InvalidFactory(); + } + FACTORY = OrderFactory(factory); + } + + function basic( + uint256 thresholdPrice, + Types.PriceCondition priceCondition, + Types.PricePair calldata pricePair, + Types.CreatorDefinedTxFields calldata creatorDefinedTxFields, + uint64 keyId, + uint64 spaceNonce, + uint64 actionTimeoutHeight, + bytes calldata expectedApproveExpression, + bytes calldata expectedRejectExpression, + bytes32 salt + ) + external + { + MockSlinkyPrecompile mSlinkyPrecompile = new MockSlinkyPrecompile(); + MockWardenPrecompile wPrecompile = new MockWardenPrecompile(); + + bytes[] memory analyzers = new bytes[](0); + bytes memory encryptionKey = new bytes(0); + Types.SignRequestData memory signRequestData = Types.SignRequestData({ + keyId: keyId, + analyzers: analyzers, + encryptionKey: encryptionKey, + spaceNonce: spaceNonce, + actionTimeoutHeight: actionTimeoutHeight, + expectedApproveExpression: string(expectedApproveExpression), + expectedRejectExpression: string(expectedRejectExpression) + }); + CommonTypes.Coin[] memory maxKeychainFees = new CommonTypes.Coin[](0); + Types.BasicOrderData memory orderData = Types.BasicOrderData({ + thresholdPrice: thresholdPrice, + priceCondition: priceCondition, + pricePair: pricePair + }); + Types.CommonExecutionData memory commonExecutionData = Types.CommonExecutionData({ + creatorDefinedTxFields: creatorDefinedTxFields, + signRequestData: signRequestData + }); + vm.etch(ISLINKY_PRECOMPILE_ADDRESS, address(mSlinkyPrecompile).code); + MockSlinkyPrecompile mockSlinkyPrecompile = MockSlinkyPrecompile(ISLINKY_PRECOMPILE_ADDRESS); + mockSlinkyPrecompile.setPrice(pricePair.base, pricePair.quote, thresholdPrice); + vm.etch(IWARDEN_PRECOMPILE_ADDRESS, address(wPrecompile).code); + vm.startBroadcast(broadcaster); + FACTORY.createOrder(abi.encode(orderData), commonExecutionData, maxKeychainFees, OrderType.Basic, salt); + + vm.stopBroadcast(); + } + + function advanced( + Types.PriceCondition priceCondition, + Types.PricePair calldata oraclePricePair, + Types.PricePair calldata predictPricePair, + Types.CreatorDefinedTxFields calldata creatorDefinedTxFields, + uint64 keyId, + uint64 spaceNonce, + uint64 actionTimeoutHeight, + bytes calldata expectedApproveExpression, + bytes calldata expectedRejectExpression, + bytes32 salt + ) + external + { + MockSlinkyPrecompile mSlinkyPrecompile = new MockSlinkyPrecompile(); + MockWardenPrecompile wPrecompile = new MockWardenPrecompile(); + MockAsyncPrecompile aPrecompile = new MockAsyncPrecompile(); + + bytes[] memory analyzers = new bytes[](0); + bytes memory encryptionKey = new bytes(0); + Types.SignRequestData memory signRequestData = Types.SignRequestData({ + keyId: keyId, + analyzers: analyzers, + encryptionKey: encryptionKey, + spaceNonce: spaceNonce, + actionTimeoutHeight: actionTimeoutHeight, + expectedApproveExpression: string(expectedApproveExpression), + expectedRejectExpression: string(expectedRejectExpression) + }); + CommonTypes.Coin[] memory maxKeychainFees = new CommonTypes.Coin[](0); + Types.AdvancedOrderData memory orderData = Types.AdvancedOrderData({ + priceCondition: priceCondition, + oraclePricePair: oraclePricePair, + predictPricePair: predictPricePair, + pricePredictDate: block.timestamp + 24 hours + }); + Types.CommonExecutionData memory commonExecutionData = Types.CommonExecutionData({ + creatorDefinedTxFields: creatorDefinedTxFields, + signRequestData: signRequestData + }); + vm.etch(ISLINKY_PRECOMPILE_ADDRESS, address(mSlinkyPrecompile).code); + MockSlinkyPrecompile mockSlinkyPrecompile = MockSlinkyPrecompile(ISLINKY_PRECOMPILE_ADDRESS); + mockSlinkyPrecompile.setPrice(oraclePricePair.base, oraclePricePair.quote, 1); + vm.etch(IWARDEN_PRECOMPILE_ADDRESS, address(wPrecompile).code); + vm.etch(IASYNC_PRECOMPILE_ADDRESS, address(aPrecompile).code); + vm.startBroadcast(broadcaster); + FACTORY.createOrder(abi.encode(orderData), commonExecutionData, maxKeychainFees, OrderType.Advanced, salt); + + vm.stopBroadcast(); + } +} diff --git a/src/orders/script/Deploy.s.sol b/src/orders/script/Deploy.s.sol new file mode 100644 index 0000000..4fee6e0 --- /dev/null +++ b/src/orders/script/Deploy.s.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { Create2 } from "../src/Create2.sol"; +import { Script } from "forge-std/src/Script.sol"; +import { Registry } from "../src/Registry.sol"; +import { OrderFactory } from "../src/OrderFactory.sol"; +import { BasicOrderFactory } from "../src/BasicOrderFactory.sol"; +import { AdvancedOrderFactory } from "../src/AdvancedOrderFactory.sol"; + +contract Deploy is Script { + address internal broadcaster; + address internal scheduler; + address internal factoryOwner; + address internal create2Address; + address internal registryAddress; + + error InvalidScheduler(); + error InvalidFactory(); + error AddressMismatch(string name); + + constructor() { + (broadcaster,) = deriveRememberKey({ mnemonic: vm.envString("MNEMONIC"), index: 0 }); + scheduler = vm.envAddress("SCHEDULER_ADDRESS"); + factoryOwner = vm.envAddress("FACTORY_OWNER_ADDRESS"); + create2Address = vm.envOr("CREATE2_ADDRESS", address(0)); + registryAddress = vm.envOr("REGISTRY_ADDRESS", address(0)); + + if (scheduler == address(0)) revert InvalidScheduler(); + if (factoryOwner == address(0)) revert InvalidFactory(); + } + + function run() external { + vm.startBroadcast(broadcaster); + + bytes11 registrySaltValue = bytes11(vm.envOr("REGISTRY_SALT", bytes11(uint88(1001)))); + bytes11 factorySaltValue = bytes11(vm.envOr("FACTORY_SALT", bytes11(uint88(1002)))); + + if (registryAddress == address(0)) { + bytes32 registrySalt = bytes32(abi.encodePacked(broadcaster, hex"00", registrySaltValue)); + bytes memory registryInitCode = type(Registry).creationCode; + + registryAddress = deployWithCreate2(registrySalt, registryInitCode, "Registry"); + } + + bytes32 factorySalt = bytes32(abi.encodePacked(broadcaster, hex"00", factorySaltValue)); + + bytes memory basicFactoryInitCode = + abi.encodePacked(type(BasicOrderFactory).creationCode, abi.encode(registryAddress)); + + address basicFactoryAddress = deployWithCreate2(factorySalt, basicFactoryInitCode, "BasicOrder"); + + bytes memory advancedFactoryInitCode = + abi.encodePacked(type(AdvancedOrderFactory).creationCode, abi.encode(registryAddress)); + + address advancedFactoryAddress = deployWithCreate2(factorySalt, advancedFactoryInitCode, "AdvancedOrder"); + + bytes memory factoryInitCode = abi.encodePacked( + type(OrderFactory).creationCode, + abi.encode(registryAddress, scheduler, factoryOwner, basicFactoryAddress, advancedFactoryAddress) + ); + + address factoryAddress = deployWithCreate2(factorySalt, factoryInitCode, "OrderFactory"); + + vm.stopBroadcast(); + + string memory chainId = vm.envString("CHAIN_ID"); + string memory output = "output"; + string memory registryK = "registry"; + string memory factoryK = "orderFactory"; + vm.serializeString(output, registryK, vm.toString(registryAddress)); + string memory out = vm.serializeString(output, factoryK, vm.toString(factoryAddress)); + string memory path = string.concat("./broadcast/Deploy.s.sol/", chainId, "/latest.json"); + vm.writeJson(out, path); + } + + function deployWithCreate2(bytes32 salt, bytes memory initCode, string memory name) internal returns (address) { + Create2 create2; + if (create2Address == address(0)) { + create2 = new Create2(); + create2Address = address(create2); + } else { + create2 = Create2(create2Address); + } + + bytes32 initCodeHash = keccak256(initCode); + + address computedAddress = create2.computeAddress(salt, initCodeHash); + address deployedAddress = create2.deploy(salt, initCode); + + if (computedAddress != deployedAddress) revert AddressMismatch(name); + + return deployedAddress; + } +} diff --git a/src/orders/src/AbstractOrder.sol b/src/orders/src/AbstractOrder.sol new file mode 100644 index 0000000..b7b017c --- /dev/null +++ b/src/orders/src/AbstractOrder.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { BroadcastType, IWarden, IWARDEN_PRECOMPILE_ADDRESS, KeyResponse } from "../precompiles/warden/IWarden.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { RLPEncode } from "./RLPEncode.sol"; +import { Types } from "./Types.sol"; +import { ExecutionData } from "./IExecution.sol"; +import { Strings } from "./Strings.sol"; + +error InvalidScheduler(); +error InvalidRegistry(); +error InvalidExpectedApproveExpression(); +error InvalidExpectedRejectExpression(); +error InvalidTxTo(); + +abstract contract AbstractOrder { + using Strings for *; + + IWarden private immutable WARDEN_PRECOMPILE; + address private _keyAddress; + int32 private constant ETHEREUM_ADDRESS_TYPE = 1; + + constructor( + Types.SignRequestData memory signRequestData, + Types.CreatorDefinedTxFields memory creatorDefinedTxFields, + address scheduler, + address registry + ) { + if (scheduler == address(0)) { + revert InvalidScheduler(); + } + + if (registry == address(0)) { + revert InvalidRegistry(); + } + + if (bytes(signRequestData.expectedApproveExpression).length == 0) { + revert InvalidExpectedApproveExpression(); + } + + if (bytes(signRequestData.expectedRejectExpression).length == 0) { + revert InvalidExpectedRejectExpression(); + } + + if (creatorDefinedTxFields.to == address(0)) { + revert InvalidTxTo(); + } + + WARDEN_PRECOMPILE = IWarden(IWARDEN_PRECOMPILE_ADDRESS); + int32[] memory addressTypes = new int32[](1); + addressTypes[0] = ETHEREUM_ADDRESS_TYPE; + KeyResponse memory keyResponse = WARDEN_PRECOMPILE.keyById(signRequestData.keyId, addressTypes); + _keyAddress = keyResponse.addresses[0].addressValue.parseAddress(); + } + + function encodeUnsignedEIP1559( + uint256 nonce, + uint256 gas, + uint256 maxPriorityFeePerGas, + uint256 maxFeePerGas, + bytes[] calldata accessList, + Types.CreatorDefinedTxFields calldata creatorDefinedTxFields + ) + public + pure + returns (bytes memory unsignedTx, bytes32 txHash) + { + uint256 txType = 2; // eip1559 tx type + bytes[] memory txArray = new bytes[](9); + txArray[0] = RLPEncode.encodeUint(creatorDefinedTxFields.chainId); + txArray[1] = RLPEncode.encodeUint(nonce); + txArray[2] = RLPEncode.encodeUint(maxPriorityFeePerGas); + txArray[3] = RLPEncode.encodeUint(maxFeePerGas); + txArray[4] = RLPEncode.encodeUint(gas); + txArray[5] = RLPEncode.encodeAddress(creatorDefinedTxFields.to); + txArray[6] = RLPEncode.encodeUint(creatorDefinedTxFields.value); + txArray[7] = RLPEncode.encodeBytes(creatorDefinedTxFields.data); + txArray[8] = RLPEncode.encodeList(accessList); + bytes memory unsignedTxEncoded = RLPEncode.encodeList(txArray); + unsignedTx = RLPEncode.concat(RLPEncode.encodeUint(txType), unsignedTxEncoded); + txHash = keccak256(unsignedTx); + } + + function buildExecutionData(Types.CreatorDefinedTxFields calldata creatorDefinedTxFields) + public + view + returns (ExecutionData memory data) + { + data = ExecutionData({ + caller: _keyAddress, + to: creatorDefinedTxFields.to, + chainId: creatorDefinedTxFields.chainId, + value: creatorDefinedTxFields.value, + data: creatorDefinedTxFields.data + }); + } + + function createSignRequest( + Types.SignRequestData calldata signRequestData, + bytes calldata signRequestInput, + CommonTypes.Coin[] calldata maxKeychainFees + ) + public + returns (bool) + { + return WARDEN_PRECOMPILE.newSignRequest( + signRequestData.keyId, + signRequestInput, + signRequestData.analyzers, + signRequestData.encryptionKey, + maxKeychainFees, + signRequestData.spaceNonce, + signRequestData.actionTimeoutHeight, + signRequestData.expectedApproveExpression, + signRequestData.expectedRejectExpression, + BroadcastType.Automatic + ); + } +} diff --git a/src/orders/src/AdvancedOrder.sol b/src/orders/src/AdvancedOrder.sol new file mode 100644 index 0000000..0d88695 --- /dev/null +++ b/src/orders/src/AdvancedOrder.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.25 <0.9.0; + +import { GetPriceResponse, ISlinky, ISLINKY_PRECOMPILE_ADDRESS } from "../precompiles/slinky/ISlinky.sol"; +import { FutureByIdResponse, IAsync, IASYNC_PRECOMPILE_ADDRESS } from "../precompiles/async/IAsync.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { AbstractOrder } from "./AbstractOrder.sol"; +import { ExecutionData, IExecution } from "./IExecution.sol"; +import { Registry } from "./Registry.sol"; +import { Types } from "./Types.sol"; + +error ConditionNotMet(); +error ExecutedError(); +error Unauthorized(); + +event Executed(); + +struct PricePredictInput { + uint256 date; + string[] tokens; + uint64[2] falsePositiveRate; +} + +contract AdvancedOrder is AbstractOrder, IExecution { + Types.AdvancedOrderData public orderData; + Types.CommonExecutionData public commonExecutionData; + uint64 public futureId; + + uint256 public constant PRICE_PREDICTION_DECIMALS = 16; + + ISlinky private immutable SLINKY_PRECOMPILE = ISlinky(ISLINKY_PRECOMPILE_ADDRESS); + IAsync private immutable ASYNC_PRECOMPILE = IAsync(IASYNC_PRECOMPILE_ADDRESS); + Registry private immutable REGISTRY; + + CommonTypes.Coin[] private _coins; + bool private _executed; + address private _scheduler; + bytes private _unsignedTx; + uint256 private _validUntil; + + constructor( + Types.AdvancedOrderData memory _orderData, + Types.CommonExecutionData memory _executionData, + CommonTypes.Coin[] memory maxKeychainFees, + address scheduler, + address registry + ) + AbstractOrder(_executionData.signRequestData, _executionData.creatorDefinedTxFields, scheduler, registry) + { + string[] memory predictTokens = new string[](2); + predictTokens[0] = _orderData.predictPricePair.base; + predictTokens[1] = _orderData.predictPricePair.quote; + + uint64[2] memory falsePositiveRate = [uint64(1), uint64(100)]; + PricePredictInput memory pricePredictInput = PricePredictInput({ + date: _orderData.pricePredictDate, + tokens: predictTokens, + falsePositiveRate: falsePositiveRate + }); + futureId = ASYNC_PRECOMPILE.addFuture("pricepred", abi.encode(pricePredictInput)); + REGISTRY = Registry(registry); + + for (uint256 i = 0; i < maxKeychainFees.length; i++) { + _coins.push(maxKeychainFees[i]); + } + + orderData = _orderData; + commonExecutionData = _executionData; + _scheduler = scheduler; + _validUntil = block.timestamp + 24 hours; + } + + function canExecute() public view override returns (bool) { + if (block.timestamp > _validUntil) return false; + + FutureByIdResponse memory future = ASYNC_PRECOMPILE.futureById(futureId); + if (future.futureResponse.result.id == 0) return false; + + uint256[] memory predictedPrices = abi.decode(future.futureResponse.result.output, (uint256[])); + GetPriceResponse memory priceResponse = + SLINKY_PRECOMPILE.getPrice(orderData.oraclePricePair.base, orderData.oraclePricePair.quote); + + uint256 predictedPrice = _getPriceInQuote(predictedPrices[0], predictedPrices[1], PRICE_PREDICTION_DECIMALS); + (uint256 oracleNormalized, uint256 predictedNormalized) = _normalizePrices( + priceResponse.price.price, predictedPrice, priceResponse.decimals, PRICE_PREDICTION_DECIMALS + ); + + return _checkPriceCondition(oracleNormalized, predictedNormalized); + } + + function execute( + uint256 nonce, + uint256 gas, + uint256, + uint256 maxPriorityFeePerGas, + uint256 maxFeePerGas + ) + external + override + returns (bool, bytes32) + { + if (msg.sender != _scheduler) revert Unauthorized(); + if (_executed) revert ExecutedError(); + if (!canExecute()) revert ConditionNotMet(); + + bytes[] memory emptyAccessList = new bytes[](0); + (bytes memory unsignedTx, bytes32 txHash) = this.encodeUnsignedEIP1559( + nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, commonExecutionData.creatorDefinedTxFields + ); + + _unsignedTx = unsignedTx; + _executed = this.createSignRequest(commonExecutionData.signRequestData, abi.encodePacked(txHash), _coins); + + if (_executed) emit Executed(); + + // origin always creator of sign request + // solhint-disable-next-line + REGISTRY.addTransaction(tx.origin, txHash); + return (_executed, txHash); + } + + function isExecuted() public view override returns (bool) { + return _executed; + } + + function getTx() external view returns (bytes memory) { + if (!_executed) revert ExecutedError(); + return _unsignedTx; + } + + function executionData() external view returns (ExecutionData memory data) { + data = this.buildExecutionData(commonExecutionData.creatorDefinedTxFields); + } + + function _normalizePrices( + uint256 price1, + uint256 price2, + uint256 decimals1, + uint256 decimals2 + ) + internal + pure + returns (uint256 normalizedPrice1, uint256 normalizedPrice2) + { + uint256 maxDecimals = decimals1 > decimals2 ? decimals1 : decimals2; + normalizedPrice1 = price1 * (10 ** (maxDecimals - decimals1)); + normalizedPrice2 = price2 * (10 ** (maxDecimals - decimals2)); + } + + function _getPriceInQuote(uint256 priceA, uint256 priceB, uint256 decimals) internal pure returns (uint256) { + return (priceA * 10 ** decimals) / priceB; + } + + function _checkPriceCondition(uint256 oraclePrice, uint256 predictedPrice) internal view returns (bool) { + if ( + (orderData.priceCondition == Types.PriceCondition.GTE && oraclePrice >= predictedPrice) + || (orderData.priceCondition == Types.PriceCondition.LTE && oraclePrice <= predictedPrice) + || (orderData.priceCondition == Types.PriceCondition.GT && oraclePrice > predictedPrice) + || (orderData.priceCondition == Types.PriceCondition.LT && oraclePrice < predictedPrice) + ) { + return true; + } + return false; + } +} diff --git a/src/orders/src/AdvancedOrderFactory.sol b/src/orders/src/AdvancedOrderFactory.sol new file mode 100644 index 0000000..d6e82a9 --- /dev/null +++ b/src/orders/src/AdvancedOrderFactory.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { AdvancedOrder } from "./AdvancedOrder.sol"; +import { Types } from "./Types.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { Create3 } from "@0xsequence/create3/contracts/Create3.sol"; +import { Registry } from "./Registry.sol"; + +error OrderDeploymentFailed(bytes32 salt); +error SaltAlreadyUsed(); + +event SaltUsed(bytes32 indexed salt, address indexed creator); + +event AdvancedOrderCreated(address indexed creator, address orderAddress); + +contract AdvancedOrderFactory is ReentrancyGuard { + // Registry of IExecution contracts + Registry public immutable REGISTRY; + + // Mapping to track used salts to prevent reuse + mapping(bytes32 salt => bool used) public usedSalts; + + constructor(address registry) { + REGISTRY = Registry(registry); + } + + /** + * @dev Creates a new instance of the AdvancedOrder contract. + * @param orderData Data specific to the order. + * @param executionData Common execution data. + * @param maxKeychainFees Maximum fees for keychain operations. + * @param scheduler Address of the scheduler. + * @param salt Salt to ensure uniqueness of the deployed contract address. + * @return orderAddress Address of the newly created AdvancedOrder contract. + */ + function createAdvancedOrder( + Types.AdvancedOrderData calldata orderData, + Types.CommonExecutionData calldata executionData, + CommonTypes.Coin[] calldata maxKeychainFees, + address scheduler, + bytes32 salt + ) + external + nonReentrant + returns (address orderAddress) + { + // Front-running protection using tx.origin + // solhint-disable-next-line + address origin = tx.origin; + bytes32 guardedSalt = keccak256(abi.encodePacked(uint256(uint160(origin)), salt)); + + if (usedSalts[guardedSalt]) { + revert SaltAlreadyUsed(); + } + + emit SaltUsed(guardedSalt, origin); + + // Encode contract creation bytecode with constructor arguments + bytes memory bytecode = abi.encodePacked( + type(AdvancedOrder).creationCode, + abi.encode(orderData, executionData, maxKeychainFees, scheduler, address(REGISTRY)) + ); + + // Deploy the contract using Create3 + orderAddress = Create3.create3(guardedSalt, bytecode); + + address expectedAddress = Create3.addressOf(guardedSalt); + if (orderAddress == address(0) || orderAddress != expectedAddress) { + revert OrderDeploymentFailed(guardedSalt); + } + + // Register the deployed contract in the registry + REGISTRY.register(orderAddress); + usedSalts[guardedSalt] = true; + + emit AdvancedOrderCreated(msg.sender, orderAddress); + } + + /** + * @notice Computes the deterministic address of a order without deploying it + * @param origin The potential order creator + * @param salt The unique salt provided by the frontend + * @return The computed address of the order + */ + function computeOrderAddress(address origin, bytes32 salt) external view returns (address) { + // front-running protection + bytes32 guardedSalt = keccak256(abi.encodePacked(uint256(uint160(origin)), salt)); + + return Create3.addressOf(guardedSalt); + } +} diff --git a/src/orders/src/BasicOrder.sol b/src/orders/src/BasicOrder.sol new file mode 100644 index 0000000..29d8679 --- /dev/null +++ b/src/orders/src/BasicOrder.sol @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { GetPriceResponse, ISlinky, ISLINKY_PRECOMPILE_ADDRESS } from "../precompiles/slinky/ISlinky.sol"; +import { ExecutionData, IExecution } from "./IExecution.sol"; +import { AbstractOrder } from "./AbstractOrder.sol"; +import { Types } from "./Types.sol"; +import { Registry } from "./Registry.sol"; + +error ConditionNotMet(); +error ExecutedError(); +error Unauthorized(); +error InvalidPriceCondition(); +error InvalidThresholdPrice(); + +event Executed(); + +contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard { + Types.BasicOrderData public orderData; + Types.CommonExecutionData public commonExecutionData; + + ISlinky private immutable SLINKY_PRECOMPILE; + Registry private immutable REGISTRY; + CommonTypes.Coin[] private _coins; + bool private _executed; + address private _scheduler; + bytes private _unsignedTx; + + // solhint-disable-next-line + constructor( + Types.BasicOrderData memory _orderData, + Types.CommonExecutionData memory _executionData, + CommonTypes.Coin[] memory maxKeychainFees, + address scheduler, + address registry + ) + AbstractOrder(_executionData.signRequestData, _executionData.creatorDefinedTxFields, scheduler, registry) + { + if (_orderData.thresholdPrice == 0) { + revert InvalidThresholdPrice(); + } + + SLINKY_PRECOMPILE = ISlinky(ISLINKY_PRECOMPILE_ADDRESS); + SLINKY_PRECOMPILE.getPrice(_orderData.pricePair.base, _orderData.pricePair.quote); + + REGISTRY = Registry(registry); + + for (uint256 i = 0; i < maxKeychainFees.length; i++) { + _coins.push(maxKeychainFees[i]); + } + + orderData = _orderData; + commonExecutionData = _executionData; + _scheduler = scheduler; + } + + function canExecute() public view returns (bool value) { + GetPriceResponse memory priceResponse = + SLINKY_PRECOMPILE.getPrice(orderData.pricePair.base, orderData.pricePair.quote); + Types.PriceCondition condition = orderData.priceCondition; + if (condition == Types.PriceCondition.GTE) { + value = priceResponse.price.price >= orderData.thresholdPrice; + } else if (condition == Types.PriceCondition.LTE) { + value = priceResponse.price.price <= orderData.thresholdPrice; + } else { + revert InvalidPriceCondition(); + } + } + + function execute( + uint256 nonce, + uint256 gas, + uint256, + uint256 maxPriorityFeePerGas, + uint256 maxFeePerGas + ) + external + nonReentrant + returns (bool, bytes32) + { + if (msg.sender != _scheduler) { + revert Unauthorized(); + } + + if (isExecuted()) { + revert ExecutedError(); + } + + if (!canExecute()) { + revert ConditionNotMet(); + } + + bytes[] memory emptyAccessList = new bytes[](0); + (bytes memory unsignedTx, bytes32 txHash) = this.encodeUnsignedEIP1559( + nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, commonExecutionData.creatorDefinedTxFields + ); + + _unsignedTx = unsignedTx; + + bytes memory signRequestInput = abi.encodePacked(txHash); + + _executed = this.createSignRequest(commonExecutionData.signRequestData, signRequestInput, _coins); + + if (_executed) { + emit Executed(); + } + + // origin always creator of sign request + // solhint-disable-next-line + REGISTRY.addTransaction(tx.origin, txHash); + + return (_executed, txHash); + } + + function isExecuted() public view returns (bool) { + return _executed; + } + + function executionData() external view returns (ExecutionData memory data) { + data = this.buildExecutionData(commonExecutionData.creatorDefinedTxFields); + } + + function getTx() external view returns (bytes memory transaction) { + if (!isExecuted()) { + revert ExecutedError(); + } + + transaction = _unsignedTx; + } +} diff --git a/src/orders/src/BasicOrderFactory.sol b/src/orders/src/BasicOrderFactory.sol new file mode 100644 index 0000000..7268927 --- /dev/null +++ b/src/orders/src/BasicOrderFactory.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { BasicOrder } from "./BasicOrder.sol"; +import { Types } from "./Types.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { Create3 } from "@0xsequence/create3/contracts/Create3.sol"; +import { Registry } from "./Registry.sol"; + +error OrderDeploymentFailed(bytes32 salt); +error SaltAlreadyUsed(); + +event SaltUsed(bytes32 indexed salt, address indexed creator); + +contract BasicOrderFactory is ReentrancyGuard { + // Event emitted when a new BasicOrder is created + event BasicOrderCreated(address indexed creator, address orderAddress); + + // Registry of IExecution contracts + Registry public immutable REGISTRY; + + // Mapping to track used salts to prevent reuse + mapping(bytes32 salt => bool used) public usedSalts; + + constructor(address registry) { + REGISTRY = Registry(registry); + } + + /** + * @dev Creates a new instance of the BasicOrder contract. + * @param orderData Data specific to the order. + * @param executionData Common execution data. + * @param maxKeychainFees Maximum fees for keychain operations. + * @param scheduler Address of the scheduler. + * @return orderAddress Address of the newly created BasicOrder contract. + */ + function createBasicOrder( + Types.BasicOrderData calldata orderData, + Types.CommonExecutionData calldata executionData, + CommonTypes.Coin[] calldata maxKeychainFees, + address scheduler, + bytes32 salt + ) + external + nonReentrant + returns (address orderAddress) + { + // front-running protection + // we use tx.origin here as msg.sender the same for all orders created through factory + // solhint-disable-next-line + address origin = tx.origin; + bytes32 guardedSalt = keccak256(abi.encodePacked(uint256(uint160(origin)), salt)); + + if (usedSalts[guardedSalt]) { + revert SaltAlreadyUsed(); + } + + emit SaltUsed(guardedSalt, origin); + + bytes memory bytecode = abi.encodePacked( + type(BasicOrder).creationCode, + abi.encode(orderData, executionData, maxKeychainFees, scheduler, address(REGISTRY)) + ); + + orderAddress = Create3.create3(guardedSalt, bytecode); + address expectedAddress = Create3.addressOf(guardedSalt); + if (orderAddress == address(0) || orderAddress != expectedAddress) { + revert OrderDeploymentFailed(guardedSalt); + } + + REGISTRY.register(orderAddress); + usedSalts[guardedSalt] = true; + + emit BasicOrderCreated(msg.sender, orderAddress); + } + + /** + * @notice Computes the deterministic address of a order without deploying it + * @param origin The potential order creator + * @param salt The unique salt provided by the frontend + * @return The computed address of the order + */ + function computeOrderAddress(address origin, bytes32 salt) external view returns (address) { + // front-running protection + bytes32 guardedSalt = keccak256(abi.encodePacked(uint256(uint160(origin)), salt)); + + return Create3.addressOf(guardedSalt); + } +} diff --git a/src/orders/src/Create2.sol b/src/orders/src/Create2.sol new file mode 100644 index 0000000..274670f --- /dev/null +++ b/src/orders/src/Create2.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +// From https://book.getfoundry.sh/tutorials/create2-tutorial +contract Create2 { + error Create2EmptyBytecode(); + + error Create2FailedDeployment(); + + function deploy(bytes32 salt, bytes memory creationCode) external payable returns (address addr) { + if (creationCode.length == 0) { + revert Create2EmptyBytecode(); + } + + // solhint-disable-next-line + assembly { + addr := create2(callvalue(), add(creationCode, 0x20), mload(creationCode), salt) + } + + if (addr == address(0)) { + revert Create2FailedDeployment(); + } + } + + function computeAddress(bytes32 salt, bytes32 creationCodeHash) external view returns (address addr) { + address contractAddress = address(this); + + // solhint-disable-next-line + assembly { + let ptr := mload(0x40) + + mstore(add(ptr, 0x40), creationCodeHash) + mstore(add(ptr, 0x20), salt) + mstore(ptr, contractAddress) + let start := add(ptr, 0x0b) + mstore8(start, 0xff) + addr := keccak256(start, 85) + } + } +} diff --git a/src/orders/src/IExecution.sol b/src/orders/src/IExecution.sol new file mode 100644 index 0000000..3606a3a --- /dev/null +++ b/src/orders/src/IExecution.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +struct ExecutionData { + address caller; + address to; + uint256 chainId; + bytes data; + uint256 value; +} + +interface IExecution { + /** + * @dev Indicates if an order can be executed. + * @return A boolean value indicating that the order can be executed. + */ + function canExecute() external view returns (bool); + + /** + * @dev Creates action for new sign request from stored order data. + * If action created successfully then emit Executed event. + * @param nonce The key account nonce. + * @param gas gas parameter in eth transaction. + * @param gasPrice gasPrice parameter in eth transaction. + * @param maxPriorityFeePerGas maxPriorityFeePerGas parameter in eth transaction. + * @param maxFeePerGas maxFeePerGas parameter in eth transaction. + * @return A boolean value indicating parameter action was created and transaction hash. + */ + function execute( + uint256 nonce, + uint256 gas, + uint256 gasPrice, + uint256 maxPriorityFeePerGas, + uint256 maxFeePerGas + ) + external + returns (bool, bytes32); + + /** + * @dev Indicates if execution was executed already. + */ + function isExecuted() external returns (bool); + + /** + * @dev Returns data necessary for scheduler. + * @return executionData Data that scheduler needs to call execute method. + */ + function executionData() external returns (ExecutionData memory executionData); + + /** + * @dev Returns builded unsigned transaction. + * @return tx Unsigned transaction. + */ + function getTx() external returns (bytes memory tx); +} diff --git a/src/orders/src/OrderFactory.sol b/src/orders/src/OrderFactory.sol new file mode 100644 index 0000000..c77c4e3 --- /dev/null +++ b/src/orders/src/OrderFactory.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { Types } from "./Types.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { AdvancedOrderFactory } from "./AdvancedOrderFactory.sol"; +import { Registry } from "./Registry.sol"; +import { BasicOrderFactory } from "./BasicOrderFactory.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; + +enum OrderType { + Basic, + Advanced +} + +error Unimplemented(); +error UnsupportedOrder(); +error InvalidRegistryAddress(); +error InvalidSchedulerAddress(); +error OrderDeploymentFailed(bytes32 salt); +error SaltAlreadyUsed(); + +event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address indexed orderContract); + +event SchedulerChanged(address indexed oldScheduler, address indexed newScheduler); + +event SaltUsed(bytes32 indexed salt, address indexed creator); + +contract OrderFactory is Ownable, ReentrancyGuard { + // Mapping from order contract to order creator + mapping(address orderAddress => address orderCreator) public orders; + + // Registry of IExecution contracts + Registry public immutable REGISTRY; + + // BasicOrderFactory contract + BasicOrderFactory public immutable BASIC_ORDER_FACTORY; + + // AdvancedOrderFactory contract + AdvancedOrderFactory public immutable ADVANCED_ORDER_FACTORY; + + // Scheduler address + address public scheduler; + + constructor( + address registry, + address _scheduler, + address owner, + address basicOrderFactory, + address advancedOrderFactory + ) + Ownable(owner) + { + if (registry == address(0)) { + revert InvalidRegistryAddress(); + } + + if (_scheduler == address(0)) { + revert InvalidSchedulerAddress(); + } + + REGISTRY = Registry(registry); + BASIC_ORDER_FACTORY = BasicOrderFactory(basicOrderFactory); + ADVANCED_ORDER_FACTORY = AdvancedOrderFactory(advancedOrderFactory); + scheduler = _scheduler; + } + + /** + * @notice Computes the deterministic address of a order without deploying it + * @param origin The potential order creator + * @param salt The unique salt provided by the frontend + * @return order The computed address of the order + */ + function computeOrderAddress( + address origin, + bytes32 salt, + OrderType orderType + ) + external + view + returns (address order) + { + if (orderType == OrderType.Basic) { + order = BASIC_ORDER_FACTORY.computeOrderAddress(origin, salt); + } else if (orderType == OrderType.Advanced) { + order = ADVANCED_ORDER_FACTORY.computeOrderAddress(origin, salt); + } + } + + /** + * @notice Creates a new order (Basic or Advanced) using CREATE3 + * @param _orderData The data required to create the order + * @param maxKeychainFees The maximum fees allowed + * @param orderType The type of order to create + * @param salt The unique salt provided by the frontend + * @return order The address of the newly created order + */ + function createOrder( + bytes calldata _orderData, + Types.CommonExecutionData calldata _executionData, + CommonTypes.Coin[] calldata maxKeychainFees, + OrderType orderType, + bytes32 salt + ) + external + nonReentrant + returns (address order) + { + if (orderType == OrderType.Basic) { + Types.BasicOrderData memory basicOrderData = abi.decode(_orderData, (Types.BasicOrderData)); + order = _createBasicOrder(salt, basicOrderData, _executionData, maxKeychainFees, scheduler); + } else if (orderType == OrderType.Advanced) { + Types.AdvancedOrderData memory advancedOrderData = abi.decode(_orderData, (Types.AdvancedOrderData)); + order = _createAdvancedOrder(salt, advancedOrderData, _executionData, maxKeychainFees, scheduler); + } else { + revert UnsupportedOrder(); + } + } + + /** + * @notice Updates the scheduler address + * @param _scheduler The new scheduler address + */ + function setScheduler(address _scheduler) external onlyOwner { + if (_scheduler == address(0)) { + revert InvalidSchedulerAddress(); + } + address oldScheduler = scheduler; + scheduler = _scheduler; + emit SchedulerChanged(oldScheduler, scheduler); + } + + /** + * @notice Internal function to create a BasicOrder using CREATE3 + * @param salt The unique salt provided by the frontend + * @param _orderData The data required to create the order + * @param _executionData The data required for order execution + * @param maxKeychainFees The maximum fees allowed + * @param _scheduler The scheduler address + * @return The address of the newly created BasicOrder + */ + function _createBasicOrder( + bytes32 salt, + Types.BasicOrderData memory _orderData, + Types.CommonExecutionData calldata _executionData, + CommonTypes.Coin[] calldata maxKeychainFees, + address _scheduler + ) + internal + returns (address) + { + address orderAddress = + BASIC_ORDER_FACTORY.createBasicOrder(_orderData, _executionData, maxKeychainFees, _scheduler, salt); + + orders[orderAddress] = msg.sender; + + emit OrderCreated(msg.sender, OrderType.Basic, orderAddress); + + return orderAddress; + } + + /** + * @notice Internal function to create a AdvancedOrder using CREATE3 + * @param salt The unique salt provided by the frontend + * @param _orderData The data required to create the order + * @param _executionData The data required for order execution + * @param maxKeychainFees The maximum fees allowed + * @param _scheduler The scheduler address + * @return The address of the newly created AdvancedOrder + */ + function _createAdvancedOrder( + bytes32 salt, + Types.AdvancedOrderData memory _orderData, + Types.CommonExecutionData calldata _executionData, + CommonTypes.Coin[] calldata maxKeychainFees, + address _scheduler + ) + internal + returns (address) + { + address orderAddress = + ADVANCED_ORDER_FACTORY.createAdvancedOrder(_orderData, _executionData, maxKeychainFees, _scheduler, salt); + + orders[orderAddress] = msg.sender; + + emit OrderCreated(msg.sender, OrderType.Advanced, orderAddress); + + return orderAddress; + } +} diff --git a/src/orders/src/RLPEncode.sol b/src/orders/src/RLPEncode.sol new file mode 100644 index 0000000..a06697f --- /dev/null +++ b/src/orders/src/RLPEncode.sol @@ -0,0 +1,257 @@ +pragma solidity >=0.8.25 <0.9.0; + +// https://github.com/bakaoh/solidity-rlp-encode + +/** + * @title RLPEncode + * @dev A simple RLP encoding library. + * @author Bakaoh + */ +library RLPEncode { + /* + * Internal functions + */ + + /** + * @dev RLP encodes a byte string. + * @param self The byte string to encode. + * @return The RLP encoded string in bytes. + */ + function encodeBytes(bytes memory self) internal pure returns (bytes memory) { + bytes memory encoded; + if (self.length == 1 && uint8(self[0]) < 128) { + encoded = self; + } else { + encoded = concat(encodeLength(self.length, 128), self); + } + return encoded; + } + + /** + * @dev RLP encodes a list of RLP encoded byte byte strings. + * @param self The list of RLP encoded byte strings. + * @return The RLP encoded list of items in bytes. + */ + function encodeList(bytes[] memory self) internal pure returns (bytes memory) { + bytes memory list = flatten(self); + return concat(encodeLength(list.length, 192), list); + } + + /** + * @dev RLP encodes a string. + * @param self The string to encode. + * @return The RLP encoded string in bytes. + */ + function encodeString(string memory self) internal pure returns (bytes memory) { + return encodeBytes(bytes(self)); + } + + /** + * @dev RLP encodes an address. + * @param self The address to encode. + * @return The RLP encoded address in bytes. + */ + function encodeAddress(address self) internal pure returns (bytes memory) { + bytes memory inputBytes; + assembly { + let m := mload(0x40) + mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, self)) + mstore(0x40, add(m, 52)) + inputBytes := m + } + return encodeBytes(inputBytes); + } + + /** + * @dev RLP encodes a uint. + * @param self The uint to encode. + * @return The RLP encoded uint in bytes. + */ + function encodeUint(uint256 self) internal pure returns (bytes memory) { + return encodeBytes(toBinary(self)); + } + + /** + * @dev RLP encodes an int. + * @param self The int to encode. + * @return The RLP encoded int in bytes. + */ + function encodeInt(int256 self) internal pure returns (bytes memory) { + return encodeUint(uint256(self)); + } + + /** + * @dev RLP encodes a bool. + * @param self The bool to encode. + * @return The RLP encoded bool in bytes. + */ + function encodeBool(bool self) internal pure returns (bytes memory) { + bytes memory encoded = new bytes(1); + encoded[0] = (self ? bytes1(0x01) : bytes1(0x80)); + return encoded; + } + + /* + * Private functions + */ + + /** + * @dev Encode the first byte, followed by the `len` in binary form if `length` is more than 55. + * @param len The length of the string or the payload. + * @param offset 128 if item is string, 192 if item is list. + * @return RLP encoded bytes. + */ + function encodeLength(uint256 len, uint256 offset) private pure returns (bytes memory) { + bytes memory encoded; + if (len < 56) { + encoded = new bytes(1); + encoded[0] = bytes32(len + offset)[31]; + } else { + uint256 lenLen; + uint256 i = 1; + while (len / i != 0) { + lenLen++; + i *= 256; + } + + encoded = new bytes(lenLen + 1); + encoded[0] = bytes32(lenLen + offset + 55)[31]; + for (i = 1; i <= lenLen; i++) { + encoded[i] = bytes32((len / (256 ** (lenLen - i))) % 256)[31]; + } + } + return encoded; + } + + /** + * @dev Encode integer in big endian binary form with no leading zeroes. + * @notice TODO: This should be optimized with assembly to save gas costs. + * @param _x The integer to encode. + * @return RLP encoded bytes. + */ + function toBinary(uint256 _x) private pure returns (bytes memory) { + bytes memory b = new bytes(32); + assembly { + mstore(add(b, 32), _x) + } + uint256 i; + for (i = 0; i < 32; i++) { + if (b[i] != 0) { + break; + } + } + bytes memory res = new bytes(32 - i); + for (uint256 j = 0; j < res.length; j++) { + res[j] = b[i++]; + } + return res; + } + + /** + * @dev Copies a piece of memory to another location. + * @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol. + * @param _dest Destination location. + * @param _src Source location. + * @param _len Length of memory to copy. + */ + function memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure { + uint256 dest = _dest; + uint256 src = _src; + uint256 len = _len; + + for (; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + uint256 mask = 256 ** (32 - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + /** + * @dev Flattens a list of byte strings into one byte string. + * @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol. + * @param _list List of byte strings to flatten. + * @return The flattened byte string. + */ + function flatten(bytes[] memory _list) private pure returns (bytes memory) { + if (_list.length == 0) { + return new bytes(0); + } + + uint256 len; + uint256 i; + for (i = 0; i < _list.length; i++) { + require(_list[i].length > 0, "An item in the list to be RLP encoded is null."); + len += _list[i].length; + } + + bytes memory flattened = new bytes(len); + uint256 flattenedPtr; + assembly { + flattenedPtr := add(flattened, 0x20) + } + + for (i = 0; i < _list.length; i++) { + bytes memory item = _list[i]; + + uint256 listPtr; + assembly { + listPtr := add(item, 0x20) + } + + memcpy(flattenedPtr, listPtr, item.length); + flattenedPtr += _list[i].length; + } + + return flattened; + } + + /** + * @dev Concatenates two bytes. + * @notice From: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol. + * @param _preBytes First byte string. + * @param _postBytes Second byte string. + * @return Both byte string combined. + */ + function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) { + bytes memory tempBytes; + + assembly { + tempBytes := mload(0x40) + + let length := mload(_preBytes) + mstore(tempBytes, length) + + let mc := add(tempBytes, 0x20) + let end := add(mc, length) + + for { let cc := add(_preBytes, 0x20) } lt(mc, end) { + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { mstore(mc, mload(cc)) } + + length := mload(_postBytes) + mstore(tempBytes, add(length, mload(tempBytes))) + + mc := end + end := add(mc, length) + + for { let cc := add(_postBytes, 0x20) } lt(mc, end) { + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { mstore(mc, mload(cc)) } + + mstore(0x40, and(add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31))) + } + + return tempBytes; + } +} diff --git a/src/orders/src/Registry.sol b/src/orders/src/Registry.sol new file mode 100644 index 0000000..1a9729a --- /dev/null +++ b/src/orders/src/Registry.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import { IExecution } from "./IExecution.sol"; + +error InvalidExecutionAddress(); +error UnauthorizedToAddTx(); +error TxAlreadyAdded(); +error InvalidHash(); +error NotExecuted(); +error Executed(); +error ExecutionAlreadyRegistered(); +error BadCreatorAddress(); + +event Registered(address indexed creator, address indexed execution); + +event NewTx(address indexed execution, address indexed creator, bytes32 indexed txHash); + +contract Registry is ReentrancyGuard { + mapping(address executionAddress => address orderCreator) public executions; + mapping(address creator => mapping(bytes32 txHash => bytes tx)) public transactions; + + function register(address execution) public { + if (execution == address(0)) { + revert InvalidExecutionAddress(); + } + + if (executions[execution] != address(0)) { + revert ExecutionAlreadyRegistered(); + } + + try IExecution(execution).isExecuted() returns (bool executed) { + if (executed) { + revert Executed(); + } + } catch { + revert InvalidExecutionAddress(); + } + + executions[execution] = msg.sender; + emit Registered(msg.sender, execution); + } + + function addTransaction(address creator, bytes32 txHash) public nonReentrant { + if (creator == address(0)) { + revert BadCreatorAddress(); + } + + if (executions[msg.sender] == address(0)) { + revert UnauthorizedToAddTx(); + } + + if (txHash == bytes32(0)) { + revert InvalidHash(); + } + + if (transactions[creator][txHash].length != 0) { + revert TxAlreadyAdded(); + } + + IExecution execution = IExecution(msg.sender); + + try execution.isExecuted() returns (bool executed) { + if (!executed) { + revert NotExecuted(); + } + } catch { + revert InvalidExecutionAddress(); + } + + transactions[creator][txHash] = execution.getTx(); + + emit NewTx(msg.sender, creator, txHash); + } +} diff --git a/src/orders/src/Strings.sol b/src/orders/src/Strings.sol new file mode 100644 index 0000000..2669b6b --- /dev/null +++ b/src/orders/src/Strings.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol) + +pragma solidity >=0.8.25 <0.9.0; + +import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; + +/** + * @dev String operations. + */ +library Strings { + using SafeCast for *; + /** + * @dev The string being parsed is not a properly formatted address. + */ + + error StringsInvalidAddressFormat(); + + /** + * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. + * + * Requirements: + * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` + */ + function parseAddress(string memory input) internal pure returns (address) { + return parseAddress(input, 0, bytes(input).length); + } + + /** + * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and + * `end` (excluded). + * + * Requirements: + * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` + */ + function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { + (bool success, address value) = tryParseAddress(input, begin, end); + if (!success) revert StringsInvalidAddressFormat(); + return value; + } + + /** + * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is + * not a properly + * formatted address. See {parseAddress} requirements. + */ + function tryParseAddress( + string memory input, + uint256 begin, + uint256 end + ) + internal + pure + returns (bool success, address value) + { + // check that input is the correct length + bool hasPrefix = bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); + uint256 expectedLength = 40 + hasPrefix.toUint() * 2; + + if (end - begin == expectedLength) { + // length guarantees that this does not overflow, and value is at most type(uint160).max + (bool s, uint256 v) = tryParseHexUint(input, begin, end); + return (s, address(uint160(v))); + } else { + return (false, address(0)); + } + } + + /** + * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an + * invalid character. + * + * NOTE: This function will revert if the result does not fit in a `uint256`. + */ + function tryParseHexUint( + string memory input, + uint256 begin, + uint256 end + ) + internal + pure + returns (bool success, uint256 value) + { + bytes memory buffer = bytes(input); + + // skip 0x prefix if present + bool hasPrefix = bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); + uint256 offset = hasPrefix.toUint() * 2; + + uint256 result = 0; + for (uint256 i = begin + offset; i < end; ++i) { + uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); + if (chr > 15) return (false, 0); + result *= 16; + unchecked { + // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). + // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. + result += chr; + } + } + return (true, result); + } + + function _tryParseChr(bytes1 chr) private pure returns (uint8) { + uint8 value = uint8(chr); + + // Try to parse `chr`: + // - Case 1: [0-9] + // - Case 2: [a-f] + // - Case 3: [A-F] + // - otherwise not supported + unchecked { + if (value > 47 && value < 58) value -= 48; + else if (value > 96 && value < 103) value -= 87; + else if (value > 64 && value < 71) value -= 55; + else return type(uint8).max; + } + + return value; + } + + /** + * @dev Reads a bytes32 from a bytes array without bounds checking. + * + * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the + * assembly block as such would prevent some optimizations. + */ + function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { + // This is not memory safe in the general case, but all calls to this private function are within bounds. + // solhint-disable-next-line + assembly ("memory-safe") { + value := mload(add(buffer, add(0x20, offset))) + } + } +} diff --git a/src/orders/src/Types.sol b/src/orders/src/Types.sol new file mode 100644 index 0000000..0e483f2 --- /dev/null +++ b/src/orders/src/Types.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +library Types { + // Sign request data + struct SignRequestData { + uint64 keyId; + bytes[] analyzers; + bytes encryptionKey; + uint64 spaceNonce; + uint64 actionTimeoutHeight; + string expectedApproveExpression; + string expectedRejectExpression; + } + + enum PriceCondition { + LTE, + GTE, + LT, + GT + } + + // Data for basic order creation + struct BasicOrderData { + uint256 thresholdPrice; + PriceCondition priceCondition; + PricePair pricePair; + } + + // Data for advanced order creation + struct AdvancedOrderData { + // Which pair use to get price for oracle + PricePair oraclePricePair; + // Which pair use to get price for prediction handler + PricePair predictPricePair; + // Price condition for execution: should be executing if current price meets condition to prediced price + PriceCondition priceCondition; + // seconds timestamp + uint256 pricePredictDate; + } + + // Data for execution + struct CommonExecutionData { + CreatorDefinedTxFields creatorDefinedTxFields; + SignRequestData signRequestData; + } + + // Price pair for oracle/prediction requests + struct PricePair { + string base; + string quote; + } + + struct CreatorDefinedTxFields { + uint256 value; + uint256 chainId; + address to; + bytes data; + } +} diff --git a/src/orders/test/BasicOrder.t.sol b/src/orders/test/BasicOrder.t.sol new file mode 100644 index 0000000..c7ef11b --- /dev/null +++ b/src/orders/test/BasicOrder.t.sol @@ -0,0 +1,631 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { Test } from "forge-std/src/Test.sol"; +import { ISLINKY_PRECOMPILE_ADDRESS } from "../precompiles/slinky/ISlinky.sol"; +import { IWARDEN_PRECOMPILE_ADDRESS } from "../precompiles/warden/IWarden.sol"; +import { Types } from "../src/Types.sol"; +import { + OrderCreated, + OrderFactory, + OrderType, + InvalidRegistryAddress, + InvalidSchedulerAddress, + SchedulerChanged, + SaltAlreadyUsed +} from "../src/OrderFactory.sol"; +import { BasicOrderFactory } from "../src/BasicOrderFactory.sol"; +import { AdvancedOrderFactory } from "../src/AdvancedOrderFactory.sol"; +import { IExecution } from "../src/IExecution.sol"; +import { MockWardenPrecompile } from "../mocks/MockWardenPrecompile.sol"; +import { MockSlinkyPrecompile } from "../mocks/MockSlinkyPrecompile.sol"; +import { Types as CommonTypes } from "../precompiles/common/Types.sol"; +import { InvalidScheduler } from "../src/AbstractOrder.sol"; +import { BasicOrder, Executed, ConditionNotMet, ExecutedError, Unauthorized } from "../src/BasicOrder.sol"; +import { + BadCreatorAddress, + ExecutionAlreadyRegistered, + InvalidExecutionAddress, + NewTx, + Registry, + Registered, + UnauthorizedToAddTx, + NotExecuted, + TxAlreadyAdded, + InvalidHash +} from "../src/Registry.sol"; +import { Create3 } from "@0xsequence/create3/contracts/Create3.sol"; + +struct TestData { + Registry registry; + BasicOrderFactory basicOrderFactory; + AdvancedOrderFactory advancedOrderFactory; + OrderFactory orderFactory; + MockWardenPrecompile wardenPrecompile; + MockSlinkyPrecompile mockSlinkyPrecompile; + uint256 thresholdPrice; + Types.PricePair pricePair; + uint64 goodKeyId; + uint64 badKeyId; + address scheduler; +} + +contract BasicOrderTest is Test { + TestData private _testData; + Types.BasicOrderData private _orderData; + Types.CommonExecutionData private _executionData; + IExecution private _order; + bytes32 private _txHash; + + // @openzeppelin Ownable.sol + error OwnableUnauthorizedAccount(address account); + + address private constant SEPOLIA_UNISWAP_V2_ROUTER = address(uint160(0xeE567Fe1712Faf6149d80dA1E6934E354124CfE3)); + address private constant RECEIVER = address(uint160(0x18517Cb2779186B86b1F8947dFdB6078C1B9C9db)); + address private constant SEPOLIA_WETH = 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14; + address private constant SEPOLIA_TEST_TOKEN = 0xE5a71132Ae99691ef35F68459aDde842118A86a5; + + function beforeTestSetup(bytes4 testSelector) public pure returns (bytes[] memory beforeTestCalldata) { + if ( + testSelector == this.test_BasicOrder_StateBeforeExecution.selector + || testSelector == this.test_basicOrderRevertWhenConditionNotMet.selector + || testSelector == this.test_basicOrderRevertWhenUnauthorized.selector + || testSelector == this.test_basicOrderRevertGetTxWhenNotExecuted.selector + || testSelector == this.test_basicOrderExecuteWhenPriceMovesDown.selector + || testSelector == this.test_RegistryRevertAddTransactionWhenInvalidHash.selector + || testSelector == this.test_RegistryRevertAddTransactionWhenNotExecuted.selector + || testSelector == this.test_RegistryRevertWhenAlreadyRegistered.selector + ) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = + abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.LTE); + } else if (testSelector == this.test_basicOrderExecuteWhenPriceMovesUp.selector) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = + abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.GTE); + } else if (testSelector == this.test_RegistryRevertAddTransactionWhenAlreadyAdded.selector) { + beforeTestCalldata = new bytes[](2); + beforeTestCalldata[0] = + abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.GTE); + beforeTestCalldata[1] = abi.encodeWithSignature("test_basicOrderExecuteWhenPriceMovesUp()"); + } else if ( + testSelector == this.test_BasicOrderRevertWhenInvalidScheduler.selector + || testSelector == this.test_BasicOrderRevertWhenInvalidExpectedApproveExpression.selector + || testSelector == this.test_BasicOrderRevertWhenInvalidExpectedRejectExpression.selector + || testSelector == this.test_BasicOrderRevertWhenInvalidThresholdPrice.selector + || testSelector == this.test_BasicOrderRevertWhenInvalidTxTo.selector + ) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = abi.encodeWithSignature("saveOrderData()"); + } else if ( + testSelector == this.test_computeOrderAddressMatchesCreateOrder.selector + || testSelector == this.test_computeOrderAddressGuardedBySender.selector + ) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = + abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.LTE); + } else if (testSelector == this.test_computeOrderAddressBeforeDeployment.selector) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = abi.encodeWithSignature("saveOrderData()"); + } else if ( + testSelector == this.test_createOrderRevertsWithUsedSalt.selector + || testSelector == this.test_createOrderWithDifferentSenderCanUseSameSalt.selector + ) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = + abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.LTE); + } + } + + function setUp() public { + Registry registry = new Registry(); + address scheduler = address(this); + address owner = address(this); + BasicOrderFactory basicOrderFactory = new BasicOrderFactory(address(registry)); + AdvancedOrderFactory advancedOrderFactory = new AdvancedOrderFactory(address(registry)); + OrderFactory orderFactory = new OrderFactory( + address(registry), scheduler, owner, address(basicOrderFactory), address(advancedOrderFactory) + ); + + MockWardenPrecompile wPrecompile = new MockWardenPrecompile(); + vm.etch(IWARDEN_PRECOMPILE_ADDRESS, address(wPrecompile).code); + MockWardenPrecompile wardenPrecompile = MockWardenPrecompile(IWARDEN_PRECOMPILE_ADDRESS); + + MockSlinkyPrecompile mSlinkyPrecompile = new MockSlinkyPrecompile(); + vm.etch(ISLINKY_PRECOMPILE_ADDRESS, address(mSlinkyPrecompile).code); + MockSlinkyPrecompile mockSlinkyPrecompile = MockSlinkyPrecompile(ISLINKY_PRECOMPILE_ADDRESS); + + uint64 goodKeyId = 1; + uint64 badKeyId = 2; + wardenPrecompile.addKey(goodKeyId, true); + wardenPrecompile.addKey(badKeyId, false); + + _testData = TestData({ + registry: registry, + basicOrderFactory: basicOrderFactory, + advancedOrderFactory: advancedOrderFactory, + orderFactory: orderFactory, + wardenPrecompile: wardenPrecompile, + mockSlinkyPrecompile: mockSlinkyPrecompile, + thresholdPrice: 5, + pricePair: Types.PricePair({ base: "ETH", quote: "DOGE" }), + goodKeyId: goodKeyId, + badKeyId: badKeyId, + scheduler: scheduler + }); + + // Initialize _orderData with valid values + bytes[] memory analyzers; + _orderData = Types.BasicOrderData({ + thresholdPrice: _testData.thresholdPrice, + priceCondition: Types.PriceCondition.LTE, + pricePair: _testData.pricePair + }); + + _executionData = Types.CommonExecutionData({ + signRequestData: Types.SignRequestData({ + keyId: _testData.goodKeyId, + analyzers: analyzers, + encryptionKey: "", + spaceNonce: 0, + actionTimeoutHeight: 0, + expectedApproveExpression: "expectedApproveExpression", + expectedRejectExpression: "expectedRejectExpression" + }), + creatorDefinedTxFields: Types.CreatorDefinedTxFields({ + value: 0, + chainId: 11_155_111, + to: SEPOLIA_UNISWAP_V2_ROUTER, + data: getTestSwapData() + }) + }); + } + + function test_BasicOrder_Create(bool goodOrder, uint8 condition) public { + if (condition > 1) { + condition = 0; + } + + bytes[] memory analyzers; + bytes memory encryptionKey; + uint64 keyId; + if (goodOrder) { + keyId = _testData.goodKeyId; + } else { + keyId = _testData.badKeyId; + } + + Types.PriceCondition cond = Types.PriceCondition(condition); + if (cond == Types.PriceCondition.LTE) { + _testData.mockSlinkyPrecompile.setPrice( + _testData.pricePair.base, _testData.pricePair.quote, _testData.thresholdPrice + 1 + ); + } else { + _testData.mockSlinkyPrecompile.setPrice( + _testData.pricePair.base, _testData.pricePair.quote, _testData.thresholdPrice - 1 + ); + } + + bytes memory data = getTestSwapData(); + Types.BasicOrderData memory orderData = Types.BasicOrderData({ + thresholdPrice: _testData.thresholdPrice, + priceCondition: cond, + pricePair: _testData.pricePair + }); + Types.CommonExecutionData memory executionData = Types.CommonExecutionData({ + signRequestData: Types.SignRequestData({ + keyId: keyId, + analyzers: analyzers, + encryptionKey: encryptionKey, + spaceNonce: 0, + actionTimeoutHeight: 0, + expectedApproveExpression: "expectedApproveExpression", + expectedRejectExpression: "expectedRejectExpression" + }), + creatorDefinedTxFields: Types.CreatorDefinedTxFields({ + value: 0, + chainId: 11_155_111, + to: SEPOLIA_UNISWAP_V2_ROUTER, + data: data + }) + }); + bytes32 orderSalt = keccak256(abi.encodePacked(address(this), block.number, "ValidOrder")); + + CommonTypes.Coin[] memory maxKeychainFees; + + vm.expectEmit(true, false, false, false); + emit Registered(address(_testData.basicOrderFactory), address(this)); + + vm.expectEmit(true, true, false, false); + emit OrderCreated(address(this), OrderType.Basic, address(this)); + + address orderAddress = _testData.orderFactory.createOrder( + abi.encode(orderData), executionData, maxKeychainFees, OrderType.Basic, orderSalt + ); + + assertEq(address(_testData.basicOrderFactory), _testData.registry.executions(orderAddress)); + assertEq(address(this), _testData.orderFactory.orders(orderAddress)); + + _order = IExecution(orderAddress); + } + + function test_BasicOrder_StateBeforeExecution() public { + assert(!_order.canExecute()); + assert(!_order.isExecuted()); + } + + function test_basicOrderRevertWhenConditionNotMet() public { + assert(!_order.canExecute()); + assert(!_order.isExecuted()); + + vm.expectRevert(ConditionNotMet.selector); + _order.execute(1, 1, 1, 1, 1); + } + + function test_basicOrderRevertWhenUnauthorized() public { + vm.expectRevert(Unauthorized.selector); + vm.prank(address(0)); + _order.execute(1, 1, 1, 1, 1); + } + + function test_basicOrderRevertGetTxWhenNotExecuted() public { + vm.expectRevert(ExecutedError.selector); + _order.getTx(); + } + + function test_basicOrderExecuteWhenPriceMovesDown() public { + uint256 price = _testData.thresholdPrice - 1; + _testData.mockSlinkyPrecompile.setPrice(_testData.pricePair.base, _testData.pricePair.quote, price); + + assert(_order.canExecute()); + + vm.expectEmit(false, false, false, false); + emit Executed(); + + vm.expectEmit(true, true, false, false); + // solhint-disable-next-line + emit NewTx(address(_order), tx.origin, bytes32(0)); + + (bool executed, bytes32 txHash) = _order.execute(1, 1, 1, 1, 1); + // solhint-disable-next-line + assertEq(_testData.registry.transactions(tx.origin, txHash), _order.getTx()); + assert(executed); + + assert(_order.isExecuted()); + + vm.expectRevert(ExecutedError.selector); + _order.execute(1, 1, 1, 1, 1); + } + + function test_basicOrderExecuteWhenPriceMovesUp() public { + uint256 price = _testData.thresholdPrice + 1; + _testData.mockSlinkyPrecompile.setPrice(_testData.pricePair.base, _testData.pricePair.quote, price); + + assert(_order.canExecute()); + + vm.expectEmit(false, false, false, false); + emit Executed(); + + vm.expectEmit(true, true, false, false); + // solhint-disable-next-line + emit NewTx(address(_order), tx.origin, bytes32(0)); + + (bool executed, bytes32 txHash) = _order.execute(1, 1, 1, 1, 1); + // solhint-disable-next-line + assertEq(_testData.registry.transactions(tx.origin, txHash), _order.getTx()); + assert(executed); + + assert(_order.isExecuted()); + + vm.expectRevert(ExecutedError.selector); + _order.execute(1, 1, 1, 1, 1); + _txHash = txHash; + } + + function saveOrderData() public { + bytes[] memory analyzers; + bytes memory encryptionKey; + bytes memory data = getTestSwapData(); + Types.BasicOrderData memory orderData = Types.BasicOrderData({ + thresholdPrice: _testData.thresholdPrice, + priceCondition: Types.PriceCondition.LTE, + pricePair: _testData.pricePair + }); + + Types.CommonExecutionData memory executionData = Types.CommonExecutionData({ + signRequestData: Types.SignRequestData({ + keyId: _testData.goodKeyId, + analyzers: analyzers, + encryptionKey: encryptionKey, + spaceNonce: 0, + actionTimeoutHeight: 0, + expectedApproveExpression: "expectedApproveExpression", + expectedRejectExpression: "expectedRejectExpression" + }), + creatorDefinedTxFields: Types.CreatorDefinedTxFields({ + value: 0, + chainId: 11_155_111, + to: SEPOLIA_UNISWAP_V2_ROUTER, + data: data + }) + }); + + _orderData = orderData; + _executionData = executionData; + } + + function test_BasicOrderRevertWhenInvalidScheduler() public { + CommonTypes.Coin[] memory maxKeychainFees; + + vm.expectRevert(InvalidScheduler.selector); + + new BasicOrder(_orderData, _executionData, maxKeychainFees, address(0), address(_testData.registry)); + } + + function test_BasicOrderRevertWhenInvalidExpectedApproveExpression() public { + CommonTypes.Coin[] memory maxKeychainFees; + _executionData.signRequestData.expectedApproveExpression = ""; + vm.expectRevert(Create3.ErrorCreatingContract.selector); + + bytes32 orderSalt = keccak256(abi.encodePacked(address(this), block.number, "InvalidApproveExpression")); + _testData.orderFactory.createOrder( + abi.encode(_orderData), _executionData, maxKeychainFees, OrderType.Basic, orderSalt + ); + } + + function test_BasicOrderRevertWhenInvalidExpectedRejectExpression() public { + CommonTypes.Coin[] memory maxKeychainFees; + _executionData.signRequestData.expectedRejectExpression = ""; + vm.expectRevert(Create3.ErrorCreatingContract.selector); + + bytes32 orderSalt = keccak256(abi.encodePacked(address(this), block.number, "InvalidRejectExpression")); + _testData.orderFactory.createOrder( + abi.encode(_orderData), _executionData, maxKeychainFees, OrderType.Basic, orderSalt + ); + } + + function test_BasicOrderRevertWhenInvalidThresholdPrice() public { + CommonTypes.Coin[] memory maxKeychainFees; + _orderData.thresholdPrice = 0; + vm.expectRevert(Create3.ErrorCreatingContract.selector); + + bytes32 orderSalt = keccak256(abi.encodePacked(address(this), block.number, "InvalidThresholdPrice")); + _testData.orderFactory.createOrder( + abi.encode(_orderData), _executionData, maxKeychainFees, OrderType.Basic, orderSalt + ); + } + + function test_BasicOrderRevertWhenInvalidTxTo() public { + CommonTypes.Coin[] memory maxKeychainFees; + _executionData.creatorDefinedTxFields.to = address(0); + vm.expectRevert(Create3.ErrorCreatingContract.selector); + + bytes32 orderSalt = keccak256(abi.encodePacked(address(this), block.number, "InvalidTxTo")); + _testData.orderFactory.createOrder( + abi.encode(_orderData), _executionData, maxKeychainFees, OrderType.Basic, orderSalt + ); + } + + function test_FactoryConstructorRevertWhenInvalidRegistry() public { + vm.expectRevert(InvalidRegistryAddress.selector); + new OrderFactory(address(0), address(this), address(this), address(this), address(this)); + } + + function test_FactoryConstructorRevertWhenInvalidScheduler() public { + vm.expectRevert(InvalidSchedulerAddress.selector); + new OrderFactory(address(this), address(0), address(this), address(this), address(this)); + } + + function test_FactorySetScheduler() public { + OrderFactory factory = + new OrderFactory(address(this), address(this), address(this), address(this), address(this)); + + vm.expectEmit(true, true, false, false); + + emit SchedulerChanged(address(this), RECEIVER); + + factory.setScheduler(RECEIVER); + + assertEq(factory.scheduler(), RECEIVER); + } + + function test_FactoryRevertWhenSetSchedulerNotOwner() public { + OrderFactory factory = + new OrderFactory(address(this), address(this), address(this), address(this), address(this)); + + vm.expectRevert(abi.encodeWithSelector(OwnableUnauthorizedAccount.selector, RECEIVER)); + vm.prank(RECEIVER); + factory.setScheduler(RECEIVER); + + assertEq(factory.scheduler(), address(this)); + } + + function test_FactoryRevertWhenSetSchedulerInvalid() public { + OrderFactory factory = + new OrderFactory(address(this), address(this), address(this), address(this), address(this)); + + vm.expectRevert(InvalidSchedulerAddress.selector); + factory.setScheduler(address(0)); + + assertEq(factory.scheduler(), address(this)); + } + + function test_RegistryRevertWhenBadAddress() public { + vm.expectRevert(InvalidExecutionAddress.selector); + _testData.registry.register(address(0)); + } + + function test_RegistryRevertWhenAlreadyRegistered() public { + vm.expectRevert(ExecutionAlreadyRegistered.selector); + _testData.registry.register(address(_order)); + } + + function test_RegistryRevertAddTransactionWhenNotOrder() public { + vm.expectRevert(UnauthorizedToAddTx.selector); + // solhint-disable-next-line + _testData.registry.addTransaction(tx.origin, keccak256(bytes("test"))); + } + + function test_RegistryRevertAddTransactionWhenInvalidHash() public { + vm.expectRevert(InvalidHash.selector); + vm.prank(address(_order)); + // solhint-disable-next-line + _testData.registry.addTransaction(tx.origin, bytes32(0)); + } + + function test_RegistryRevertAddTransactionWhenAlreadyAdded() public { + vm.expectRevert(TxAlreadyAdded.selector); + vm.prank(address(_order)); + // solhint-disable-next-line + _testData.registry.addTransaction(tx.origin, _txHash); + } + + function test_RegistryRevertAddTransactionWhenNotExecuted() public { + vm.expectRevert(NotExecuted.selector); + vm.prank(address(_order)); + // solhint-disable-next-line + _testData.registry.addTransaction(tx.origin, keccak256(bytes("test"))); + } + + function test_RegistryRevertAddTransactionWhenBadCreatorAddress() public { + vm.expectRevert(BadCreatorAddress.selector); + vm.prank(address(_order)); + _testData.registry.addTransaction(address(0), keccak256(bytes("test"))); + } + + function test_computeOrderAddressMatchesCreateOrder() public { + bytes32 salt = keccak256(abi.encodePacked("unique_salt")); + + // Compute the expected order address + // solhint-disable-next-line + address computedAddress = _testData.orderFactory.computeOrderAddress(tx.origin, salt, OrderType.Basic); + + // Create the order + bytes memory orderData = abi.encode(_orderData); + Types.CommonExecutionData memory executionData = _executionData; + CommonTypes.Coin[] memory maxKeychainFees; + address orderAddress = + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + + // Assert that the computed address matches the deployed order address + assertEq(computedAddress, orderAddress, "Computed address does not match deployed order address"); + } + + function test_computeOrderAddressBeforeDeployment() public { + bytes32 salt = keccak256(abi.encodePacked("another_unique_salt")); + + // Ensure that the MockSlinkyPrecompile is set up properly + _testData.mockSlinkyPrecompile.setPrice( + _testData.pricePair.base, _testData.pricePair.quote, _testData.thresholdPrice + 1 + ); + + // Compute the expected order address before deployment + // solhint-disable-next-line + address computedAddress = _testData.orderFactory.computeOrderAddress(tx.origin, salt, OrderType.Basic); + + // Ensure that no contract is deployed at the computed address yet + assertEq(computedAddress.code.length, 0, "Order address should not be deployed yet"); + + // Create the order + bytes memory orderData = abi.encode(_orderData); + Types.CommonExecutionData memory executionData = _executionData; + CommonTypes.Coin[] memory maxKeychainFees; + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + + // Now, the contract should be deployed + assertEq(computedAddress.code.length > 0, true, "Order contract was not deployed at computed address"); + } + + function test_createOrderRevertsWithUsedSalt() public { + bytes32 salt = keccak256(abi.encodePacked("reused_salt")); + + // First creation should succeed + bytes memory orderData = abi.encode(_orderData); + Types.CommonExecutionData memory executionData = _executionData; + CommonTypes.Coin[] memory maxKeychainFees; + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + + // Expect revert when using the same salt again + vm.expectRevert(SaltAlreadyUsed.selector); + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + } + + function test_createOrderWithDifferentSenderCanUseSameSalt() public { + bytes32 salt = keccak256(abi.encodePacked("shared_salt")); + + // Create order with original sender + bytes memory orderData = abi.encode(_orderData); + Types.CommonExecutionData memory executionData = _executionData; + CommonTypes.Coin[] memory maxKeychainFees; + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + + // Change the caller to a different address + address newSender = address(0xBEEF); + vm.prank(address(this), newSender); + + // This should succeed because the salt is guarded by msg.sender + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + } + + function test_computeOrderAddressGuardedBySender() public { + bytes32 salt = keccak256(abi.encodePacked("guarded_salt")); + + // Compute order address with original sender + // solhint-disable-next-line + address computedAddressOriginal = _testData.orderFactory.computeOrderAddress(tx.origin, salt, OrderType.Basic); + + // Create order with original sender + bytes memory orderData = abi.encode(_orderData); + Types.CommonExecutionData memory executionData = _executionData; + CommonTypes.Coin[] memory maxKeychainFees; + address orderAddressOriginal = + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + + // Assert that the computed address matches the deployed address for original sender + assertEq( + computedAddressOriginal, + orderAddressOriginal, + "Computed address does not match deployed order address for original sender" + ); + + // Compute order address with a different sender + address differentSender = address(0xDEAD); + address computedAddressDifferent = + _testData.orderFactory.computeOrderAddress(differentSender, salt, OrderType.Basic); + + // Create order with different sender + vm.prank(address(this), differentSender); + address orderAddressDifferent = + _testData.orderFactory.createOrder(orderData, executionData, maxKeychainFees, OrderType.Basic, salt); + + // Assert that the computed address matches the deployed address for different sender + assertEq( + computedAddressDifferent, + orderAddressDifferent, + "Computed address does not match deployed order address for different sender" + ); + + // Ensure that the two order addresses are different + assertEq( + orderAddressOriginal == orderAddressDifferent, + false, + "Order addresses for different senders should not be the same" + ); + } + + function getTestSwapData() internal pure returns (bytes memory) { + // Encode Uniswap V2 swapExactTokensForTokens parameters + address[] memory path = new address[](2); + path[0] = SEPOLIA_WETH; + path[1] = SEPOLIA_TEST_TOKEN; + bytes4 functionSelector = + bytes4(keccak256(abi.encodePacked("swapExactETHForTokens(uint256,address[],address, uint256)"))); + return abi.encodeWithSelector( + functionSelector, + 1, // amountOutMin + path, + RECEIVER, + type(uint256).max // deadline + ); + } +} diff --git a/src/orders/test/Create2.t.sol b/src/orders/test/Create2.t.sol new file mode 100644 index 0000000..a024388 --- /dev/null +++ b/src/orders/test/Create2.t.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.25 <0.9.0; + +import { Test } from "forge-std/src/Test.sol"; +import { Create2 } from "../src/Create2.sol"; +import { Registry } from "../src/Registry.sol"; +import { OrderFactory } from "../src/OrderFactory.sol"; + +contract Create2Test is Test { + Create2 internal create2; + + function setUp() public { + create2 = new Create2(); + } + + function testDeterministicDeploy() public { + vm.deal(address(0x1), 100 ether); + + vm.startPrank(address(0x1)); + bytes32 salt = "12345"; + bytes32 wrongSalt = "123456"; + bytes memory creationCode = abi.encodePacked(type(Registry).creationCode); + + address computedAddress = create2.computeAddress(salt, keccak256(creationCode)); + address wrongComputedAddress = create2.computeAddress(wrongSalt, keccak256(creationCode)); + address deployedAddress = create2.deploy(salt, creationCode); + vm.stopPrank(); + + assertEq(computedAddress, deployedAddress); + assertNotEq(wrongComputedAddress, deployedAddress); + } + + function testDeterministicDeployWithConstructorArgs() public { + vm.deal(address(0x1), 100 ether); + + vm.startPrank(address(0x1)); + bytes32 salt = "12345"; + bytes memory creationCode = abi.encodePacked( + type(OrderFactory).creationCode, + abi.encode(address(0x2), address(0x3), address(0x4), address(0x6), address(0x7)) + ); + bytes memory wrongCreationCode = abi.encodePacked( + type(OrderFactory).creationCode, + abi.encode(address(0x5), address(0x3), address(0x4), address(0x6), address(0x7)) + ); + + address computedAddress = create2.computeAddress(salt, keccak256(creationCode)); + address wrongComputedAddress = create2.computeAddress(salt, keccak256(wrongCreationCode)); + address deployedAddress = create2.deploy(salt, creationCode); + vm.stopPrank(); + + assertEq(computedAddress, deployedAddress); + assertNotEq(wrongComputedAddress, deployedAddress); + } +}