From 16393ca8bfc0fcc84eaeb6ed50678f99c5283eb9 Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Wed, 30 Oct 2024 00:59:58 +0400 Subject: [PATCH 01/12] test(evm): statedb tests for race conditions within funtoken precompile (#2098) * test(evm): statedb tests for race conditions within funtoken precompile * chore: changelog update --- CHANGELOG.md | 1 + .../IFunToken.json | 2 +- .../TestERC20TransferThenPrecompileSend.json | 50 ++++ .../TestNativeSendThenPrecompileSend.json | 50 ++++ .../contracts/{FunToken.sol => IFunToken.sol} | 0 .../TestERC20TransferThenPrecompileSend.sol | 39 +++ .../TestNativeSendThenPrecompileSend.sol | 34 +++ x/evm/embeds/embeds.go | 28 +- x/evm/embeds/embeds_test.go | 2 + x/evm/keeper/funtoken_from_coin_test.go | 251 +++++++++++++++--- x/evm/precompile/funtoken.go | 2 +- 11 files changed, 418 insertions(+), 41 deletions(-) rename x/evm/embeds/artifacts/contracts/{FunToken.sol => IFunToken.sol}/IFunToken.json (93%) create mode 100644 x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json create mode 100644 x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json rename x/evm/embeds/contracts/{FunToken.sol => IFunToken.sol} (100%) create mode 100644 x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol create mode 100644 x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 821b29e13..41cf28c19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ consistent setup and dynamic gas calculations, addressing the following tickets. - [#2088](https://github.com/NibiruChain/nibiru/pull/2088) - refactor(evm): remove outdated comment and improper error message text - [#2089](https://github.com/NibiruChain/nibiru/pull/2089) - better handling of gas consumption within erc20 contract execution - [#2091](https://github.com/NibiruChain/nibiru/pull/2091) - feat(evm): add fun token creation fee validation +- [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb tests for race conditions within funtoken precompile #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/x/evm/embeds/artifacts/contracts/FunToken.sol/IFunToken.json b/x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json similarity index 93% rename from x/evm/embeds/artifacts/contracts/FunToken.sol/IFunToken.json rename to x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json index 9f006c50f..6fe6e838a 100644 --- a/x/evm/embeds/artifacts/contracts/FunToken.sol/IFunToken.json +++ b/x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json @@ -1,7 +1,7 @@ { "_format": "hh-sol-artifact-1", "contractName": "IFunToken", - "sourceName": "contracts/FunToken.sol", + "sourceName": "contracts/IFunToken.sol", "abi": [ { "inputs": [ diff --git a/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json b/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json new file mode 100644 index 000000000..234a7f943 --- /dev/null +++ b/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json @@ -0,0 +1,50 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestERC20TransferThenPrecompileSend", + "sourceName": "contracts/TestERC20TransferThenPrecompileSend.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "erc20_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "precompileRecipient", + "type": "string" + }, + { + "internalType": "uint256", + "name": "precompileAmount", + "type": "uint256" + } + ], + "name": "erc20TransferThenPrecompileSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610974380380610974833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b61085d806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212205d952e3358213844ef60215f35b3c3adb68dbc657522a8dd683eb1c5c0f64bfa64736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212205d952e3358213844ef60215f35b3c3adb68dbc657522a8dd683eb1c5c0f64bfa64736f6c63430008180033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json b/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json new file mode 100644 index 000000000..1d44a675c --- /dev/null +++ b/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json @@ -0,0 +1,50 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestNativeSendThenPrecompileSend", + "sourceName": "contracts/TestNativeSendThenPrecompileSend.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "erc20_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "nativeRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nativeAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "precompileRecipient", + "type": "string" + }, + { + "internalType": "uint256", + "name": "precompileAmount", + "type": "uint256" + } + ], + "name": "nativeSendThenPrecompileSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610877380380610877833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b610760806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea26469706673582212206bab9cbf21b89041a55ee0f768a9443ae5e5ebfde23fe8a91daf9d4b339427db64736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea26469706673582212206bab9cbf21b89041a55ee0f768a9443ae5e5ebfde23fe8a91daf9d4b339427db64736f6c63430008180033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/x/evm/embeds/contracts/FunToken.sol b/x/evm/embeds/contracts/IFunToken.sol similarity index 100% rename from x/evm/embeds/contracts/FunToken.sol rename to x/evm/embeds/contracts/IFunToken.sol diff --git a/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol b/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol new file mode 100644 index 000000000..b51d0367e --- /dev/null +++ b/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +// Uncomment this line to use console.log +// import "hardhat/console.sol"; +import "./IFunToken.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract TestERC20TransferThenPrecompileSend { + address erc20; + + constructor(address erc20_) { + erc20 = erc20_; + } + + function erc20TransferThenPrecompileSend( + address payable transferRecipient, + uint256 transferAmount, + string memory precompileRecipient, + uint256 precompileAmount + ) public { + require( + ERC20(erc20).transfer(transferRecipient, transferAmount), + "ERC-20 transfer failed" + ); + + (bool success, ) = FUNTOKEN_PRECOMPILE_ADDRESS.call( + abi.encodeWithSignature( + "bankSend(address,uint256,string)", + erc20, + uint256(precompileAmount), + precompileRecipient + ) + ); + + require(success, string.concat("Failed to call bankSend")); + } +} diff --git a/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol b/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol new file mode 100644 index 000000000..da9cb471b --- /dev/null +++ b/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import "./IFunToken.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +contract TestNativeSendThenPrecompileSend { + address erc20; + + constructor(address erc20_) { + erc20 = erc20_; + } + + function nativeSendThenPrecompileSend( + address payable nativeRecipient, + uint256 nativeAmount, + string memory precompileRecipient, + uint256 precompileAmount + ) public { + bool isSent = nativeRecipient.send(nativeAmount); + require(isSent, "Failed to send native token"); + + (bool success, ) = FUNTOKEN_PRECOMPILE_ADDRESS.call( + abi.encodeWithSignature( + "bankSend(address,uint256,string)", + erc20, + precompileAmount, + precompileRecipient + ) + ); + + require(success, string.concat("Failed to call precompile bankSend")); + } +} diff --git a/x/evm/embeds/embeds.go b/x/evm/embeds/embeds.go index 5ac65655d..12b0d981c 100644 --- a/x/evm/embeds/embeds.go +++ b/x/evm/embeds/embeds.go @@ -19,7 +19,7 @@ var ( erc20MinterContractJSON []byte //go:embed artifacts/contracts/IOracle.sol/IOracle.json oracleContractJSON []byte - //go:embed artifacts/contracts/FunToken.sol/IFunToken.json + //go:embed artifacts/contracts/IFunToken.sol/IFunToken.json funtokenPrecompileJSON []byte //go:embed artifacts/contracts/Wasm.sol/IWasm.json wasmPrecompileJSON []byte @@ -29,6 +29,10 @@ var ( testErc20MaliciousNameJson []byte //go:embed artifacts/contracts/TestERC20MaliciousTransfer.sol/TestERC20MaliciousTransfer.json testErc20MaliciousTransferJson []byte + //go:embed artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json + testERC20TransferThenPrecompileSendJson []byte + //go:embed artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json + testNativeSendThenPrecompileSendJson []byte ) var ( @@ -40,10 +44,10 @@ var ( } // SmartContract_Funtoken: Precompile contract interface for - // "FunToken.sol". This precompile enables transfers of ERC20 tokens + // "IFunToken.sol". This precompile enables transfers of ERC20 tokens // to non-EVM accounts. Only the ABI is used. SmartContract_FunToken = CompiledEvmContract{ - Name: "FunToken.sol", + Name: "IFunToken.sol", EmbedJSON: funtokenPrecompileJSON, } @@ -76,6 +80,22 @@ var ( Name: "TestERC20MaliciousTransfer.sol", EmbedJSON: testErc20MaliciousTransferJson, } + // SmartContract_TestNativeSendThenPrecompileSendJson is a test contract + // that performs two sends in a single call: a native nibi send and a precompile bankSend. + // It tests a race condition where the state DB commit + // may overwrite the state after the precompile execution, potentially causing a loss of funds. + SmartContract_TestNativeSendThenPrecompileSendJson = CompiledEvmContract{ + Name: "TestNativeSendThenPrecompileSend.sol", + EmbedJSON: testNativeSendThenPrecompileSendJson, + } + // SmartContract_TestERC20TransferThenPrecompileSend is a test contract + // that performs two sends in a single call: an erc20 token transfer and a precompile bankSend. + // It tests a race condition where the state DB commit + // may overwrite the state after the precompile execution, potentially causing an infinite token mint. + SmartContract_TestERC20TransferThenPrecompileSend = CompiledEvmContract{ + Name: "TestERC20TransferThenPrecompileSend.sol", + EmbedJSON: testERC20TransferThenPrecompileSendJson, + } ) func init() { @@ -86,6 +106,8 @@ func init() { SmartContract_TestERC20.MustLoad() SmartContract_TestERC20MaliciousName.MustLoad() SmartContract_TestERC20MaliciousTransfer.MustLoad() + SmartContract_TestNativeSendThenPrecompileSendJson.MustLoad() + SmartContract_TestERC20TransferThenPrecompileSend.MustLoad() } type CompiledEvmContract struct { diff --git a/x/evm/embeds/embeds_test.go b/x/evm/embeds/embeds_test.go index 586ff68b9..94f208dbb 100644 --- a/x/evm/embeds/embeds_test.go +++ b/x/evm/embeds/embeds_test.go @@ -16,5 +16,7 @@ func TestLoadContracts(t *testing.T) { embeds.SmartContract_TestERC20.MustLoad() embeds.SmartContract_TestERC20MaliciousName.MustLoad() embeds.SmartContract_TestERC20MaliciousTransfer.MustLoad() + embeds.SmartContract_TestNativeSendThenPrecompileSendJson.MustLoad() + embeds.SmartContract_TestERC20TransferThenPrecompileSend.MustLoad() }) } diff --git a/x/evm/keeper/funtoken_from_coin_test.go b/x/evm/keeper/funtoken_from_coin_test.go index 1f5e3a85a..3b4b17f7a 100644 --- a/x/evm/keeper/funtoken_from_coin_test.go +++ b/x/evm/keeper/funtoken_from_coin_test.go @@ -169,45 +169,13 @@ func (s *FunTokenFromCoinSuite) TestCreateFunTokenFromCoin() { func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { deps := evmtest.NewTestDeps() alice := evmtest.NewEthPrivAcc() - bankDenom := "unibi" + bankDenom := evm.EVMBankDenom - s.T().Log("Setup: Create a coin in the bank state") - deps.App.BankKeeper.SetDenomMetaData(deps.Ctx, bank.Metadata{ - DenomUnits: []*bank.DenomUnit{ - { - Denom: bankDenom, - Exponent: 0, - Aliases: nil, - }, - }, - Base: bankDenom, - Display: bankDenom, - Name: bankDenom, - Symbol: "TOKEN", - }) - - s.T().Log("Give the sender funds") - s.Require().NoError(testapp.FundAccount( - deps.App.BankKeeper, - deps.Ctx, - deps.Sender.NibiruAddr, - deps.EvmKeeper.FeeForCreateFunToken(deps.Ctx).Add(sdk.NewCoin(bankDenom, sdk.NewInt(100))), - )) - - s.T().Log("Create FunToken mapping and ERC20") - createFunTokenResp, err := deps.EvmKeeper.CreateFunToken( - sdk.WrapSDKContext(deps.Ctx), - &evm.MsgCreateFunToken{ - FromBankDenom: bankDenom, - Sender: deps.Sender.NibiruAddr.String(), - }, - ) - s.Require().NoError(err) - - funTokenErc20Addr := createFunTokenResp.FuntokenMapping.Erc20Addr + // Initial setup + funTokenErc20Addr := s.fundAndCreateFunToken(deps, 100) s.T().Log("Convert bank coin to erc-20") - _, err = deps.EvmKeeper.ConvertCoinToEvm( + _, err := deps.EvmKeeper.ConvertCoinToEvm( sdk.WrapSDKContext(deps.Ctx), &evm.MsgConvertCoinToEvm{ Sender: deps.Sender.NibiruAddr.String(), @@ -299,6 +267,217 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { s.Require().ErrorContains(err, "transfer amount exceeds balance") } +// TestNativeSendThenPrecompileSend +// 1. Creates a funtoken from coin. +// 2. Using the test contract, performs two sends in a single call: a native nibi send and a precompile bankSend. +// It tests a race condition where the state DB commit may overwrite the state after the precompile execution, +// potentially causing a loss of funds. +// +// INITIAL STATE: +// - Test contract funds: 10 NIBI, 10 WNIBI +// CONTRACT CALL: +// - Sends 10 NIBI natively and 10 WNIBI -> NIBI to Alice using precompile +// EXPECTED: +// - Test contract funds: 0 NIBI, 0 WNIBI +// - Alice: 20 NIBI +// - Module account: 0 NIBI escrowed +func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() { + deps := evmtest.NewTestDeps() + bankDenom := evm.EVMBankDenom + + // Initial setup + funTokenErc20Addr := s.fundAndCreateFunToken(deps, 10e6) + + s.T().Log("Deploy Test Contract") + deployResp, err := evmtest.DeployContract( + &deps, + embeds.SmartContract_TestNativeSendThenPrecompileSendJson, + funTokenErc20Addr.Address, + ) + s.Require().NoError(err) + + testContractAddr := deployResp.ContractAddr + testContractNibiAddr := eth.EthAddrToNibiruAddr(testContractAddr) + + s.T().Log("Give the test contract 10 NIBI (native)") + s.Require().NoError(testapp.FundAccount( + deps.App.BankKeeper, + deps.Ctx, + testContractNibiAddr, + sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(10e6)))), + ) + + s.T().Log("Convert bank coin to erc-20: give test contract 10 WNIBI (erc20)") + _, err = deps.EvmKeeper.ConvertCoinToEvm( + sdk.WrapSDKContext(deps.Ctx), + &evm.MsgConvertCoinToEvm{ + Sender: deps.Sender.NibiruAddr.String(), + BankCoin: sdk.NewCoin(bankDenom, sdk.NewInt(10e6)), + ToEthAddr: eth.EIP55Addr{Address: testContractAddr}, + }, + ) + s.Require().NoError(err) + + // Alice hex and Alice bech32 is the same address in different representation, + // so funds are expected to be available in Alice's bank wallet + alice := evmtest.NewEthPrivAcc() + + s.T().Log("call test contract") + _, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_TestNativeSendThenPrecompileSendJson.ABI, + deps.Sender.EthAddr, + &testContractAddr, + true, + "nativeSendThenPrecompileSend", + alice.EthAddr, + evm.NativeToWei(big.NewInt(10e6)), // for native evm send: 18 decimals + alice.NibiruAddr.String(), + big.NewInt(10e6), // for precompile bankSend: 6 decimals + ) + s.Require().NoError(err) + + // Check 1: Alice has 20 NIBI in bank + aliceBankBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, alice.NibiruAddr, bankDenom) + s.Require().Equal(sdk.NewInt(20e6), aliceBankBalance.Amount) + + // Check 2: Alice has 0 WNIBI on ERC20 + aliceERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, alice.EthAddr, deps.Ctx) + s.Require().NoError(err) + s.Require().Zero(big.NewInt(0).Cmp(aliceERC20Balance)) + + // Check 3: test contract has 0 NIBI in bank + testContractBankBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, testContractNibiAddr, bankDenom) + s.Require().Equal(sdk.NewInt(0), testContractBankBalance.Amount) + + // Check 4: test contract has 0 WNIBI on ERC20 + testContractERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, testContractAddr, deps.Ctx) + s.Require().NoError(err) + s.Require().Zero(big.NewInt(0).Cmp(testContractERC20Balance)) + + // Check 5: module balance has 0 NIBI escrowed + moduleBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, authtypes.NewModuleAddress(evm.ModuleName), bankDenom) + s.Require().Equal(sdk.NewInt(0), moduleBalance.Amount) +} + +// TestERC20TransferThenPrecompileSend +// 1. Creates a funtoken from coin. +// 2. Using the test contract, performs two sends in a single call: a erc20 transfer and a precompile bankSend. +// It tests a race condition where the state DB commit may overwrite the state after the precompile execution, +// potentially causing an infinite minting of funds. +// +// INITIAL STATE: +// - Test contract funds: 10 WNIBI +// CONTRACT CALL: +// - Sends 1 WNIBI to Alice using erc20 transfer and 9 WNIBI -> NIBI to Alice using precompile +// EXPECTED: +// - Test contract funds: 0 WNIBI +// - Alice: 1 WNIBI, 9 NIBI +// - Module account: 1 NIBI escrowed (which Alice holds as 1 WNIBI) +func (s *FunTokenFromCoinSuite) TestERC20TransferThenPrecompileSend() { + deps := evmtest.NewTestDeps() + bankDenom := evm.EVMBankDenom + + // Initial setup + funTokenErc20Addr := s.fundAndCreateFunToken(deps, 10e6) + + s.T().Log("Deploy Test Contract") + deployResp, err := evmtest.DeployContract( + &deps, + embeds.SmartContract_TestERC20TransferThenPrecompileSend, + funTokenErc20Addr.Address, + ) + s.Require().NoError(err) + + testContractAddr := deployResp.ContractAddr + + s.T().Log("Convert bank coin to erc-20: give test contract 10 WNIBI (erc20)") + _, err = deps.EvmKeeper.ConvertCoinToEvm( + sdk.WrapSDKContext(deps.Ctx), + &evm.MsgConvertCoinToEvm{ + Sender: deps.Sender.NibiruAddr.String(), + BankCoin: sdk.NewCoin(bankDenom, sdk.NewInt(10e6)), + ToEthAddr: eth.EIP55Addr{Address: testContractAddr}, + }, + ) + s.Require().NoError(err) + + // Alice hex and Alice bech32 is the same address in different representation + alice := evmtest.NewEthPrivAcc() + + s.T().Log("call test contract") + _, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_TestERC20TransferThenPrecompileSend.ABI, + deps.Sender.EthAddr, + &testContractAddr, + true, + "erc20TransferThenPrecompileSend", + alice.EthAddr, + big.NewInt(1e6), // erc20 created with 6 decimals + alice.NibiruAddr.String(), + big.NewInt(9e6), // for precompile bankSend: 6 decimals + ) + s.Require().NoError(err) + + // Check 1: Alice has 9 NIBI in bank + aliceBankBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, alice.NibiruAddr, bankDenom) + s.Require().Equal(sdk.NewInt(9e6), aliceBankBalance.Amount) + + // Check 2: Alice has 1 WNIBI on ERC20 + aliceERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, alice.EthAddr, deps.Ctx) + s.Require().NoError(err) + s.Require().Zero(big.NewInt(1e6).Cmp(aliceERC20Balance)) + + // Check 3: test contract has 0 WNIBI on ERC20 + testContractERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, testContractAddr, deps.Ctx) + s.Require().NoError(err) + s.Require().Zero(big.NewInt(0).Cmp(testContractERC20Balance)) + + // Check 4: module balance has 1 NIBI escrowed (which Alice holds as 1 WNIBI) + moduleBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, authtypes.NewModuleAddress(evm.ModuleName), bankDenom) + s.Require().Equal(sdk.NewInt(1e6), moduleBalance.Amount) +} + +// fundAndCreateFunToken creates initial setup for tests +func (s *FunTokenFromCoinSuite) fundAndCreateFunToken(deps evmtest.TestDeps, unibiAmount int64) eth.EIP55Addr { + bankDenom := evm.EVMBankDenom + + s.T().Log("Setup: Create a coin in the bank state") + deps.App.BankKeeper.SetDenomMetaData(deps.Ctx, bank.Metadata{ + DenomUnits: []*bank.DenomUnit{ + { + Denom: bankDenom, + Exponent: 0, + Aliases: nil, + }, + }, + Base: bankDenom, + Display: bankDenom, + Name: bankDenom, + Symbol: "NIBI", + }) + + s.T().Log("Give the sender funds for funtoken creation and funding test contract") + s.Require().NoError(testapp.FundAccount( + deps.App.BankKeeper, + deps.Ctx, + deps.Sender.NibiruAddr, + deps.EvmKeeper.FeeForCreateFunToken(deps.Ctx).Add(sdk.NewCoin(bankDenom, sdk.NewInt(unibiAmount))), + )) + + s.T().Log("Create FunToken from coin") + createFunTokenResp, err := deps.EvmKeeper.CreateFunToken( + sdk.WrapSDKContext(deps.Ctx), + &evm.MsgCreateFunToken{ + FromBankDenom: bankDenom, + Sender: deps.Sender.NibiruAddr.String(), + }, + ) + s.Require().NoError(err) + return createFunTokenResp.FuntokenMapping.Erc20Addr +} + type FunTokenFromCoinSuite struct { suite.Suite } diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index 5c585c2e9..a937d111f 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -23,7 +23,7 @@ import ( var _ vm.PrecompiledContract = (*precompileFunToken)(nil) -// Precompile address for "FunToken.sol", the contract that +// Precompile address for "IFunToken.sol", the contract that // enables transfers of ERC20 tokens to "nibi" addresses as bank coins // using the ERC20's `FunToken` mapping. var PrecompileAddr_FunToken = gethcommon.HexToAddress("0x0000000000000000000000000000000000000800") From f3cbcaec58f23c54f6b75204b0c4009856b47250 Mon Sep 17 00:00:00 2001 From: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:19:03 -0500 Subject: [PATCH 02/12] fix(evm): StateDB multistore cache for precompile reversion and a safer Nibiru bank keeper that respects the EVM (#2094) * statedb: add cacheing for multistore before precompile runs * messy, working first version that allows for precompile reversion * wip!: Save checkpoint. 1. Created NibiruBankKeeper with safety around NIBI transfers inside of EthereumTx. 2. The "PrecompileCalled" JournalChange now has a propery implementation and a strong test case to show that reverting the precompile calls works as intended. 3. Remove unneeded functions created for testing with low-level struct fields. * chore: changelog * finalize bank keeper changes * revert to previous commit 7f904a07ac4d5555d8c088411024fc50ff65d085 * fix strange ignored file issue * remove new bank keeper * chore: comments from self-review --- CHANGELOG.md | 9 ++ app/keepers.go | 7 +- go.mod | 3 + go.sum | 8 +- x/evm/deps.go | 13 -- x/evm/evmtest/test_deps.go | 3 +- x/evm/evmtest/tx.go | 203 ++++++++++++++++++-------------- x/evm/keeper/erc20.go | 6 +- x/evm/keeper/keeper.go | 6 +- x/evm/keeper/msg_server.go | 2 +- x/evm/keeper/precompiles.go | 4 + x/evm/keeper/statedb.go | 12 +- x/evm/precompile/funtoken.go | 3 +- x/evm/precompile/precompile.go | 15 ++- x/evm/precompile/test/export.go | 65 +++++++++- x/evm/precompile/wasm.go | 4 +- x/evm/precompile/wasm_test.go | 4 +- x/evm/statedb/access_list.go | 4 +- x/evm/statedb/config.go | 3 +- x/evm/statedb/debug.go | 39 ++++++ x/evm/statedb/interfaces.go | 16 +-- x/evm/statedb/journal.go | 68 +++++++---- x/evm/statedb/journal_test.go | 130 +++++++++++++++----- x/evm/statedb/state_object.go | 7 +- x/evm/statedb/statedb.go | 152 ++++++++++++++++++++---- 25 files changed, 563 insertions(+), 223 deletions(-) create mode 100644 x/evm/statedb/debug.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cf28c19..c99138718 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,15 @@ consistent setup and dynamic gas calculations, addressing the following tickets. - [#2088](https://github.com/NibiruChain/nibiru/pull/2088) - refactor(evm): remove outdated comment and improper error message text - [#2089](https://github.com/NibiruChain/nibiru/pull/2089) - better handling of gas consumption within erc20 contract execution - [#2091](https://github.com/NibiruChain/nibiru/pull/2091) - feat(evm): add fun token creation fee validation +- [#2094](https://github.com/NibiruChain/nibiru/pull/2094) - fix(evm): Following +from the changs in #2086, this pull request implements a new `JournalChange` +struct that saves a deep copy of the state multi store before each +state-modifying, Nibiru-specific precompiled contract is called (`OnRunStart`). +Additionally, we commit the `StateDB` there as well. This guarantees that the +non-EVM and EVM state will be in sync even if there are complex, multi-step +Ethereum transactions, such as in the case of an EthereumTx that influences the +`StateDB`, then calls a precompile that also changes non-EVM state, and then EVM +reverts inside of a try-catch. - [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb tests for race conditions within funtoken precompile #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/app/keepers.go b/app/keepers.go index 6695a6194..4c5721e83 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -140,6 +140,7 @@ type AppKeepers struct { } type privateKeepers struct { + bankBaseKeeper bankkeeper.BaseKeeper capabilityKeeper *capabilitykeeper.Keeper slashingKeeper slashingkeeper.Keeper crisisKeeper crisiskeeper.Keeper @@ -262,13 +263,15 @@ func (app *NibiruApp) InitKeepers( sdk.GetConfig().GetBech32AccountAddrPrefix(), govModuleAddr, ) - app.BankKeeper = bankkeeper.NewBaseKeeper( + + app.bankBaseKeeper = bankkeeper.NewBaseKeeper( appCodec, keys[banktypes.StoreKey], app.AccountKeeper, BlockedAddresses(), govModuleAddr, ) + app.BankKeeper = app.bankBaseKeeper app.StakingKeeper = stakingkeeper.NewKeeper( appCodec, keys[stakingtypes.StoreKey], @@ -605,7 +608,7 @@ func (app *NibiruApp) initAppModules( ), auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), + bank.NewAppModule(appCodec, app.bankBaseKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), capability.NewAppModule(appCodec, *app.capabilityKeeper, false), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), diff --git a/go.mod b/go.mod index 158dc9b80..bc14078f3 100644 --- a/go.mod +++ b/go.mod @@ -244,6 +244,9 @@ require ( replace ( cosmossdk.io/api => cosmossdk.io/api v0.3.1 + github.com/CosmWasm/wasmd => github.com/NibiruChain/wasmd v0.44.0-nibiru + github.com/cosmos/cosmos-sdk => github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru + github.com/cosmos/iavl => github.com/cosmos/iavl v0.20.0 github.com/ethereum/go-ethereum => github.com/NibiruChain/go-ethereum v1.10.27-nibiru diff --git a/go.sum b/go.sum index 2c789f74f..213ee9c84 100644 --- a/go.sum +++ b/go.sum @@ -221,8 +221,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= -github.com/CosmWasm/wasmd v0.44.0 h1:2sbcoCAvfjCs1O0SWt53xULKjkV06dbSFthEViIC6Zg= -github.com/CosmWasm/wasmd v0.44.0/go.mod h1:tDyYN050qUcdd7LOxGeo2e185sEShyO3nJGl2Cf59+k= github.com/CosmWasm/wasmvm v1.5.5 h1:XlZI3xO5iUhiBqMiyzsrWEfUtk5gcBMNYIdHnsTB+NI= github.com/CosmWasm/wasmvm v1.5.5/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -237,8 +235,12 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NibiruChain/collections v0.5.0 h1:33pXpVTe1PK/tfdZlAJF1JF7AdzGNARG+iL9G/z3X7k= github.com/NibiruChain/collections v0.5.0/go.mod h1:43L6yjuF0BMre/mw4gqn/kUOZz1c2Y3huZ/RQfBFrOQ= +github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru h1:PgFpxDe+7+OzWHs4zXlml5j2i9sGq2Zpd3ndYQG29/0= +github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/NibiruChain/go-ethereum v1.10.27-nibiru h1:o6lRFt57izoYwzN5cG8tnnBtJcaO3X7MjjN7PGGNCFg= github.com/NibiruChain/go-ethereum v1.10.27-nibiru/go.mod h1:kvvL3nDceUcB+1qGUBAsVf5dW23RBR77fqxgx2PGNrQ= +github.com/NibiruChain/wasmd v0.44.0-nibiru h1:b+stNdbMFsl0+o4KedXyF83qRnEpB/jCiTGZZgv2h2U= +github.com/NibiruChain/wasmd v0.44.0-nibiru/go.mod h1:inrbdsixQ0Kdu4mFUg1u7fn3XPOEkzqieGv0H/gR0ck= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -426,8 +428,6 @@ github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAK github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.47.11 h1:0Qx7eORw0RJqPv+mvDuU8NQ1LV3nJJKJnPoYblWHolc= -github.com/cosmos/cosmos-sdk v0.47.11/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= diff --git a/x/evm/deps.go b/x/evm/deps.go index 04327db06..2325def18 100644 --- a/x/evm/deps.go +++ b/x/evm/deps.go @@ -4,7 +4,6 @@ package evm import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bank "github.com/cosmos/cosmos-sdk/x/bank/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -32,18 +31,6 @@ type AccountKeeper interface { SetModuleAccount(ctx sdk.Context, macc authtypes.ModuleAccountI) } -// BankKeeper defines the expected interface needed to retrieve account balances. -type BankKeeper interface { - authtypes.BankKeeper - GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin - SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error - MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error - BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error - - GetDenomMetaData(ctx sdk.Context, denom string) (metadata bank.Metadata, isFound bool) - SetDenomMetaData(ctx sdk.Context, denomMetaData bank.Metadata) -} - // StakingKeeper returns the historical headers kept in store. type StakingKeeper interface { GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool) diff --git a/x/evm/evmtest/test_deps.go b/x/evm/evmtest/test_deps.go index 1810b1c8f..44fb34c31 100644 --- a/x/evm/evmtest/test_deps.go +++ b/x/evm/evmtest/test_deps.go @@ -46,7 +46,8 @@ func NewTestDeps() TestDeps { } func (deps TestDeps) StateDB() *statedb.StateDB { - return statedb.New(deps.Ctx, &deps.App.EvmKeeper, + return deps.EvmKeeper.NewStateDB( + deps.Ctx, statedb.NewEmptyTxConfig( gethcommon.BytesToHash(deps.Ctx.HeaderHash().Bytes()), ), diff --git a/x/evm/evmtest/tx.go b/x/evm/evmtest/tx.go index dde679851..6b876f16d 100644 --- a/x/evm/evmtest/tx.go +++ b/x/evm/evmtest/tx.go @@ -26,95 +26,6 @@ import ( "github.com/NibiruChain/nibiru/v2/x/evm/embeds" ) -type GethTxType = uint8 - -func TxTemplateAccessListTx() *gethcore.AccessListTx { - return &gethcore.AccessListTx{ - GasPrice: big.NewInt(1), - Gas: gethparams.TxGas, - To: &gethcommon.Address{}, - Value: big.NewInt(0), - Data: []byte{}, - } -} - -func TxTemplateLegacyTx() *gethcore.LegacyTx { - return &gethcore.LegacyTx{ - GasPrice: big.NewInt(1), - Gas: gethparams.TxGas, - To: &gethcommon.Address{}, - Value: big.NewInt(0), - Data: []byte{}, - } -} - -func TxTemplateDynamicFeeTx() *gethcore.DynamicFeeTx { - return &gethcore.DynamicFeeTx{ - GasFeeCap: big.NewInt(10), - GasTipCap: big.NewInt(2), - Gas: gethparams.TxGas, - To: &gethcommon.Address{}, - Value: big.NewInt(0), - Data: []byte{}, - } -} - -func NewEthTxMsgFromTxData( - deps *TestDeps, - txType GethTxType, - innerTxData []byte, - nonce uint64, - to *gethcommon.Address, - value *big.Int, - gas uint64, - accessList gethcore.AccessList, -) (*evm.MsgEthereumTx, error) { - if innerTxData == nil { - innerTxData = []byte{} - } - - var ethCoreTx *gethcore.Transaction - switch txType { - case gethcore.LegacyTxType: - innerTx := TxTemplateLegacyTx() - innerTx.Nonce = nonce - innerTx.Data = innerTxData - innerTx.To = to - innerTx.Value = value - innerTx.Gas = gas - ethCoreTx = gethcore.NewTx(innerTx) - case gethcore.AccessListTxType: - innerTx := TxTemplateAccessListTx() - innerTx.Nonce = nonce - innerTx.Data = innerTxData - innerTx.AccessList = accessList - innerTx.To = to - innerTx.Value = value - innerTx.Gas = gas - ethCoreTx = gethcore.NewTx(innerTx) - case gethcore.DynamicFeeTxType: - innerTx := TxTemplateDynamicFeeTx() - innerTx.Nonce = nonce - innerTx.Data = innerTxData - innerTx.To = to - innerTx.Value = value - innerTx.Gas = gas - innerTx.AccessList = accessList - ethCoreTx = gethcore.NewTx(innerTx) - default: - return nil, fmt.Errorf( - "received unknown tx type (%v) in NewEthTxMsgFromTxData", txType) - } - - ethTxMsg := new(evm.MsgEthereumTx) - if err := ethTxMsg.FromEthereumTx(ethCoreTx); err != nil { - return ethTxMsg, err - } - - ethTxMsg.From = deps.Sender.EthAddr.Hex() - return ethTxMsg, ethTxMsg.Sign(deps.GethSigner(), deps.Sender.KeyringSigner) -} - // ExecuteNibiTransfer executes nibi transfer func ExecuteNibiTransfer(deps *TestDeps, t *testing.T) *evm.MsgEthereumTx { nonce := deps.StateDB().GetNonce(deps.Sender.EthAddr) @@ -326,6 +237,10 @@ func TransferWei( return err } +// -------------------------------------------------- +// Templates +// -------------------------------------------------- + // ValidLegacyTx: Useful initial condition for tests // Exported only for use in tests. func ValidLegacyTx() *evm.LegacyTx { @@ -342,3 +257,113 @@ func ValidLegacyTx() *evm.LegacyTx { S: []byte{}, } } + +// GethTxType represents different Ethereum transaction types as defined in +// go-ethereum, such as Legacy, AccessList, and DynamicFee transactions. +type GethTxType = uint8 + +func TxTemplateAccessListTx() *gethcore.AccessListTx { + return &gethcore.AccessListTx{ + GasPrice: big.NewInt(1), + Gas: gethparams.TxGas, + To: &gethcommon.Address{}, + Value: big.NewInt(0), + Data: []byte{}, + } +} + +func TxTemplateLegacyTx() *gethcore.LegacyTx { + return &gethcore.LegacyTx{ + GasPrice: big.NewInt(1), + Gas: gethparams.TxGas, + To: &gethcommon.Address{}, + Value: big.NewInt(0), + Data: []byte{}, + } +} + +func TxTemplateDynamicFeeTx() *gethcore.DynamicFeeTx { + return &gethcore.DynamicFeeTx{ + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(2), + Gas: gethparams.TxGas, + To: &gethcommon.Address{}, + Value: big.NewInt(0), + Data: []byte{}, + } +} + +// NewEthTxMsgFromTxData creates an Ethereum transaction message based on +// the specified txType (Legacy, AccessList, or DynamicFee). This function +// populates transaction fields like nonce, recipient, value, and gas, with +// an optional access list for AccessList and DynamicFee types. The transaction +// is signed using the provided dependencies. +// +// Parameters: +// - deps: Required dependencies including the sender address and signer. +// - txType: Transaction type (Legacy, AccessList, or DynamicFee). +// - innerTxData: Byte slice of transaction data (input). +// - nonce: Transaction nonce. +// - to: Recipient address. +// - value: ETH value (in wei) to transfer. +// - gas: Gas limit for the transaction. +// - accessList: Access list for AccessList and DynamicFee types. +// +// Returns: +// - *evm.MsgEthereumTx: Ethereum transaction message ready for submission. +// - error: Any error encountered during creation or signing. +func NewEthTxMsgFromTxData( + deps *TestDeps, + txType GethTxType, + innerTxData []byte, + nonce uint64, + to *gethcommon.Address, + value *big.Int, + gas uint64, + accessList gethcore.AccessList, +) (*evm.MsgEthereumTx, error) { + if innerTxData == nil { + innerTxData = []byte{} + } + + var ethCoreTx *gethcore.Transaction + switch txType { + case gethcore.LegacyTxType: + innerTx := TxTemplateLegacyTx() + innerTx.Nonce = nonce + innerTx.Data = innerTxData + innerTx.To = to + innerTx.Value = value + innerTx.Gas = gas + ethCoreTx = gethcore.NewTx(innerTx) + case gethcore.AccessListTxType: + innerTx := TxTemplateAccessListTx() + innerTx.Nonce = nonce + innerTx.Data = innerTxData + innerTx.AccessList = accessList + innerTx.To = to + innerTx.Value = value + innerTx.Gas = gas + ethCoreTx = gethcore.NewTx(innerTx) + case gethcore.DynamicFeeTxType: + innerTx := TxTemplateDynamicFeeTx() + innerTx.Nonce = nonce + innerTx.Data = innerTxData + innerTx.To = to + innerTx.Value = value + innerTx.Gas = gas + innerTx.AccessList = accessList + ethCoreTx = gethcore.NewTx(innerTx) + default: + return nil, fmt.Errorf( + "received unknown tx type (%v) in NewEthTxMsgFromTxData", txType) + } + + ethTxMsg := new(evm.MsgEthereumTx) + if err := ethTxMsg.FromEthereumTx(ethCoreTx); err != nil { + return ethTxMsg, err + } + + ethTxMsg.From = deps.Sender.EthAddr.Hex() + return ethTxMsg, ethTxMsg.Sign(deps.GethSigner(), deps.Sender.KeyringSigner) +} diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go index 10404bea4..328452ecf 100644 --- a/x/evm/keeper/erc20.go +++ b/x/evm/keeper/erc20.go @@ -218,11 +218,8 @@ func (k Keeper) CallContractWithInput( // sent by a user txConfig := k.TxConfig(ctx, gethcommon.BigToHash(big.NewInt(0))) - // Using tmp context to not modify the state in case of evm revert - tmpCtx, commitCtx := ctx.CacheContext() - evmResp, evmObj, err = k.ApplyEvmMsg( - tmpCtx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, + ctx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, ) if err != nil { // We don't know the actual gas used, so consuming the gas limit @@ -245,7 +242,6 @@ func (k Keeper) CallContractWithInput( } else { // Success, committing the state to ctx if commit { - commitCtx() totalGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) if err != nil { k.ResetGasMeterAndConsumeGas(ctx, ctx.GasMeter().Limit()) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 49ea0c9bf..dd31229fd 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/NibiruChain/nibiru/v2/app/appconst" @@ -40,7 +41,7 @@ type Keeper struct { // this should be the x/gov module account. authority sdk.AccAddress - bankKeeper evm.BankKeeper + bankKeeper bankkeeper.Keeper accountKeeper evm.AccountKeeper stakingKeeper evm.StakingKeeper @@ -63,13 +64,14 @@ func NewKeeper( storeKey, transientKey storetypes.StoreKey, authority sdk.AccAddress, accKeeper evm.AccountKeeper, - bankKeeper evm.BankKeeper, + bankKeeper bankkeeper.Keeper, stakingKeeper evm.StakingKeeper, tracer string, ) Keeper { if err := sdk.VerifyAddressFormat(authority); err != nil { panic(err) } + return Keeper{ cdc: cdc, storeKey: storeKey, diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 89a249dd3..be8abb236 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -252,7 +252,7 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, vmErr error // vm errors do not effect consensus and are therefore not assigned to err ) - stateDB := statedb.New(ctx, k, txConfig) + stateDB := k.NewStateDB(ctx, txConfig) evmObj = k.NewEVM(ctx, msg, evmConfig, tracer, stateDB) leftoverGas := msg.Gas() diff --git a/x/evm/keeper/precompiles.go b/x/evm/keeper/precompiles.go index 965866660..3b1a0e480 100644 --- a/x/evm/keeper/precompiles.go +++ b/x/evm/keeper/precompiles.go @@ -21,3 +21,7 @@ func (k *Keeper) AddPrecompiles( } } } + +func (k *Keeper) IsPrecompile(addr gethcommon.Address) bool { + return k.precompiles.Has(addr) +} diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 6eb46f990..7aff8c02d 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -17,6 +17,13 @@ import ( var _ statedb.Keeper = &Keeper{} +func (k *Keeper) NewStateDB( + ctx sdk.Context, + txConfig statedb.TxConfig, +) *statedb.StateDB { + return statedb.New(ctx, k, txConfig) +} + // ---------------------------------------------------------------------------- // StateDB Keeper implementation // ---------------------------------------------------------------------------- @@ -65,7 +72,10 @@ func (k *Keeper) ForEachStorage( } } -// SetAccBalance update account's balance, compare with current balance first, then decide to mint or burn. +// SetAccBalance update account's balance, compare with current balance first, +// then decide to mint or burn. +// Implements the `statedb.Keeper` interface. +// Only called by `StateDB.Commit()`. func (k *Keeper) SetAccBalance( ctx sdk.Context, addr gethcommon.Address, amountEvmDenom *big.Int, ) error { diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index a937d111f..69e756ed3 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -72,8 +72,7 @@ func (p precompileFunToken) Run( if err != nil { return nil, err } - // Dirty journal entries in `StateDB` must be committed - return bz, start.StateDB.Commit() + return bz, err } func PrecompileFunToken(keepers keepers.PublicKeepers) vm.PrecompiledContract { diff --git a/x/evm/precompile/precompile.go b/x/evm/precompile/precompile.go index a6bbfefc4..40d0c74b4 100644 --- a/x/evm/precompile/precompile.go +++ b/x/evm/precompile/precompile.go @@ -147,6 +147,8 @@ type OnRunStartResult struct { Method *gethabi.Method StateDB *statedb.StateDB + + PrecompileJournalEntry statedb.PrecompileCalled } // OnRunStart prepares the execution environment for a precompiled contract call. @@ -188,14 +190,21 @@ func OnRunStart( err = fmt.Errorf("failed to load the sdk.Context from the EVM StateDB") return } - ctx := stateDB.GetContext() - if err = stateDB.Commit(); err != nil { + + // journalEntry captures the state before precompile execution to enable + // proper state reversal if the call fails or if [statedb.JournalChange] + // is reverted in general. + cacheCtx, journalEntry := stateDB.CacheCtxForPrecompile(contract.Address()) + if err = stateDB.SavePrecompileCalledJournalChange(contract.Address(), journalEntry); err != nil { + return res, err + } + if err = stateDB.CommitCacheCtx(); err != nil { return res, fmt.Errorf("error committing dirty journal entries: %w", err) } return OnRunStartResult{ Args: args, - Ctx: ctx, + Ctx: cacheCtx, Method: method, StateDB: stateDB, }, nil diff --git a/x/evm/precompile/test/export.go b/x/evm/precompile/test/export.go index 966dd3359..28670e3e0 100644 --- a/x/evm/precompile/test/export.go +++ b/x/evm/precompile/test/export.go @@ -2,11 +2,14 @@ package test import ( "encoding/json" + "math/big" "os" "os/exec" "path" "strings" + serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasm "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/ethereum/go-ethereum/core/vm" @@ -267,6 +270,7 @@ func IncrementWasmCounterWithExecuteMulti( deps *evmtest.TestDeps, wasmContract sdk.AccAddress, times uint, + finalizeTx bool, ) (evmObj *vm.EVM) { msgArgsBz := []byte(` { @@ -308,9 +312,68 @@ func IncrementWasmCounterWithExecuteMulti( s.Require().NoError(err) ethTxResp, evmObj, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, finalizeTx, input, ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) return evmObj } + +func IncrementWasmCounterWithExecuteMultiViaVMCall( + s *suite.Suite, + deps *evmtest.TestDeps, + wasmContract sdk.AccAddress, + times uint, + finalizeTx bool, + evmObj *vm.EVM, +) error { + msgArgsBz := []byte(` + { + "increment": {} + } + `) + + // Parse funds argument. + var funds []precompile.WasmBankCoin // blank funds + fundsJson, err := json.Marshal(funds) + s.NoErrorf(err, "fundsJson: %s", fundsJson) + err = json.Unmarshal(fundsJson, &funds) + s.Require().NoError(err, "fundsJson %s, funds %s", fundsJson, funds) + + // The "times" arg determines the number of messages in the executeMsgs slice + executeMsgs := []struct { + ContractAddr string `json:"contractAddr"` + MsgArgs []byte `json:"msgArgs"` + Funds []precompile.WasmBankCoin `json:"funds"` + }{ + {wasmContract.String(), msgArgsBz, funds}, + } + if times == 0 { + executeMsgs = executeMsgs[:0] // force empty + } else { + for i := uint(1); i < times; i++ { + executeMsgs = append(executeMsgs, executeMsgs[0]) + } + } + s.Require().Len(executeMsgs, int(times)) // sanity check assertion + + callArgs := []any{ + executeMsgs, + } + input, err := embeds.SmartContract_Wasm.ABI.Pack( + string(precompile.WasmMethod_executeMulti), + callArgs..., + ) + s.Require().NoError(err) + + contract := precompile.PrecompileAddr_Wasm + leftoverGas := serverconfig.DefaultEthCallGasLimit + _, _, err = evmObj.Call( + vm.AccountRef(deps.Sender.EthAddr), + contract, + input, + leftoverGas, + big.NewInt(0), + ) + return err +} diff --git a/x/evm/precompile/wasm.go b/x/evm/precompile/wasm.go index 10817c673..a7b21684c 100644 --- a/x/evm/precompile/wasm.go +++ b/x/evm/precompile/wasm.go @@ -62,9 +62,7 @@ func (p precompileWasm) Run( if err != nil { return nil, err } - - // Dirty journal entries in `StateDB` must be committed - return bz, start.StateDB.Commit() + return bz, err } type precompileWasm struct { diff --git a/x/evm/precompile/wasm_test.go b/x/evm/precompile/wasm_test.go index d796f8b89..dbe35b839 100644 --- a/x/evm/precompile/wasm_test.go +++ b/x/evm/precompile/wasm_test.go @@ -100,13 +100,13 @@ func (s *WasmSuite) TestExecuteMultiHappy() { test.AssertWasmCounterState(&s.Suite, deps, wasmContract, 0) // count += 2 test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, &deps, wasmContract, 2) + &s.Suite, &deps, wasmContract, 2, true) // count = 2 test.AssertWasmCounterState(&s.Suite, deps, wasmContract, 2) s.assertWasmCounterStateRaw(deps, wasmContract, 2) // count += 67 test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, &deps, wasmContract, 67) + &s.Suite, &deps, wasmContract, 67, true) // count = 69 test.AssertWasmCounterState(&s.Suite, deps, wasmContract, 69) s.assertWasmCounterStateRaw(deps, wasmContract, 69) diff --git a/x/evm/statedb/access_list.go b/x/evm/statedb/access_list.go index 4513a9164..f62b45171 100644 --- a/x/evm/statedb/access_list.go +++ b/x/evm/statedb/access_list.go @@ -1,3 +1,5 @@ +package statedb + // Copyright 2020 The go-ethereum Authors // This file is part of the go-ethereum library. // @@ -14,8 +16,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package statedb - import ( "github.com/ethereum/go-ethereum/common" ) diff --git a/x/evm/statedb/config.go b/x/evm/statedb/config.go index 887f591c5..417e480ac 100644 --- a/x/evm/statedb/config.go +++ b/x/evm/statedb/config.go @@ -1,6 +1,7 @@ -// Copyright (c) 2023-2024 Nibi, Inc. package statedb +// Copyright (c) 2023-2024 Nibi, Inc. + import ( "math/big" diff --git a/x/evm/statedb/debug.go b/x/evm/statedb/debug.go new file mode 100644 index 000000000..c2b5fb968 --- /dev/null +++ b/x/evm/statedb/debug.go @@ -0,0 +1,39 @@ +package statedb + +// Copyright (c) 2023-2024 Nibi, Inc. + +import ( + "github.com/ethereum/go-ethereum/common" +) + +// DebugDirtiesCount is a test helper to inspect how many entries in the journal +// are still dirty (uncommitted). After calling [StateDB.Commit], this function +// should return zero. +func (s *StateDB) DebugDirtiesCount() int { + dirtiesCount := 0 + for _, dirtyCount := range s.Journal.dirties { + dirtiesCount += dirtyCount + } + return dirtiesCount +} + +// DebugDirties is a test helper that returns the journal's dirty account changes map. +func (s *StateDB) DebugDirties() map[common.Address]int { + return s.Journal.dirties +} + +// DebugEntries is a test helper that returns the sequence of [JournalChange] +// objects added during execution. +func (s *StateDB) DebugEntries() []JournalChange { + return s.Journal.entries +} + +// DebugStateObjects is a test helper that returns returns a copy of the +// [StateDB.stateObjects] map. +func (s *StateDB) DebugStateObjects() map[common.Address]*stateObject { + copyOfMap := make(map[common.Address]*stateObject) + for key, val := range s.stateObjects { + copyOfMap[key] = val + } + return copyOfMap +} diff --git a/x/evm/statedb/interfaces.go b/x/evm/statedb/interfaces.go index a4c1c3b59..c242771ca 100644 --- a/x/evm/statedb/interfaces.go +++ b/x/evm/statedb/interfaces.go @@ -1,22 +1,12 @@ -// Copyright (c) 2023-2024 Nibi, Inc. package statedb +// Copyright (c) 2023-2024 Nibi, Inc. + import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" ) -// ExtStateDB defines an extension to the interface provided by the go-ethereum -// codebase to support additional state transition functionalities. In particular -// it supports appending a new entry to the state journal through -// AppendJournalEntry so that the state can be reverted after running -// stateful precompiled contracts. -type ExtStateDB interface { - vm.StateDB - AppendJournalEntry(JournalChange) -} - // Keeper provide underlying storage of StateDB type Keeper interface { // GetAccount: Ethereum account getter for a [statedb.Account]. @@ -38,4 +28,6 @@ type Keeper interface { // DeleteAccount handles contract's suicide call, clearing the balance, // contract bytecode, contract state, and its native account. DeleteAccount(ctx sdk.Context, addr common.Address) error + + IsPrecompile(addr common.Address) bool } diff --git a/x/evm/statedb/journal.go b/x/evm/statedb/journal.go index ac041b617..acbba5eab 100644 --- a/x/evm/statedb/journal.go +++ b/x/evm/statedb/journal.go @@ -1,3 +1,5 @@ +package statedb + // Copyright 2016 The go-ethereum Authors // This file is part of the go-ethereum library. // @@ -14,13 +16,13 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package statedb - import ( "bytes" "math/big" "sort" + store "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" ) @@ -91,25 +93,6 @@ func (j *journal) Length() int { return len(j.entries) } -// DirtiesCount is a test helper to inspect how many entries in the journal are -// still dirty (uncommitted). After calling [StateDB.Commit], this function should -// return zero. -func (s *StateDB) DirtiesCount() int { - dirtiesCount := 0 - for _, dirtyCount := range s.Journal.dirties { - dirtiesCount += dirtyCount - } - return dirtiesCount -} - -func (s *StateDB) Dirties() map[common.Address]int { - return s.Journal.dirties -} - -func (s *StateDB) Entries() []JournalChange { - return s.Journal.entries -} - // ------------------------------------------------------ // createObjectChange @@ -335,3 +318,46 @@ func (ch accessListAddSlotChange) Revert(s *StateDB) { func (ch accessListAddSlotChange) Dirtied() *common.Address { return nil } + +// ------------------------------------------------------ +// PrecompileSnapshotBeforeRun + +// PrecompileCalled: Precompiles can alter persistent storage of other +// modules. These changes to persistent storage are not reverted by a `Revert` of +// [JournalChange] by default, as it generally manages only changes to accounts +// and Bank balances for ether (NIBI). +// +// As a workaround to make state changes from precompiles reversible, we store +// [PrecompileCalled] snapshots that sync and record the prior state +// of the other modules, allowing precompile calls to truly be reverted. +// +// As a simple example, suppose that a transaction calls a precompile. +// 1. If the precompile changes the state in the Bank Module or Wasm module +// 2. The call gets reverted (`revert()` in Solidity), which shoud restore the +// state to a in-memory snapshot recorded on the StateDB journal. +// 3. This could cause a problem where changes to the rest of the blockchain state +// are still in effect following the reversion in the EVM state DB. +type PrecompileCalled struct { + MultiStore store.CacheMultiStore + Events sdk.Events +} + +var _ JournalChange = PrecompileCalled{} + +// Revert rolls back the [StateDB] cache context to the state it was in prior to +// the precompile call. Modifications to this cache context are pushed to the +// commit context (s.evmTxCtx) when [StateDB.Commit] is executed. +func (ch PrecompileCalled) Revert(s *StateDB) { + s.cacheCtx = s.cacheCtx.WithMultiStore(ch.MultiStore) + // Rewrite the `writeCacheCtxFn` using the same logic as sdk.Context.CacheCtx + s.writeToCommitCtxFromCacheCtx = func() { + s.evmTxCtx.EventManager().EmitEvents(ch.Events) + // TODO: Check correctness of the emitted events + // https://github.com/NibiruChain/nibiru/issues/2096 + ch.MultiStore.Write() + } +} + +func (ch PrecompileCalled) Dirtied() *common.Address { + return nil +} diff --git a/x/evm/statedb/journal_test.go b/x/evm/statedb/journal_test.go index 5863face5..6390b640f 100644 --- a/x/evm/statedb/journal_test.go +++ b/x/evm/statedb/journal_test.go @@ -6,10 +6,12 @@ import ( "strings" "testing" + "github.com/MakeNowJust/heredoc/v2" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/core/vm" serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" + "github.com/NibiruChain/nibiru/v2/x/common" "github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp" "github.com/NibiruChain/nibiru/v2/x/evm" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" @@ -18,7 +20,7 @@ import ( "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) -func (s *Suite) TestPrecompileSnapshots() { +func (s *Suite) TestComplexJournalChanges() { deps := evmtest.NewTestDeps() bankDenom := evm.EVMBankDenom s.Require().NoError(testapp.FundAccount( @@ -32,25 +34,11 @@ func (s *Suite) TestPrecompileSnapshots() { wasmContract := test.SetupWasmContracts(&deps, &s.Suite)[1] fmt.Printf("wasmContract: %s\n", wasmContract) - assertionsBeforeRun := func(deps *evmtest.TestDeps) { - test.AssertWasmCounterState( - &s.Suite, *deps, wasmContract, 0, - ) - } - run := func(deps *evmtest.TestDeps) *vm.EVM { - return test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, deps, wasmContract, 7, - ) - } - assertionsAfterRun := func(deps *evmtest.TestDeps) { - test.AssertWasmCounterState( - &s.Suite, *deps, wasmContract, 7, - ) - } s.T().Log("Assert before transition") - - assertionsBeforeRun(&deps) + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 0, + ) deployArgs := []any{"name", "SYMBOL", uint8(18)} deployResp, err := evmtest.DeployContract( @@ -71,7 +59,7 @@ func (s *Suite) TestPrecompileSnapshots() { s.Run("Populate dirty journal entries. Remove with Commit", func() { stateDB := evmObj.StateDB.(*statedb.StateDB) - s.Equal(0, stateDB.DirtiesCount()) + s.Equal(0, stateDB.DebugDirtiesCount()) randomAcc := evmtest.NewEthPrivAcc().EthAddr balDelta := evm.NativeToWei(big.NewInt(4)) @@ -81,14 +69,15 @@ func (s *Suite) TestPrecompileSnapshots() { stateDB.AddBalance(randomAcc, balDelta) // 1 dirties from [balanceChange] stateDB.SubBalance(randomAcc, balDelta) - if stateDB.DirtiesCount() != 4 { + if stateDB.DebugDirtiesCount() != 4 { debugDirtiesCountMismatch(stateDB, s.T()) s.FailNow("expected 4 dirty journal changes") } - err = stateDB.Commit() // Dirties should be gone + s.T().Log("StateDB.Commit, then Dirties should be gone") + err = stateDB.Commit() s.NoError(err) - if stateDB.DirtiesCount() != 0 { + if stateDB.DebugDirtiesCount() != 0 { debugDirtiesCountMismatch(stateDB, s.T()) s.FailNow("expected 0 dirty journal changes") } @@ -110,7 +99,7 @@ func (s *Suite) TestPrecompileSnapshots() { ) s.Require().NoError(err) stateDB := evmObj.StateDB.(*statedb.StateDB) - if stateDB.DirtiesCount() != 2 { + if stateDB.DebugDirtiesCount() != 2 { debugDirtiesCountMismatch(stateDB, s.T()) s.FailNow("expected 2 dirty journal changes") } @@ -136,22 +125,105 @@ func (s *Suite) TestPrecompileSnapshots() { s.Require().ErrorContains(err, vm.ErrExecutionReverted.Error()) }) - s.Run("Precompile calls also start and end clean (no dirty changes)", func() { - evmObj = run(&deps) - assertionsAfterRun(&deps) + s.Run("Precompile calls populate snapshots", func() { + s.T().Log("commitEvmTx=true, expect 0 dirty journal entries") + commitEvmTx := true + evmObj = test.IncrementWasmCounterWithExecuteMulti( + &s.Suite, &deps, wasmContract, 7, commitEvmTx, + ) + // assertions after run + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 7, + ) stateDB, ok := evmObj.StateDB.(*statedb.StateDB) s.Require().True(ok, "error retrieving StateDB from the EVM") - if stateDB.DirtiesCount() != 0 { + if stateDB.DebugDirtiesCount() != 0 { + debugDirtiesCountMismatch(stateDB, s.T()) + s.FailNow("expected 0 dirty journal changes") + } + + s.T().Log("commitEvmTx=false, expect dirty journal entries") + commitEvmTx = false + evmObj = test.IncrementWasmCounterWithExecuteMulti( + &s.Suite, &deps, wasmContract, 5, commitEvmTx, + ) + stateDB, ok = evmObj.StateDB.(*statedb.StateDB) + s.Require().True(ok, "error retrieving StateDB from the EVM") + + s.T().Log("Expect exactly 0 dirty journal entry for the precompile snapshot") + if stateDB.DebugDirtiesCount() != 0 { debugDirtiesCountMismatch(stateDB, s.T()) s.FailNow("expected 0 dirty journal changes") } + + s.T().Log("Expect no change since the StateDB has not been committed") + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 7, // 7 = 7 + 0 + ) + + s.T().Log("Expect change to persist on the StateDB cacheCtx") + cacheCtx := stateDB.GetCacheContext() + s.NotNil(cacheCtx) + deps.Ctx = *cacheCtx + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 12, // 12 = 7 + 5 + ) + // NOTE: that the [StateDB.Commit] fn has not been called yet. We're still + // mid-transaction. + + s.T().Log("EVM revert operation should bring about the old state") + err = test.IncrementWasmCounterWithExecuteMultiViaVMCall( + &s.Suite, &deps, wasmContract, 50, commitEvmTx, evmObj, + ) + stateDBPtr := evmObj.StateDB.(*statedb.StateDB) + s.Require().Equal(stateDB, stateDBPtr) + s.Require().NoError(err) + s.T().Log(heredoc.Doc(`At this point, 2 precompile calls have succeeded. +One that increments the counter to 7 + 5, and another for +50. +The StateDB has not been committed. We expect to be able to revert to both +snapshots and see the prior states.`)) + cacheCtx = stateDB.GetCacheContext() + deps.Ctx = *cacheCtx + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 7+5+50, + ) + + errFn := common.TryCatch(func() { + // There were only two EVM calls. + // Thus, there are only 2 snapshots: 0 and 1. + // We should not be able to revert to a third one. + stateDB.RevertToSnapshot(2) + }) + s.Require().ErrorContains(errFn(), "revision id 2 cannot be reverted") + + stateDB.RevertToSnapshot(1) + cacheCtx = stateDB.GetCacheContext() + s.NotNil(cacheCtx) + deps.Ctx = *cacheCtx + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 7+5, + ) + + stateDB.RevertToSnapshot(0) + cacheCtx = stateDB.GetCacheContext() + s.NotNil(cacheCtx) + deps.Ctx = *cacheCtx + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 7, // state before precompile called + ) + + err = stateDB.Commit() + deps.Ctx = stateDB.GetEvmTxContext() + test.AssertWasmCounterState( + &s.Suite, deps, wasmContract, 7, // state before precompile called + ) }) } func debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) string { lines := []string{} - dirties := db.Dirties() - stateObjects := db.StateObjects() + dirties := db.DebugDirties() + stateObjects := db.DebugStateObjects() for addr, dirtyCountForAddr := range dirties { lines = append(lines, fmt.Sprintf("Dirty addr: %s, dirtyCountForAddr=%d", addr, dirtyCountForAddr)) diff --git a/x/evm/statedb/state_object.go b/x/evm/statedb/state_object.go index e371beae0..28ba2d85a 100644 --- a/x/evm/statedb/state_object.go +++ b/x/evm/statedb/state_object.go @@ -1,6 +1,7 @@ -// Copyright (c) 2023-2024 Nibi, Inc. package statedb +// Copyright (c) 2023-2024 Nibi, Inc. + import ( "bytes" "math/big" @@ -198,7 +199,7 @@ func (s *stateObject) Code() []byte { if bytes.Equal(s.CodeHash(), emptyCodeHash) { return nil } - code := s.db.keeper.GetCode(s.db.ctx, common.BytesToHash(s.CodeHash())) + code := s.db.keeper.GetCode(s.db.evmTxCtx, common.BytesToHash(s.CodeHash())) s.code = code return code } @@ -260,7 +261,7 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { return value } // If no live objects are available, load it from keeper - value := s.db.keeper.GetState(s.db.ctx, s.Address(), key) + value := s.db.keeper.GetState(s.db.evmTxCtx, s.Address(), key) s.OriginStorage[key] = value return value } diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index 223e92edb..4c79e61af 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -1,11 +1,28 @@ -// Copyright (c) 2023-2024 Nibi, Inc. +// The "evm/statedb" package implements a go-ethereum [vm.StateDB] with state +// management and journal changes specific to the Nibiru EVM. +// +// This package plays a critical role in managing the state of accounts, +// contracts, and storage while handling atomicity, caching, and state +// modifications. It ensures that state transitions made during the +// execution of smart contracts are either committed or reverted based +// on transaction outcomes. +// +// StateDB structs used to store anything within the state tree, including +// accounts, contracts, and contract storage. +// Note that Nibiru's state tree is an IAVL tree, which differs from the Merkle +// Patricia Trie structure seen on Ethereum mainnet. +// +// StateDBs also take care of caching and handling nested states. package statedb +// Copyright (c) 2023-2024 Nibi, Inc. + import ( "fmt" "math/big" "sort" + store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" gethcore "github.com/ethereum/go-ethereum/core/types" @@ -13,14 +30,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -// revision is the identifier of a version of state. -// it consists of an auto-increment id and a journal index. -// it's safer to use than using journal index alone. -type revision struct { - id int - journalIndex int -} - var _ vm.StateDB = &StateDB{} // StateDB structs within the ethereum protocol are used to store anything @@ -30,8 +39,9 @@ var _ vm.StateDB = &StateDB{} // * Accounts type StateDB struct { keeper Keeper - // ctx is the persistent context used for official `StateDB.Commit` calls. - ctx sdk.Context + + // evmTxCtx is the persistent context used for official `StateDB.Commit` calls. + evmTxCtx sdk.Context // Journal of state modifications. This is the backbone of // Snapshot and RevertToSnapshot. @@ -43,6 +53,21 @@ type StateDB struct { txConfig TxConfig + // cacheCtx: An sdk.Context produced from the [StateDB.ctx] with the + // multi-store cached and a new event manager. The cached context + // (`cacheCtx`) is written to the persistent context (`ctx`) when + // `writeCacheCtx` is called. + cacheCtx sdk.Context + + // writeToCommitCtxFromCacheCtx is the "write" function received from + // `s.evmTxCtx.CacheContext()`. It saves mutations on s.cacheCtx to the StateDB's + // commit context (s.evmTxCtx). This synchronizes the multistore and event manager + // of the two contexts. + writeToCommitCtxFromCacheCtx func() + + // The number of precompiled contract calls within the current transaction + multistoreCacheCount uint8 + // The refund counter, also used by state transitioning. refund uint64 @@ -57,7 +82,7 @@ type StateDB struct { func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB { return &StateDB{ keeper: keeper, - ctx: ctx, + evmTxCtx: ctx, stateObjects: make(map[common.Address]*stateObject), Journal: newJournal(), accessList: newAccessList(), @@ -66,14 +91,30 @@ func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB { } } +// revision is the identifier of a version of state. +// it consists of an auto-increment id and a journal index. +// it's safer to use than using journal index alone. +type revision struct { + id int + journalIndex int +} + // Keeper returns the underlying `Keeper` func (s *StateDB) Keeper() Keeper { return s.keeper } -// GetContext returns the transaction Context. -func (s *StateDB) GetContext() sdk.Context { - return s.ctx +// GetEvmTxContext returns the EVM transaction context. +func (s *StateDB) GetEvmTxContext() sdk.Context { + return s.evmTxCtx +} + +// GetCacheContext: Getter for testing purposes. +func (s *StateDB) GetCacheContext() *sdk.Context { + if s.writeToCommitCtxFromCacheCtx == nil { + return nil + } + return &s.cacheCtx } // AddLog adds a log, called by evm. @@ -212,8 +253,9 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject { if obj := s.stateObjects[addr]; obj != nil { return obj } + // If no live objects are available, load it from keeper - account := s.keeper.GetAccount(s.ctx, addr) + account := s.keeper.GetAccount(s.evmTxCtx, addr) if account == nil { return nil } @@ -274,7 +316,7 @@ func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common. if so == nil { return nil } - s.keeper.ForEachStorage(s.ctx, addr, func(key, value common.Hash) bool { + s.keeper.ForEachStorage(s.evmTxCtx, addr, func(key, value common.Hash) bool { if value, dirty := so.DirtyStorage[key]; dirty { return cb(key, value) } @@ -438,6 +480,9 @@ func (s *StateDB) Snapshot() int { // RevertToSnapshot reverts all state changes made since the given revision. func (s *StateDB) RevertToSnapshot(revid int) { + fmt.Printf("len(s.validRevisions): %d\n", len(s.validRevisions)) + fmt.Printf("s.validRevisions: %v\n", s.validRevisions) + // Find the snapshot in the stack of valid snapshots. idx := sort.Search(len(s.validRevisions), func(i int) bool { return s.validRevisions[i].id >= revid @@ -460,11 +505,37 @@ func errorf(format string, args ...any) error { // Commit writes the dirty journal state changes to the EVM Keeper. The // StateDB object cannot be reused after [Commit] has completed. A new // object needs to be created from the EVM. +// +// cacheCtxSyncNeeded: If one of the [Nibiru-Specific Precompiled Contracts] was +// called, a [JournalChange] of type [PrecompileSnapshotBeforeRun] gets added and +// we branch off a cache of the commit context (s.evmTxCtx). +// +// [Nibiru-Specific Precompiled Contracts]: https://nibiru.fi/docs/evm/precompiles/nibiru.html func (s *StateDB) Commit() error { - ctx := s.GetContext() + if s.writeToCommitCtxFromCacheCtx != nil { + s.writeToCommitCtxFromCacheCtx() + } + return s.commitCtx(s.GetEvmTxContext()) +} + +// CommitCacheCtx is identical to [StateDB.Commit], except it: +// (1) uses the cacheCtx of the [StateDB] and +// (2) does not save mutations of the cacheCtx to the commit context (s.evmTxCtx). +// The reason for (2) is that the overall EVM transaction (block, not internal) +// is only finalized when [Commit] is called, not when [CommitCacheCtx] is +// called. +func (s *StateDB) CommitCacheCtx() error { + return s.commitCtx(s.cacheCtx) +} + +// commitCtx writes the dirty journal state changes to the EVM Keeper. The +// StateDB object cannot be reused after [commitCtx] has completed. A new +// object needs to be created from the EVM. +func (s *StateDB) commitCtx(ctx sdk.Context) error { for _, addr := range s.Journal.sortedDirties() { obj := s.getStateObject(addr) if obj == nil { + s.Journal.dirties[addr] = 0 continue } if obj.Suicided { @@ -493,18 +564,47 @@ func (s *StateDB) Commit() error { obj.OriginStorage[key] = dirtyVal } } - // Clear the dirty counts because all state changes have been - // committed. + // TODO: UD-DEBUG: Assume clean to pretend for tests + // Reset the dirty count to 0 because all state changes for this dirtied + // address in the journal have been committed. s.Journal.dirties[addr] = 0 } return nil } -// StateObjects: Returns a copy of the [StateDB.stateObjects] map. -func (s *StateDB) StateObjects() map[common.Address]*stateObject { - copyOfMap := make(map[common.Address]*stateObject) - for key, val := range s.stateObjects { - copyOfMap[key] = val +func (s *StateDB) CacheCtxForPrecompile(precompileAddr common.Address) ( + sdk.Context, PrecompileCalled, +) { + if s.writeToCommitCtxFromCacheCtx == nil { + s.cacheCtx, s.writeToCommitCtxFromCacheCtx = s.evmTxCtx.CacheContext() + } + return s.cacheCtx, PrecompileCalled{ + MultiStore: s.cacheCtx.MultiStore().(store.CacheMultiStore).Copy(), + Events: s.cacheCtx.EventManager().Events(), + } +} + +// SavePrecompileCalledJournalChange adds a snapshot of the commit multistore +// ([PrecompileCalled]) to the [StateDB] journal at the end of +// successful invocation of a precompiled contract. This is necessary to revert +// intermediate states where an EVM contract augments the multistore with a +// precompile and an inconsistency occurs between the EVM module and other +// modules. +// +// See [PrecompileCalled] for more info. +func (s *StateDB) SavePrecompileCalledJournalChange( + precompileAddr common.Address, + journalChange PrecompileCalled, +) error { + s.Journal.append(journalChange) + s.multistoreCacheCount++ + if s.multistoreCacheCount > maxMultistoreCacheCount { + return fmt.Errorf( + "exceeded maximum number Nibiru-specific precompiled contract calls in one transaction (%d). Called address %s", + maxMultistoreCacheCount, precompileAddr.Hex(), + ) } - return copyOfMap + return nil } + +const maxMultistoreCacheCount uint8 = 10 From 9d0dbd5edb108bb69f844219c46cb7c30f71154a Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:17:40 +0100 Subject: [PATCH 03/12] fix(evm): transfer for native to erc20 (#2090) * feat: fix transfer for native to erc20 * chore: changelog * feat: check transfer occurred by ensuring new balance is higher than previous one * feat: fix the 0 check * fix: fix error message * feat: move transfer logic to erc20.go * chore: changelog * fix: make the FunToken precompile return the sent amount --------- Co-authored-by: Unique-Divine --- CHANGELOG.md | 4 + .../contracts/IFunToken.sol/IFunToken.json | 8 +- .../TestERC20TransferThenPrecompileSend.json | 4 +- .../TestNativeSendThenPrecompileSend.json | 4 +- x/evm/embeds/contracts/IFunToken.sol | 17 ++- x/evm/keeper/erc20.go | 40 ++++++- x/evm/keeper/erc20_test.go | 15 ++- x/evm/keeper/msg_server.go | 100 +++++++----------- x/evm/precompile/funtoken.go | 11 +- x/evm/precompile/funtoken_test.go | 22 +++- 10 files changed, 134 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c99138718..61dc41b07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,10 @@ Ethereum transactions, such as in the case of an EthereumTx that influences the `StateDB`, then calls a precompile that also changes non-EVM state, and then EVM reverts inside of a try-catch. - [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb tests for race conditions within funtoken precompile +- [#2090](https://github.com/NibiruChain/nibiru/pull/2090) - fix(evm): Account +for (1) ERC20 transfers with tokens that return false success values instead of +throwing an error and (2) ERC20 transfers with other operations that don't bring +about the expected resulting balance for the transfer recipient. #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json b/x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json index 6fe6e838a..882e04696 100644 --- a/x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json +++ b/x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json @@ -22,7 +22,13 @@ } ], "name": "bankSend", - "outputs": [], + "outputs": [ + { + "internalType": "uint256", + "name": "sentAmount", + "type": "uint256" + } + ], "stateMutability": "nonpayable", "type": "function" } diff --git a/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json b/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json index 234a7f943..2d58f750e 100644 --- a/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json +++ b/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json @@ -43,8 +43,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b50604051610974380380610974833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b61085d806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212205d952e3358213844ef60215f35b3c3adb68dbc657522a8dd683eb1c5c0f64bfa64736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212205d952e3358213844ef60215f35b3c3adb68dbc657522a8dd683eb1c5c0f64bfa64736f6c63430008180033", + "bytecode": "0x608060405234801561001057600080fd5b50604051610974380380610974833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b61085d806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212203da3b9141c515078ba917a5b792ee843396b82d45e2ef60e0d6307c236e8c30664736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212203da3b9141c515078ba917a5b792ee843396b82d45e2ef60e0d6307c236e8c30664736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json b/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json index 1d44a675c..5b0046040 100644 --- a/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json +++ b/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json @@ -43,8 +43,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b50604051610877380380610877833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b610760806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea26469706673582212206bab9cbf21b89041a55ee0f768a9443ae5e5ebfde23fe8a91daf9d4b339427db64736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea26469706673582212206bab9cbf21b89041a55ee0f768a9443ae5e5ebfde23fe8a91daf9d4b339427db64736f6c63430008180033", + "bytecode": "0x608060405234801561001057600080fd5b50604051610877380380610877833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b610760806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea2646970667358221220bd148fba67bf9e1966835ecfba5be560625fcf8c88f7890050149168488a782364736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea2646970667358221220bd148fba67bf9e1966835ecfba5be560625fcf8c88f7890050149168488a782364736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/x/evm/embeds/contracts/IFunToken.sol b/x/evm/embeds/contracts/IFunToken.sol index 73fb0ed7f..b571c0d00 100644 --- a/x/evm/embeds/contracts/IFunToken.sol +++ b/x/evm/embeds/contracts/IFunToken.sol @@ -5,11 +5,18 @@ pragma solidity >=0.8.19; /// coins to a Nibiru bech32 address using the "FunToken" mapping between the /// ERC20 and bank. interface IFunToken { - /// @dev bankSend sends ERC20 tokens as coins to a Nibiru base account - /// @param erc20 the address of the ERC20 token contract - /// @param amount the amount of tokens to send - /// @param to the receiving Nibiru base account address as a string - function bankSend(address erc20, uint256 amount, string memory to) external; + /// @dev bankSend sends ERC20 tokens as coins to a Nibiru base account + /// @param erc20 - the address of the ERC20 token contract + /// @param amount - the amount of tokens to send + /// @param to - the receiving Nibiru base account address as a string + /// @return sentAmount - amount of tokens received by the recipient. This may + /// not be equal to `amount` if the corresponding ERC20 contract has a fee or + /// deduction on transfer. + function bankSend( + address erc20, + uint256 amount, + string memory to + ) external returns (uint256 sentAmount); } address constant FUNTOKEN_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000800; diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go index 328452ecf..06d2e5ab3 100644 --- a/x/evm/keeper/erc20.go +++ b/x/evm/keeper/erc20.go @@ -73,23 +73,53 @@ Transfer implements "ERC20.transfer" func (e erc20Calls) Transfer( contract, from, to gethcommon.Address, amount *big.Int, ctx sdk.Context, -) (out bool, err error) { +) (balanceIncrease *big.Int, err error) { + recipientBalanceBefore, err := e.BalanceOf(contract, to, ctx) + if err != nil { + return balanceIncrease, errors.Wrap(err, "failed to retrieve recipient balance") + } + input, err := e.ABI.Pack("transfer", to, amount) if err != nil { - return false, fmt.Errorf("failed to pack ABI args: %w", err) + return balanceIncrease, fmt.Errorf("failed to pack ABI args: %w", err) } + resp, _, err := e.CallContractWithInput(ctx, from, &contract, true, input) if err != nil { - return false, err + return balanceIncrease, err } var erc20Bool ERC20Bool err = e.ABI.UnpackIntoInterface(&erc20Bool, "transfer", resp.Ret) if err != nil { - return false, err + return balanceIncrease, err + } + + // Handle the case of success=false: https://github.com/NibiruChain/nibiru/issues/2080 + success := erc20Bool.Value + if !success { + return balanceIncrease, fmt.Errorf("transfer executed but returned success=false") + } + + recipientBalanceAfter, err := e.BalanceOf(contract, to, ctx) + if err != nil { + return balanceIncrease, errors.Wrap(err, "failed to retrieve recipient balance") + } + + balanceIncrease = new(big.Int).Sub(recipientBalanceAfter, recipientBalanceBefore) + + // For flexibility with fee on transfer tokens and other types of deductions, + // we cannot assume that the amount received by the recipient is equal to + // the call "amount". Instead, verify that the recipient got tokens and + // return the amount. + if balanceIncrease.Sign() <= 0 { + return balanceIncrease, fmt.Errorf( + "amount of ERC20 tokens received MUST be positive: the balance of recipient %s would've changed by %v for token %s", + to.Hex(), balanceIncrease.String(), contract.Hex(), + ) } - return erc20Bool.Value, nil + return balanceIncrease, err } // BalanceOf retrieves the balance of an ERC20 token for a specific account. diff --git a/x/evm/keeper/erc20_test.go b/x/evm/keeper/erc20_test.go index 4b1dc10fa..c45ed10a1 100644 --- a/x/evm/keeper/erc20_test.go +++ b/x/evm/keeper/erc20_test.go @@ -34,7 +34,8 @@ func (s *Suite) TestERC20Calls() { s.T().Log("Transfer - Not enough funds") { - _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, big.NewInt(9_420), deps.Ctx) + amt := big.NewInt(9_420) + _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx) s.ErrorContains(err, "ERC20: transfer amount exceeds balance") // balances unchanged evmtest.AssertERC20BalanceEqual(s.T(), deps, contract, deps.Sender.EthAddr, big.NewInt(0)) @@ -43,10 +44,16 @@ func (s *Suite) TestERC20Calls() { s.T().Log("Transfer - Success (sanity check)") { - _, err := deps.EvmKeeper.ERC20().Transfer(contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, big.NewInt(9_420), deps.Ctx) + amt := big.NewInt(9_420) + sentAmt, err := deps.EvmKeeper.ERC20().Transfer( + contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, amt, deps.Ctx, + ) s.Require().NoError(err) - evmtest.AssertERC20BalanceEqual(s.T(), deps, contract, deps.Sender.EthAddr, big.NewInt(9_420)) - evmtest.AssertERC20BalanceEqual(s.T(), deps, contract, evm.EVM_MODULE_ADDRESS, big.NewInt(60_000)) + evmtest.AssertERC20BalanceEqual( + s.T(), deps, contract, deps.Sender.EthAddr, big.NewInt(9_420)) + evmtest.AssertERC20BalanceEqual( + s.T(), deps, contract, evm.EVM_MODULE_ADDRESS, big.NewInt(60_000)) + s.Require().Equal(sentAmt.String(), amt.String()) } s.T().Log("Burn tokens - Allowed as non-owner") diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index be8abb236..ec13c0709 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -491,22 +491,27 @@ func (k *Keeper) ConvertCoinToEvm( fungibleTokenMapping := funTokens[0] if fungibleTokenMapping.IsMadeFromCoin { - return k.convertCoinNativeCoin(ctx, sender, msg.ToEthAddr.Address, msg.BankCoin, fungibleTokenMapping) + return k.convertCoinToEvmBornCoin( + ctx, sender, msg.ToEthAddr.Address, msg.BankCoin, fungibleTokenMapping, + ) } else { - return k.convertCoinNativeERC20(ctx, sender, msg.ToEthAddr.Address, msg.BankCoin, fungibleTokenMapping) + return k.convertCoinToEvmBornERC20( + ctx, sender, msg.ToEthAddr.Address, msg.BankCoin, fungibleTokenMapping, + ) } } -// Converts a native coin to an ERC20 token. -// EVM module owns the ERC-20 contract and can mint the ERC-20 tokens. -func (k Keeper) convertCoinNativeCoin( +// Converts Bank Coins for FunToken mapping that was born from a coin +// (IsMadeFromCoin=true) into the ERC20 tokens. EVM module owns the ERC-20 +// contract and can mint the ERC-20 tokens. +func (k Keeper) convertCoinToEvmBornCoin( ctx sdk.Context, sender sdk.AccAddress, recipient gethcommon.Address, coin sdk.Coin, funTokenMapping evm.FunToken, ) (*evm.MsgConvertCoinToEvmResponse, error) { - // Step 1: Escrow bank coins with EVM module account + // Step 1: Send Bank Coins to the EVM module err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, evm.ModuleName, sdk.NewCoins(coin)) if err != nil { return nil, errors.Wrap(err, "failed to send coins to module account") @@ -514,7 +519,7 @@ func (k Keeper) convertCoinNativeCoin( erc20Addr := funTokenMapping.Erc20Addr.Address - // Step 2: mint ERC-20 tokens for recipient + // Step 2: Mint ERC20 tokens to the recipient evmResp, err := k.CallContract( ctx, embeds.SmartContract_ERC20Minter.ABI, @@ -542,10 +547,11 @@ func (k Keeper) convertCoinNativeCoin( return &evm.MsgConvertCoinToEvmResponse{}, nil } -// Converts a coin that was originally an ERC20 token, and that was converted to a bank coin, back to an ERC20 token. -// EVM module does not own the ERC-20 contract and cannot mint the ERC-20 tokens. -// EVM module has escrowed tokens in the first conversion from ERC-20 to bank coin. -func (k Keeper) convertCoinNativeERC20( +// Converts a coin that was originally an ERC20 token, and that was converted to +// a bank coin, back to an ERC20 token. EVM module does not own the ERC-20 +// contract and cannot mint the ERC-20 tokens. EVM module has escrowed tokens in +// the first conversion from ERC-20 to bank coin. +func (k Keeper) convertCoinToEvmBornERC20( ctx sdk.Context, sender sdk.AccAddress, recipient gethcommon.Address, @@ -553,44 +559,26 @@ func (k Keeper) convertCoinNativeERC20( funTokenMapping evm.FunToken, ) (*evm.MsgConvertCoinToEvmResponse, error) { erc20Addr := funTokenMapping.Erc20Addr.Address - - recipientBalanceBefore, err := k.ERC20().BalanceOf(erc20Addr, recipient, ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to retrieve balance") - } - if recipientBalanceBefore == nil { - return nil, fmt.Errorf("failed to retrieve balance, balance is nil") - } - - // Escrow Coins on module account + // 1 | Caller transfers Bank Coins to be converted to ERC20 tokens. if err := k.bankKeeper.SendCoinsFromAccountToModule( ctx, sender, evm.ModuleName, sdk.NewCoins(coin), ); err != nil { - return nil, errors.Wrap(err, "failed to escrow coins") + return nil, errors.Wrap(err, "error sending Bank Coins to the EVM") } - // verify that the EVM module account has enough escrowed ERC-20 to transfer - // should never fail, because the coins were minted from the escrowed tokens, but check just in case - evmModuleBalance, err := k.ERC20().BalanceOf( - erc20Addr, - evm.EVM_MODULE_ADDRESS, - ctx, - ) - if err != nil { - return nil, errors.Wrap(err, "failed to retrieve balance") - } - if evmModuleBalance == nil { - return nil, fmt.Errorf("failed to retrieve balance, balance is nil") - } - if evmModuleBalance.Cmp(coin.Amount.BigInt()) < 0 { - return nil, fmt.Errorf("insufficient balance in EVM module account") - } - - // unescrow ERC-20 tokens from EVM module address - res, err := k.ERC20().Transfer( + // 2 | EVM sends ERC20 tokens to the "to" account. + // This should never fail due to the EVM account lacking ERc20 fund because + // the an account must have sent the EVM module ERC20 tokens in the mapping + // in order to create the coins originally. + // + // Said another way, if an asset is created as an ERC20 and some amount is + // converted to its Bank Coin representation, a balance of the ERC20 is left + // inside the EVM module account in order to convert the coins back to + // ERC20s. + actualSentAmount, err := k.ERC20().Transfer( erc20Addr, evm.EVM_MODULE_ADDRESS, recipient, @@ -598,37 +586,25 @@ func (k Keeper) convertCoinNativeERC20( ctx, ) if err != nil { - return nil, errors.Wrap(err, "failed to transfer ERC20 tokens") - } - if !res { - return nil, fmt.Errorf("failed to transfer ERC20 tokens") - } - - // Check expected Receiver balance after transfer execution - recipientBalanceAfter, err := k.ERC20().BalanceOf(erc20Addr, recipient, ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to retrieve balance") - } - if recipientBalanceAfter == nil { - return nil, fmt.Errorf("failed to retrieve balance, balance is nil") + return nil, errors.Wrap(err, "failed to transfer ERC-20 tokens") } - expectedFinalBalance := big.NewInt(0).Add(recipientBalanceBefore, coin.Amount.BigInt()) - if r := recipientBalanceAfter.Cmp(expectedFinalBalance); r != 0 { - return nil, fmt.Errorf("expected balance after transfer to be %s, got %s", expectedFinalBalance, recipientBalanceAfter) - } - - // Burn escrowed Coins - err = k.bankKeeper.BurnCoins(ctx, evm.ModuleName, sdk.NewCoins(coin)) + // 3 | In the FunToken ERC20 → BC conversion process that preceded this + // TxMsg, the Bank Coins were minted. Consequently, to preserve an invariant + // on the sum of the FunToken's bank and ERC20 supply, we burn the coins here + // in the BC → ERC20 conversion. + burnCoin := sdk.NewCoin(coin.Denom, sdk.NewIntFromBigInt(actualSentAmount)) + err = k.bankKeeper.BurnCoins(ctx, evm.ModuleName, sdk.NewCoins(burnCoin)) if err != nil { return nil, errors.Wrap(err, "failed to burn coins") } + // Emit event with the actual amount received _ = ctx.EventManager().EmitTypedEvent(&evm.EventConvertCoinToEvm{ Sender: sender.String(), Erc20ContractAddress: funTokenMapping.Erc20Addr.String(), ToEthAddr: recipient.String(), - BankCoin: coin, + BankCoin: burnCoin, }) return &evm.MsgConvertCoinToEvmResponse{}, nil diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index 69e756ed3..e9ccaee82 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -143,20 +143,19 @@ func (p precompileFunToken) bankSend( // Caller transfers ERC20 to the EVM account transferTo := evm.EVM_MODULE_ADDRESS - _, err = p.evmKeeper.ERC20().Transfer(erc20, caller, transferTo, amount, ctx) + gotAmount, err := p.evmKeeper.ERC20().Transfer(erc20, caller, transferTo, amount, ctx) if err != nil { - return nil, fmt.Errorf("failed to send from caller to the EVM account: %w", err) + return nil, fmt.Errorf("error in ERC20.transfer from caller to EVM account: %w", err) } // EVM account mints FunToken.BankDenom to module account - amt := math.NewIntFromBigInt(amount) - coinToSend := sdk.NewCoin(funtoken.BankDenom, amt) + coinToSend := sdk.NewCoin(funtoken.BankDenom, math.NewIntFromBigInt(gotAmount)) if funtoken.IsMadeFromCoin { // If the FunToken mapping was created from a bank coin, then the EVM account // owns the ERC20 contract and was the original minter of the ERC20 tokens. // Since we're sending them away and want accurate total supply tracking, the // tokens need to be burned. - _, err = p.evmKeeper.ERC20().Burn(erc20, evm.EVM_MODULE_ADDRESS, amount, ctx) + _, err = p.evmKeeper.ERC20().Burn(erc20, evm.EVM_MODULE_ADDRESS, gotAmount, ctx) if err != nil { err = fmt.Errorf("ERC20.Burn: %w", err) return @@ -187,7 +186,7 @@ func (p precompileFunToken) bankSend( // TODO: UD-DEBUG: feat: Emit EVM events - return method.Outputs.Pack() + return method.Outputs.Pack(gotAmount) } func SafeMintCoins( diff --git a/x/evm/precompile/funtoken_test.go b/x/evm/precompile/funtoken_test.go index dd5176fb3..fc51a47f5 100644 --- a/x/evm/precompile/funtoken_test.go +++ b/x/evm/precompile/funtoken_test.go @@ -126,18 +126,32 @@ func (s *FuntokenSuite) TestHappyPath() { input, err := embeds.SmartContract_FunToken.ABI.Pack(string(precompile.FunTokenMethod_BankSend), callArgs...) s.NoError(err) - _, resp, err := evmtest.CallContractTx( + _, ethTxResp, err := evmtest.CallContractTx( &deps, precompile.PrecompileAddr_FunToken, input, deps.Sender, ) s.Require().NoError(err) - s.Require().Empty(resp.VmError) + s.Require().Empty(ethTxResp.VmError) - evmtest.AssertERC20BalanceEqual(s.T(), deps, erc20, deps.Sender.EthAddr, big.NewInt(69_000)) - evmtest.AssertERC20BalanceEqual(s.T(), deps, erc20, evm.EVM_MODULE_ADDRESS, big.NewInt(0)) + evmtest.AssertERC20BalanceEqual( + s.T(), deps, erc20, deps.Sender.EthAddr, big.NewInt(69_000), + ) + evmtest.AssertERC20BalanceEqual( + s.T(), deps, erc20, evm.EVM_MODULE_ADDRESS, big.NewInt(0), + ) s.Equal(sdk.NewInt(420).String(), deps.App.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.String(), ) + + s.T().Log("Parse the response contract addr and response bytes") + var sentAmt *big.Int + err = embeds.SmartContract_FunToken.ABI.UnpackIntoInterface( + &sentAmt, + string(precompile.FunTokenMethod_BankSend), + ethTxResp.Ret, + ) + s.NoError(err) + s.Require().Equal("420", sentAmt.String()) } From 7b7beb7b53a537a8ad1462cf8ca5520e21e4978c Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:09:25 +0100 Subject: [PATCH 04/12] feat: add validation for multi message execution wasm (#2092) * feat: add validation for multi message execution wasm * chore: changelog * merge conflicts + simplify --------- Co-authored-by: Unique-Divine --- CHANGELOG.md | 1 + x/evm/precompile/wasm.go | 12 ++- x/evm/precompile/wasm_test.go | 183 ++++++++++++++++++++++++++++++++++ x/evm/statedb/statedb.go | 3 - 4 files changed, 193 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61dc41b07..23dcb15d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ reverts inside of a try-catch. for (1) ERC20 transfers with tokens that return false success values instead of throwing an error and (2) ERC20 transfers with other operations that don't bring about the expected resulting balance for the transfer recipient. +- [#2092](https://github.com/NibiruChain/nibiru/pull/2092) - feat(evm): add validation for wasm multi message execution #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/x/evm/precompile/wasm.go b/x/evm/precompile/wasm.go index a7b21684c..f19511cb9 100644 --- a/x/evm/precompile/wasm.go +++ b/x/evm/precompile/wasm.go @@ -10,6 +10,7 @@ import ( "github.com/NibiruChain/nibiru/v2/x/evm/embeds" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasm "github.com/CosmWasm/wasmd/x/wasm/types" gethabi "github.com/ethereum/go-ethereum/accounts/abi" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -275,10 +276,15 @@ func (p precompileWasm) executeMulti( callerBech32 := eth.EthAddrToNibiruAddr(caller) var responses [][]byte - for _, m := range wasmExecMsgs { + for i, m := range wasmExecMsgs { wasmContract, e := sdk.AccAddressFromBech32(m.ContractAddr) if e != nil { - err = fmt.Errorf("Execute failed: %w", e) + err = fmt.Errorf("Execute failed at index %d: %w", i, e) + return + } + msgArgsCopy := wasm.RawContractMessage(m.MsgArgs) + if e := msgArgsCopy.ValidateBasic(); e != nil { + err = fmt.Errorf("Execute failed at index %d: error parsing msg args: %w", i, e) return } var funds sdk.Coins @@ -290,7 +296,7 @@ func (p precompileWasm) executeMulti( } respBz, e := p.Wasm.Execute(ctx, wasmContract, callerBech32, m.MsgArgs, funds) if e != nil { - err = e + err = fmt.Errorf("Execute failed at index %d: %w", i, e) return } responses = append(responses, respBz) diff --git a/x/evm/precompile/wasm_test.go b/x/evm/precompile/wasm_test.go index dbe35b839..72c45046c 100644 --- a/x/evm/precompile/wasm_test.go +++ b/x/evm/precompile/wasm_test.go @@ -8,6 +8,7 @@ import ( wasm "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/NibiruChain/nibiru/v2/x/common/testutil" + "github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" "github.com/NibiruChain/nibiru/v2/x/evm/evmtest" "github.com/NibiruChain/nibiru/v2/x/evm/precompile" @@ -313,3 +314,185 @@ func (s *WasmSuite) TestSadArgsExecute() { }) } } + +type WasmExecuteMsg struct { + ContractAddr string `json:"contractAddr"` + MsgArgs []byte `json:"msgArgs"` + Funds []precompile.WasmBankCoin `json:"funds"` +} + +func (s *WasmSuite) TestExecuteMultiValidation() { + deps := evmtest.NewTestDeps() + + s.Require().NoError(testapp.FundAccount( + deps.App.BankKeeper, + deps.Ctx, + deps.Sender.NibiruAddr, + sdk.NewCoins(sdk.NewCoin("unibi", sdk.NewInt(100))), + )) + + wasmContracts := test.SetupWasmContracts(&deps, &s.Suite) + wasmContract := wasmContracts[1] // hello_world_counter.wasm + + invalidMsgArgsBz := []byte(`{"invalid": "json"}`) // Invalid message format + validMsgArgsBz := []byte(`{"increment": {}}`) // Valid increment message + + var emptyFunds []precompile.WasmBankCoin + validFunds := []precompile.WasmBankCoin{{ + Denom: "unibi", + Amount: big.NewInt(100), + }} + invalidFunds := []precompile.WasmBankCoin{{ + Denom: "invalid!denom", + Amount: big.NewInt(100), + }} + + testCases := []struct { + name string + executeMsgs []WasmExecuteMsg + wantError string + }{ + { + name: "valid - single message", + executeMsgs: []WasmExecuteMsg{ + { + ContractAddr: wasmContract.String(), + MsgArgs: validMsgArgsBz, + Funds: emptyFunds, + }, + }, + wantError: "", + }, + { + name: "valid - multiple messages", + executeMsgs: []WasmExecuteMsg{ + { + ContractAddr: wasmContract.String(), + MsgArgs: validMsgArgsBz, + Funds: validFunds, + }, + { + ContractAddr: wasmContract.String(), + MsgArgs: validMsgArgsBz, + Funds: emptyFunds, + }, + }, + wantError: "", + }, + { + name: "invalid - malformed contract address", + executeMsgs: []WasmExecuteMsg{ + { + ContractAddr: "invalid-address", + MsgArgs: validMsgArgsBz, + Funds: emptyFunds, + }, + }, + wantError: "decoding bech32 failed", + }, + { + name: "invalid - malformed message args", + executeMsgs: []WasmExecuteMsg{ + { + ContractAddr: wasmContract.String(), + MsgArgs: invalidMsgArgsBz, + Funds: emptyFunds, + }, + }, + wantError: "unknown variant", + }, + { + name: "invalid - malformed funds", + executeMsgs: []WasmExecuteMsg{ + { + ContractAddr: wasmContract.String(), + MsgArgs: validMsgArgsBz, + Funds: invalidFunds, + }, + }, + wantError: "invalid coins", + }, + { + name: "invalid - second message fails validation", + executeMsgs: []WasmExecuteMsg{ + { + ContractAddr: wasmContract.String(), + MsgArgs: validMsgArgsBz, + Funds: emptyFunds, + }, + { + ContractAddr: wasmContract.String(), + MsgArgs: invalidMsgArgsBz, + Funds: emptyFunds, + }, + }, + wantError: "unknown variant", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + callArgs := []any{tc.executeMsgs} + input, err := embeds.SmartContract_Wasm.ABI.Pack( + string(precompile.WasmMethod_executeMulti), + callArgs..., + ) + s.Require().NoError(err) + + ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( + deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + ) + + if tc.wantError != "" { + s.Require().ErrorContains(err, tc.wantError) + return + } + s.Require().NoError(err) + s.NotNil(ethTxResp) + s.NotEmpty(ethTxResp.Ret) + }) + } +} + +// TestExecuteMultiPartialExecution ensures that no state changes occur if any message +// in the batch fails validation +func (s *WasmSuite) TestExecuteMultiPartialExecution() { + deps := evmtest.NewTestDeps() + wasmContracts := test.SetupWasmContracts(&deps, &s.Suite) + wasmContract := wasmContracts[1] // hello_world_counter.wasm + + // First verify initial state is 0 + test.AssertWasmCounterState(&s.Suite, deps, wasmContract, 0) + + // Create a batch where the second message will fail validation + executeMsgs := []WasmExecuteMsg{ + { + ContractAddr: wasmContract.String(), + MsgArgs: []byte(`{"increment": {}}`), + Funds: []precompile.WasmBankCoin{}, + }, + { + ContractAddr: wasmContract.String(), + MsgArgs: []byte(`{"invalid": "json"}`), // This will fail validation + Funds: []precompile.WasmBankCoin{}, + }, + } + + callArgs := []any{executeMsgs} + input, err := embeds.SmartContract_Wasm.ABI.Pack( + string(precompile.WasmMethod_executeMulti), + callArgs..., + ) + s.Require().NoError(err) + + ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( + deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + ) + + // Verify that the call failed + s.Require().Error(err, "ethTxResp: ", ethTxResp) + s.Require().Contains(err.Error(), "unknown variant") + + // Verify that no state changes occurred + test.AssertWasmCounterState(&s.Suite, deps, wasmContract, 0) +} diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index 4c79e61af..a411660f9 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -480,9 +480,6 @@ func (s *StateDB) Snapshot() int { // RevertToSnapshot reverts all state changes made since the given revision. func (s *StateDB) RevertToSnapshot(revid int) { - fmt.Printf("len(s.validRevisions): %d\n", len(s.validRevisions)) - fmt.Printf("s.validRevisions: %v\n", s.validRevisions) - // Find the snapshot in the stack of valid snapshots. idx := sort.Search(len(s.validRevisions), func(i int) bool { return s.validRevisions[i].id >= revid From 0afb08f403baffc6e61046f3ad0774f64e7d14c4 Mon Sep 17 00:00:00 2001 From: Kevin Yang <5478483+k-yang@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:48:29 -0700 Subject: [PATCH 05/12] refactor: general code style cleanups on precompile and statedb journal (#2100) * statedb: add cacheing for multistore before precompile runs * messy, working first version that allows for precompile reversion * wip!: Save checkpoint. 1. Created NibiruBankKeeper with safety around NIBI transfers inside of EthereumTx. 2. The "PrecompileCalled" JournalChange now has a propery implementation and a strong test case to show that reverting the precompile calls works as intended. 3. Remove unneeded functions created for testing with low-level struct fields. * chore: changelog * finalize bank keeper changes * revert to previous commit 7f904a07ac4d5555d8c088411024fc50ff65d085 * fix strange ignored file issue * remove new bank keeper * chore: comments from self-review * refactor: clean up test code * refactor: clean up parse fund args * refactor: clean up common precompile functions * refactor: clean up precompile onrunstart * refactor: clean up precompile onrunstart * refactor: clean up oracle precompile * fix: import * Delete .gitignore * Update CHANGELOG.md * refactor: replace interface{} with any * refactor: add ABI() precompile fn * refactor: replace assertNotReadonlyTx --------- Co-authored-by: Unique-Divine --- CHANGELOG.md | 7 +-- app/server/config/server_config.go | 2 +- cmd/nibid/cmd/base64.go | 2 +- cmd/nibid/cmd/decode_base64.go | 8 +-- eth/eip712/eip712_legacy.go | 10 ++-- eth/eip712/encoding_legacy.go | 4 +- eth/eip712/message.go | 4 +- eth/rpc/backend/blocks.go | 8 +-- eth/rpc/backend/node_info.go | 4 +- eth/rpc/backend/tracing.go | 8 +-- eth/rpc/backend/utils.go | 2 +- eth/rpc/rpc.go | 6 +-- eth/rpc/rpcapi/debugapi/api.go | 4 +- eth/rpc/rpcapi/eth_api.go | 20 ++++---- eth/rpc/rpcapi/eth_filters_api.go | 2 +- eth/rpc/rpcapi/websockets.go | 34 ++++++------- x/common/testutil/nullify.go | 2 +- x/common/testutil/testnetwork/logger.go | 4 +- x/devgas/v1/types/params.go | 6 +-- x/epochs/types/identifier.go | 2 +- x/evm/errors.go | 2 +- x/evm/keeper/grpc_query.go | 4 +- x/evm/params.go | 4 +- x/evm/precompile/.gitignore | 17 ------- x/evm/precompile/errors.go | 16 +++--- x/evm/precompile/funtoken.go | 28 ++++------- x/evm/precompile/oracle.go | 21 ++++---- x/evm/precompile/precompile.go | 43 ++++++++-------- x/evm/precompile/test/export.go | 63 +++++++++-------------- x/evm/precompile/wasm.go | 57 +++++++++++---------- x/evm/precompile/wasm_parse.go | 66 +++++++++++-------------- x/evm/statedb/journal_test.go | 27 +++++----- x/evm/statedb/statedb.go | 7 ++- x/evm/vmtracer.go | 4 +- x/inflation/types/params.go | 12 ++--- x/oracle/types/hash.go | 2 +- x/tokenfactory/types/codec.go | 2 +- 37 files changed, 230 insertions(+), 284 deletions(-) delete mode 100644 x/evm/precompile/.gitignore diff --git a/CHANGELOG.md b/CHANGELOG.md index 23dcb15d1..88fa93ee9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,9 +63,9 @@ committed as expected, fixes the `StateDB.Commit` to follow its guidelines more closely, and solves for a critical state inconsistency producible from the FunToken.sol precompiled contract. It also aligns the precompiles to use consistent setup and dynamic gas calculations, addressing the following tickets. - - https://github.com/NibiruChain/nibiru/issues/2083 - - https://github.com/code-423n4/2024-10-nibiru-zenith/issues/43 - - https://github.com/code-423n4/2024-10-nibiru-zenith/issues/47 + - + - + - - [#2088](https://github.com/NibiruChain/nibiru/pull/2088) - refactor(evm): remove outdated comment and improper error message text - [#2089](https://github.com/NibiruChain/nibiru/pull/2089) - better handling of gas consumption within erc20 contract execution - [#2091](https://github.com/NibiruChain/nibiru/pull/2091) - feat(evm): add fun token creation fee validation @@ -163,6 +163,7 @@ about the expected resulting balance for the transfer recipient. - [#2060](https://github.com/NibiruChain/nibiru/pull/2060) - fix(evm-precompiles): add assertNumArgs validation - [#2056](https://github.com/NibiruChain/nibiru/pull/2056) - feat(evm): add oracle precompile - [#2065](https://github.com/NibiruChain/nibiru/pull/2065) - refactor(evm)!: Refactor out dead code from the evm.Params +- [#2100](https://github.com/NibiruChain/nibiru/pull/2100) - refactor: cleanup statedb and precompile sections ### State Machine Breaking (Other) diff --git a/app/server/config/server_config.go b/app/server/config/server_config.go index b72638ed2..f393983a9 100644 --- a/app/server/config/server_config.go +++ b/app/server/config/server_config.go @@ -174,7 +174,7 @@ type TLSConfig struct { // AppConfig helps to override default appConfig template and configs. // return "", nil if no custom configuration is required for the application. -func AppConfig(denom string) (string, interface{}) { +func AppConfig(denom string) (string, any) { // Optionally allow the chain developer to overwrite the SDK's default // server config. customAppConfig := DefaultConfig() diff --git a/cmd/nibid/cmd/base64.go b/cmd/nibid/cmd/base64.go index 5f235d3ea..ba5685aff 100644 --- a/cmd/nibid/cmd/base64.go +++ b/cmd/nibid/cmd/base64.go @@ -33,7 +33,7 @@ func GetBuildWasmMsg() *cobra.Command { Value string `json:"value,omitempty"` } - js, err := json.Marshal(map[string]interface{}{ + js, err := json.Marshal(map[string]any{ "stargate": stargateMessage{ TypeURL: anyMsg.TypeUrl, Value: base64.StdEncoding.EncodeToString(anyMsg.Value), diff --git a/cmd/nibid/cmd/decode_base64.go b/cmd/nibid/cmd/decode_base64.go index 3de3706f2..8625070c3 100644 --- a/cmd/nibid/cmd/decode_base64.go +++ b/cmd/nibid/cmd/decode_base64.go @@ -27,7 +27,7 @@ import ( // from the provided JSON data. // - err error: An error object, which is nil if the operation is successful. func YieldStargateMsgs(jsonBz []byte) (sgMsgs []wasmvm.StargateMsg, err error) { - var data interface{} + var data any if err := json.Unmarshal(jsonBz, &data); err != nil { return sgMsgs, err } @@ -50,7 +50,7 @@ func YieldStargateMsgs(jsonBz []byte) (sgMsgs []wasmvm.StargateMsg, err error) { // encoded base 64 string. func parseStargateMsgs(jsonData any, msgs *[]wasmvm.StargateMsg) { switch v := jsonData.(type) { - case map[string]interface{}: + case map[string]any: if typeURL, ok := v["type_url"].(string); ok { if value, ok := v["value"].(string); ok { *msgs = append(*msgs, wasmvm.StargateMsg{ @@ -62,7 +62,7 @@ func parseStargateMsgs(jsonData any, msgs *[]wasmvm.StargateMsg) { for _, value := range v { parseStargateMsgs(value, msgs) } - case []interface{}: + case []any: for _, value := range v { parseStargateMsgs(value, msgs) } @@ -93,7 +93,7 @@ func DecodeBase64StargateMsgs( ) (newSgMsgs []StargateMsgDecoded, err error) { codec := clientCtx.Codec - var data interface{} + var data any if err := json.Unmarshal(jsonBz, &data); err != nil { return newSgMsgs, fmt.Errorf( "failed to decode stargate msgs due to invalid JSON: %w", err) diff --git a/eth/eip712/eip712_legacy.go b/eth/eip712/eip712_legacy.go index c1d0b1b30..b50f10e5f 100644 --- a/eth/eip712/eip712_legacy.go +++ b/eth/eip712/eip712_legacy.go @@ -38,7 +38,7 @@ func LegacyWrapTxToTypedData( data []byte, feeDelegation *FeeDelegationOptions, ) (apitypes.TypedData, error) { - txData := make(map[string]interface{}) + txData := make(map[string]any) if err := json.Unmarshal(data, &txData); err != nil { return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data") @@ -58,7 +58,7 @@ func LegacyWrapTxToTypedData( } if feeDelegation != nil { - feeInfo, ok := txData["fee"].(map[string]interface{}) + feeInfo, ok := txData["fee"].(map[string]any) if !ok { return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrInvalidType, "cannot parse fee from tx data") } @@ -139,7 +139,7 @@ func extractMsgTypes(cdc codectypes.AnyUnpacker, msgTypeName string, msg sdk.Msg return rootTypes, nil } -func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType string, in interface{}) (err error) { +func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType string, in any) (err error) { defer doRecover(&err) t := reflect.TypeOf(in) @@ -161,8 +161,8 @@ func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType str } type CosmosAnyWrapper struct { - Type string `json:"type"` - Value interface{} `json:"value"` + Type string `json:"type"` + Value any `json:"value"` } // legacyTraverseFields: Recursively inspects the fields of a given diff --git a/eth/eip712/encoding_legacy.go b/eth/eip712/encoding_legacy.go index 805eb48dd..23f943eaf 100644 --- a/eth/eip712/encoding_legacy.go +++ b/eth/eip712/encoding_legacy.go @@ -17,8 +17,8 @@ import ( ) type aminoMessage struct { - Type string `json:"type"` - Value interface{} `json:"value"` + Type string `json:"type"` + Value any `json:"value"` } // LegacyGetEIP712BytesForMsg returns the EIP-712 object bytes for the given SignDoc bytes by decoding the bytes into diff --git a/eth/eip712/message.go b/eth/eip712/message.go index 6a8577c22..176d90b56 100644 --- a/eth/eip712/message.go +++ b/eth/eip712/message.go @@ -14,7 +14,7 @@ import ( type eip712MessagePayload struct { payload gjson.Result numPayloadMsgs int - message map[string]interface{} + message map[string]any } const ( @@ -34,7 +34,7 @@ func createEIP712MessagePayload(data []byte) (eip712MessagePayload, error) { return eip712MessagePayload{}, errorsmod.Wrap(err, "failed to flatten payload JSON messages") } - message, ok := payload.Value().(map[string]interface{}) + message, ok := payload.Value().(map[string]any) if !ok { return eip712MessagePayload{}, errorsmod.Wrap(errortypes.ErrInvalidType, "failed to parse JSON as map") } diff --git a/eth/rpc/backend/blocks.go b/eth/rpc/backend/blocks.go index a64e73e2a..7bc5f4b97 100644 --- a/eth/rpc/backend/blocks.go +++ b/eth/rpc/backend/blocks.go @@ -57,7 +57,7 @@ func (b *Backend) BlockNumber() (hexutil.Uint64, error) { // GetBlockByNumber returns the JSON-RPC compatible Ethereum block identified by // block number. Depending on fullTx it either returns the full transaction // objects or if false only the hashes of the transactions. -func (b *Backend) GetBlockByNumber(blockNum rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (b *Backend) GetBlockByNumber(blockNum rpc.BlockNumber, fullTx bool) (map[string]any, error) { resBlock, err := b.TendermintBlockByNumber(blockNum) if err != nil { return nil, nil @@ -85,7 +85,7 @@ func (b *Backend) GetBlockByNumber(blockNum rpc.BlockNumber, fullTx bool) (map[s // GetBlockByHash returns the JSON-RPC compatible Ethereum block identified by // hash. -func (b *Backend) GetBlockByHash(hash gethcommon.Hash, fullTx bool) (map[string]interface{}, error) { +func (b *Backend) GetBlockByHash(hash gethcommon.Hash, fullTx bool) (map[string]any, error) { resBlock, err := b.TendermintBlockByHash(hash) if err != nil { return nil, err @@ -348,8 +348,8 @@ func (b *Backend) RPCBlockFromTendermintBlock( resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool, -) (map[string]interface{}, error) { - ethRPCTxs := []interface{}{} +) (map[string]any, error) { + ethRPCTxs := []any{} block := resBlock.Block baseFeeWei, err := b.BaseFeeWei(blockRes) diff --git a/eth/rpc/backend/node_info.go b/eth/rpc/backend/node_info.go index 402578dd5..e95488b2a 100644 --- a/eth/rpc/backend/node_info.go +++ b/eth/rpc/backend/node_info.go @@ -39,7 +39,7 @@ func (b *Backend) Accounts() ([]gethcommon.Address, error) { // - highestBlock: block number of the highest block header this node has received from peers // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled -func (b *Backend) Syncing() (interface{}, error) { +func (b *Backend) Syncing() (any, error) { status, err := b.clientCtx.Client.Status(b.ctx) if err != nil { return false, err @@ -49,7 +49,7 @@ func (b *Backend) Syncing() (interface{}, error) { return false, nil } - return map[string]interface{}{ + return map[string]any{ "startingBlock": hexutil.Uint64(status.SyncInfo.EarliestBlockHeight), "currentBlock": hexutil.Uint64(status.SyncInfo.LatestBlockHeight), // "highestBlock": nil, // NA diff --git a/eth/rpc/backend/tracing.go b/eth/rpc/backend/tracing.go index 4a20557cd..94bb8fbba 100644 --- a/eth/rpc/backend/tracing.go +++ b/eth/rpc/backend/tracing.go @@ -18,7 +18,7 @@ import ( // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. -func (b *Backend) TraceTransaction(hash gethcommon.Hash, config *evm.TraceConfig) (interface{}, error) { +func (b *Backend) TraceTransaction(hash gethcommon.Hash, config *evm.TraceConfig) (any, error) { // Get transaction by hash transaction, err := b.GetTxByEthHash(hash) if err != nil { @@ -124,7 +124,7 @@ func (b *Backend) TraceTransaction(hash gethcommon.Hash, config *evm.TraceConfig // Response format is unknown due to custom tracer config param // More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered - var decodedResult interface{} + var decodedResult any err = json.Unmarshal(traceResult.Data, &decodedResult) if err != nil { return nil, err @@ -219,7 +219,7 @@ func (b *Backend) TraceCall( txArgs evm.JsonTxArgs, contextBlock rpc.BlockNumber, config *evm.TraceConfig, -) (interface{}, error) { +) (any, error) { blk, err := b.TendermintBlockByNumber(contextBlock) if err != nil { b.logger.Debug("block not found", "contextBlock", contextBlock) @@ -253,7 +253,7 @@ func (b *Backend) TraceCall( if err != nil { return nil, err } - var decodedResult interface{} + var decodedResult any err = json.Unmarshal(traceResult.Data, &decodedResult) if err != nil { return nil, err diff --git a/eth/rpc/backend/utils.go b/eth/rpc/backend/utils.go index 23ce2f410..bb689bcce 100644 --- a/eth/rpc/backend/utils.go +++ b/eth/rpc/backend/utils.go @@ -109,7 +109,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i // See eth_feeHistory method for more details of the return format. func (b *Backend) retrieveEVMTxFeesFromBlock( tendermintBlock *tmrpctypes.ResultBlock, - ethBlock *map[string]interface{}, + ethBlock *map[string]any, rewardPercentiles []float64, tendermintBlockResult *tmrpctypes.ResultBlockResults, targetOneFeeHistory *rpc.OneFeeHistory, diff --git a/eth/rpc/rpc.go b/eth/rpc/rpc.go index de5a97991..c6c0891de 100644 --- a/eth/rpc/rpc.go +++ b/eth/rpc/rpc.go @@ -114,9 +114,9 @@ func BlockMaxGasFromConsensusParams( // transactions. func FormatBlock( header tmtypes.Header, size int, gasLimit int64, - gasUsed *big.Int, transactions []interface{}, bloom gethcore.Bloom, + gasUsed *big.Int, transactions []any, bloom gethcore.Bloom, validatorAddr gethcommon.Address, baseFee *big.Int, -) map[string]interface{} { +) map[string]any { var transactionsRoot gethcommon.Hash if len(transactions) == 0 { transactionsRoot = gethcore.EmptyRootHash @@ -124,7 +124,7 @@ func FormatBlock( transactionsRoot = gethcommon.BytesToHash(header.DataHash) } - result := map[string]interface{}{ + result := map[string]any{ "number": hexutil.Uint64(header.Height), "hash": hexutil.Bytes(header.Hash()), "parentHash": gethcommon.BytesToHash(header.LastBlockID.Hash.Bytes()), diff --git a/eth/rpc/rpcapi/debugapi/api.go b/eth/rpc/rpcapi/debugapi/api.go index c70673273..7ce3fa345 100644 --- a/eth/rpc/rpcapi/debugapi/api.go +++ b/eth/rpc/rpcapi/debugapi/api.go @@ -65,7 +65,7 @@ func NewImplDebugAPI( // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. -func (a *DebugAPI) TraceTransaction(hash common.Hash, config *evm.TraceConfig) (interface{}, error) { +func (a *DebugAPI) TraceTransaction(hash common.Hash, config *evm.TraceConfig) (any, error) { a.logger.Debug("debug_traceTransaction", "hash", hash) return a.backend.TraceTransaction(hash, config) } @@ -115,7 +115,7 @@ func (a *DebugAPI) TraceCall( args evm.JsonTxArgs, blockNrOrHash rpc.BlockNumberOrHash, config *evm.TraceConfig, -) (interface{}, error) { +) (any, error) { a.logger.Debug("debug_traceCall", args.String(), "block number or hash", blockNrOrHash) // Get Tendermint Block diff --git a/eth/rpc/rpcapi/eth_api.go b/eth/rpc/rpcapi/eth_api.go index 62590347f..3ada30358 100644 --- a/eth/rpc/rpcapi/eth_api.go +++ b/eth/rpc/rpcapi/eth_api.go @@ -30,8 +30,8 @@ type IEthAPI interface { // // Retrieves information from a particular block in the blockchain. BlockNumber() (hexutil.Uint64, error) - GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) - GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) + GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]any, error) + GetBlockByHash(hash common.Hash, fullTx bool) (map[string]any, error) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint GetBlockTransactionCountByNumber(blockNum rpc.BlockNumber) *hexutil.Uint @@ -97,15 +97,15 @@ type IEthAPI interface { // and replaced by a canonical block instead. GetUncleByBlockHashAndIndex( hash common.Hash, idx hexutil.Uint, - ) map[string]interface{} + ) map[string]any GetUncleByBlockNumberAndIndex( number, idx hexutil.Uint, - ) map[string]interface{} + ) map[string]any GetUncleCountByBlockHash(hash common.Hash) hexutil.Uint GetUncleCountByBlockNumber(blockNum rpc.BlockNumber) hexutil.Uint // Other - Syncing() (interface{}, error) + Syncing() (any, error) GetTransactionLogs(txHash common.Hash) ([]*gethcore.Log, error) FillTransaction( args evm.JsonTxArgs, @@ -144,13 +144,13 @@ func (e *EthAPI) BlockNumber() (hexutil.Uint64, error) { } // GetBlockByNumber returns the block identified by number. -func (e *EthAPI) GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (e *EthAPI) GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]any, error) { e.logger.Debug("eth_getBlockByNumber", "number", ethBlockNum, "full", fullTx) return e.backend.GetBlockByNumber(ethBlockNum, fullTx) } // GetBlockByHash returns the block identified by hash. -func (e *EthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { +func (e *EthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]any, error) { e.logger.Debug("eth_getBlockByHash", "hash", hash.Hex(), "full", fullTx) return e.backend.GetBlockByHash(hash, fullTx) } @@ -359,7 +359,7 @@ func (e *EthAPI) ChainId() (*hexutil.Big, error) { //nolint // Always returns nil. func (e *EthAPI) GetUncleByBlockHashAndIndex( _ common.Hash, _ hexutil.Uint, -) map[string]interface{} { +) map[string]any { return nil } @@ -367,7 +367,7 @@ func (e *EthAPI) GetUncleByBlockHashAndIndex( // index. Always returns nil. func (e *EthAPI) GetUncleByBlockNumberAndIndex( _, _ hexutil.Uint, -) map[string]interface{} { +) map[string]any { return nil } @@ -396,7 +396,7 @@ func (e *EthAPI) GetUncleCountByBlockNumber(_ rpc.BlockNumber) hexutil.Uint { // - highestBlock: block number of the highest block header this node has received from peers // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled -func (e *EthAPI) Syncing() (interface{}, error) { +func (e *EthAPI) Syncing() (any, error) { e.logger.Debug("eth_syncing") return e.backend.Syncing() } diff --git a/eth/rpc/rpcapi/eth_filters_api.go b/eth/rpc/rpcapi/eth_filters_api.go index 782014bb5..eca8dd27c 100644 --- a/eth/rpc/rpcapi/eth_filters_api.go +++ b/eth/rpc/rpcapi/eth_filters_api.go @@ -621,7 +621,7 @@ func (api *FiltersAPI) GetFilterLogs(ctx context.Context, id gethrpc.ID) ([]*get // // This function implements the "eth_getFilterChanges" JSON-RPC service method. // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges -func (api *FiltersAPI) GetFilterChanges(id gethrpc.ID) (interface{}, error) { +func (api *FiltersAPI) GetFilterChanges(id gethrpc.ID) (any, error) { api.logger.Debug("eth_getFilterChanges") api.filtersMu.Lock() defer api.filtersMu.Unlock() diff --git a/eth/rpc/rpcapi/websockets.go b/eth/rpc/rpcapi/websockets.go index 68fb7eb9e..530dd39d7 100644 --- a/eth/rpc/rpcapi/websockets.go +++ b/eth/rpc/rpcapi/websockets.go @@ -41,9 +41,9 @@ type WebsocketsServer interface { } type SubscriptionResponseJSON struct { - Jsonrpc string `json:"jsonrpc"` - Result interface{} `json:"result"` - ID float64 `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result any `json:"result"` + ID float64 `json:"id"` } type SubscriptionNotification struct { @@ -53,8 +53,8 @@ type SubscriptionNotification struct { } type SubscriptionResult struct { - Subscription gethrpc.ID `json:"subscription"` - Result interface{} `json:"result"` + Subscription gethrpc.ID `json:"subscription"` + Result any `json:"result"` } type ErrorResponseJSON struct { @@ -157,7 +157,7 @@ type wsConn struct { mux *sync.Mutex } -func (w *wsConn) WriteJSON(v interface{}) error { +func (w *wsConn) WriteJSON(v any) error { w.mux.Lock() defer w.mux.Unlock() @@ -203,7 +203,7 @@ func (s *websocketsServer) readLoop(wsConn *wsConn) { continue } - var msg map[string]interface{} + var msg map[string]any if err = json.Unmarshal(mb, &msg); err != nil { s.sendErrResponse(wsConn, err.Error()) continue @@ -299,8 +299,8 @@ func (s *websocketsServer) readLoop(wsConn *wsConn) { } // tcpGetAndSendResponse sends error response to client if params is invalid -func (s *websocketsServer) getParamsAndCheckValid(msg map[string]interface{}, wsConn *wsConn) ([]interface{}, bool) { - params, ok := msg["params"].([]interface{}) +func (s *websocketsServer) getParamsAndCheckValid(msg map[string]any, wsConn *wsConn) ([]any, bool) { + params, ok := msg["params"].([]any) if !ok { s.sendErrResponse(wsConn, "invalid parameters") return nil, false @@ -336,7 +336,7 @@ func (s *websocketsServer) tcpGetAndSendResponse(wsConn *wsConn, mb []byte) erro return errors.Wrap(err, "could not read body from response") } - var wsSend interface{} + var wsSend any err = json.Unmarshal(body, &wsSend) if err != nil { return errors.Wrap(err, "failed to unmarshal rest-server response") @@ -362,7 +362,7 @@ func newPubSubAPI(clientCtx client.Context, logger log.Logger, tmWSClient *rpccl } } -func (api *pubSubAPI) subscribe(wsConn *wsConn, subID gethrpc.ID, params []interface{}) (pubsub.UnsubscribeFunc, error) { +func (api *pubSubAPI) subscribe(wsConn *wsConn, subID gethrpc.ID, params []any) (pubsub.UnsubscribeFunc, error) { method, ok := params[0].(string) if !ok { return nil, errors.New("invalid parameters") @@ -462,11 +462,11 @@ func try(fn func(), l log.Logger, desc string) { fn() } -func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra interface{}) (pubsub.UnsubscribeFunc, error) { +func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra any) (pubsub.UnsubscribeFunc, error) { crit := filters.FilterCriteria{} if extra != nil { - params, ok := extra.(map[string]interface{}) + params, ok := extra.(map[string]any) if !ok { err := errors.New("invalid criteria") api.logger.Debug("invalid criteria", "type", fmt.Sprintf("%T", extra)) @@ -475,7 +475,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte if params["address"] != nil { address, isString := params["address"].(string) - addresses, isSlice := params["address"].([]interface{}) + addresses, isSlice := params["address"].([]any) if !isString && !isSlice { err := errors.New("invalid addresses; must be address or array of addresses") api.logger.Debug("invalid addresses", "type", fmt.Sprintf("%T", params["address"])) @@ -502,7 +502,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte } if params["topics"] != nil { - topics, ok := params["topics"].([]interface{}) + topics, ok := params["topics"].([]any) if !ok { err := errors.Errorf("invalid topics: %s", topics) api.logger.Error("invalid topics", "type", fmt.Sprintf("%T", topics)) @@ -511,7 +511,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte crit.Topics = make([][]common.Hash, len(topics)) - addCritTopic := func(topicIdx int, topic interface{}) error { + addCritTopic := func(topicIdx int, topic any) error { tstr, ok := topic.(string) if !ok { err := errors.Errorf("invalid topic: %s", topic) @@ -538,7 +538,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte } // in case we actually have a list of subtopics - subtopicsList, ok := subtopics.([]interface{}) + subtopicsList, ok := subtopics.([]any) if !ok { err := errors.New("invalid subtopics") api.logger.Error("invalid subtopic", "type", fmt.Sprintf("%T", subtopics)) diff --git a/x/common/testutil/nullify.go b/x/common/testutil/nullify.go index 202b59e6f..96fc340f6 100644 --- a/x/common/testutil/nullify.go +++ b/x/common/testutil/nullify.go @@ -16,7 +16,7 @@ var ( // Fill analyze all struct fields and slices with // reflection and initialize the nil and empty slices, // structs, and pointers. -func Fill(x interface{}) interface{} { +func Fill(x any) any { v := reflect.Indirect(reflect.ValueOf(x)) switch v.Kind() { case reflect.Slice: diff --git a/x/common/testutil/testnetwork/logger.go b/x/common/testutil/testnetwork/logger.go index dfdf56d97..7b1206a94 100644 --- a/x/common/testutil/testnetwork/logger.go +++ b/x/common/testutil/testnetwork/logger.go @@ -11,8 +11,8 @@ import ( // Typically, a `testing.T` struct is used as the logger for both the "Network" // and corresponding "Validators". type Logger interface { - Log(args ...interface{}) - Logf(format string, args ...interface{}) + Log(args ...any) + Logf(format string, args ...any) } var _ Logger = (*testing.T)(nil) diff --git a/x/devgas/v1/types/params.go b/x/devgas/v1/types/params.go index 433aa4d43..532436c73 100644 --- a/x/devgas/v1/types/params.go +++ b/x/devgas/v1/types/params.go @@ -28,7 +28,7 @@ func DefaultParams() ModuleParams { } } -func validateBool(i interface{}) error { +func validateBool(i any) error { _, ok := i.(bool) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -37,7 +37,7 @@ func validateBool(i interface{}) error { return nil } -func validateShares(i interface{}) error { +func validateShares(i any) error { v, ok := i.(sdk.Dec) if !ok { @@ -59,7 +59,7 @@ func validateShares(i interface{}) error { return nil } -func validateArray(i interface{}) error { +func validateArray(i any) error { _, ok := i.([]string) if !ok { return fmt.Errorf("invalid parameter type: %T", i) diff --git a/x/epochs/types/identifier.go b/x/epochs/types/identifier.go index 3dd3012cb..714b9dd66 100644 --- a/x/epochs/types/identifier.go +++ b/x/epochs/types/identifier.go @@ -20,7 +20,7 @@ const ( // ValidateEpochIdentifierInterface performs a stateless // validation of the epoch ID interface. -func ValidateEpochIdentifierInterface(i interface{}) error { +func ValidateEpochIdentifierInterface(i any) error { v, ok := i.(string) if !ok { return fmt.Errorf("invalid parameter type: %T", i) diff --git a/x/evm/errors.go b/x/evm/errors.go index 9fc6722ac..87d5c747b 100644 --- a/x/evm/errors.go +++ b/x/evm/errors.go @@ -106,6 +106,6 @@ func (e *RevertError) ErrorCode() int { } // ErrorData returns the hex encoded revert reason. -func (e *RevertError) ErrorData() interface{} { +func (e *RevertError) ErrorData() any { return e.reason } diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 9cc9290e9..4e13254a9 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -736,7 +736,7 @@ func (k *Keeper) TraceEthTxMsg( traceConfig *evm.TraceConfig, commitMessage bool, tracerJSONConfig json.RawMessage, -) (*interface{}, uint, error) { +) (*any, uint, error) { // Assemble the structured logger or the JavaScript tracer var ( tracer tracers.Tracer @@ -805,7 +805,7 @@ func (k *Keeper) TraceEthTxMsg( return nil, 0, grpcstatus.Error(grpccodes.Internal, err.Error()) } - var result interface{} + var result any result, err = tracer.GetResult() if err != nil { return nil, 0, grpcstatus.Error(grpccodes.Internal, err.Error()) diff --git a/x/evm/params.go b/x/evm/params.go index 66d31e035..e0211d0bb 100644 --- a/x/evm/params.go +++ b/x/evm/params.go @@ -35,7 +35,7 @@ func DefaultParams() Params { } // validateChannels checks if channels ids are valid -func validateChannels(i interface{}) error { +func validateChannels(i any) error { channels, ok := i.([]string) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -76,7 +76,7 @@ func (p Params) IsEVMChannel(channel string) bool { return slices.Contains(p.EVMChannels, channel) } -func validateEIPs(i interface{}) error { +func validateEIPs(i any) error { eips, ok := i.([]int64) if !ok { return fmt.Errorf("invalid EIP slice type: %T", i) diff --git a/x/evm/precompile/.gitignore b/x/evm/precompile/.gitignore deleted file mode 100644 index e8c12ff4f..000000000 --- a/x/evm/precompile/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -node_modules -.env - -# Hardhat files -/cache -/artifacts - -# TypeChain files -/typechain -/typechain-types - -# solidity-coverage files -/coverage -/coverage.json - -# Hardhat Ignition default folder for deployments against a local node -ignition/deployments/chain-31337 diff --git a/x/evm/precompile/errors.go b/x/evm/precompile/errors.go index a95989b71..438ffa750 100644 --- a/x/evm/precompile/errors.go +++ b/x/evm/precompile/errors.go @@ -1,7 +1,6 @@ package precompile import ( - "errors" "fmt" "reflect" @@ -9,6 +8,13 @@ import ( "github.com/ethereum/go-ethereum/core/vm" ) +func assertNotReadonlyTx(readOnly bool, method *gethabi.Method) error { + if readOnly { + return fmt.Errorf("method %s cannot be called in a read-only context (e.g. staticcall)", method.Name) + } + return nil +} + // ErrPrecompileRun is error function intended for use in a `defer` pattern, // which modifies the input error in the event that its value becomes non-nil. // This creates a concise way to prepend extra information to the original error. @@ -34,14 +40,6 @@ func ErrMethodCalled(method *gethabi.Method, wrapped error) error { return fmt.Errorf("%s method called: %w", method.Name, wrapped) } -// Check required for transactions but not needed for queries -func assertNotReadonlyTx(readOnly bool, isTx bool) error { - if readOnly && isTx { - return errors.New("cannot write state from staticcall (a read-only call)") - } - return nil -} - // assertContractQuery checks if a contract call is a valid query operation. This // function verifies that no funds (wei) are being sent with the query, as query // operations should be read-only and not involve any value transfer. diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index e9ccaee82..1d50d99ab 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -3,7 +3,6 @@ package precompile import ( "fmt" "math/big" - "sync" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -32,21 +31,19 @@ func (p precompileFunToken) Address() gethcommon.Address { return PrecompileAddr_FunToken } -func (p precompileFunToken) ABI() *gethabi.ABI { - return embeds.SmartContract_FunToken.ABI -} - // RequiredGas calculates the cost of calling the precompile in gas units. func (p precompileFunToken) RequiredGas(input []byte) (gasCost uint64) { - return RequiredGas(input, p.ABI()) + return requiredGas(input, p.ABI()) +} + +func (p precompileFunToken) ABI() *gethabi.ABI { + return embeds.SmartContract_FunToken.ABI } const ( FunTokenMethod_BankSend PrecompileMethod = "bankSend" ) -type PrecompileMethod string - // Run runs the precompiled contract func (p precompileFunToken) Run( evm *vm.EVM, contract *vm.Contract, readonly bool, @@ -54,7 +51,7 @@ func (p precompileFunToken) Run( defer func() { err = ErrPrecompileRun(err, p) }() - start, err := OnRunStart(evm, contract, p.ABI()) + start, err := OnRunStart(evm, contract.Input, p.ABI()) if err != nil { return nil, err } @@ -87,8 +84,6 @@ type precompileFunToken struct { evmKeeper evmkeeper.Keeper } -var executionGuard sync.Mutex - // bankSend: Implements "IFunToken.bankSend" // // The "args" populate the following function signature in Solidity: @@ -105,15 +100,10 @@ func (p precompileFunToken) bankSend( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - ctx, method, args := start.Ctx, start.Method, start.Args - if e := assertNotReadonlyTx(readOnly, true); e != nil { - err = e - return - } - if !executionGuard.TryLock() { - return nil, fmt.Errorf("bankSend is already in progress") + ctx, method, args := start.CacheCtx, start.Method, start.Args + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } - defer executionGuard.Unlock() erc20, amount, to, err := p.decomposeBankSendArgs(args) if err != nil { diff --git a/x/evm/precompile/oracle.go b/x/evm/precompile/oracle.go index fb0b2981b..f59b93822 100644 --- a/x/evm/precompile/oracle.go +++ b/x/evm/precompile/oracle.go @@ -24,7 +24,11 @@ func (p precompileOracle) Address() gethcommon.Address { } func (p precompileOracle) RequiredGas(input []byte) (gasPrice uint64) { - return RequiredGas(input, embeds.SmartContract_Oracle.ABI) + return requiredGas(input, p.ABI()) +} + +func (p precompileOracle) ABI() *gethabi.ABI { + return embeds.SmartContract_Oracle.ABI } const ( @@ -38,21 +42,19 @@ func (p precompileOracle) Run( defer func() { err = ErrPrecompileRun(err, p) }() - res, err := OnRunStart(evm, contract, embeds.SmartContract_Oracle.ABI) + startResult, err := OnRunStart(evm, contract.Input, p.ABI()) if err != nil { return nil, err } - method, args, ctx := res.Method, res.Args, res.Ctx + method, args, ctx := startResult.Method, startResult.Args, startResult.CacheCtx switch PrecompileMethod(method.Name) { case OracleMethod_queryExchangeRate: - bz, err = p.queryExchangeRate(ctx, method, args, readonly) + return p.queryExchangeRate(ctx, method, args) default: err = fmt.Errorf("invalid method called with name \"%s\"", method.Name) return } - - return } func PrecompileOracle(keepers keepers.PublicKeepers) vm.PrecompiledContract { @@ -68,10 +70,9 @@ type precompileOracle struct { func (p precompileOracle) queryExchangeRate( ctx sdk.Context, method *gethabi.Method, - args []interface{}, - readOnly bool, + args []any, ) (bz []byte, err error) { - pair, err := p.decomposeQueryExchangeRateArgs(args) + pair, err := p.parseQueryExchangeRateArgs(args) if err != nil { return nil, err } @@ -88,7 +89,7 @@ func (p precompileOracle) queryExchangeRate( return method.Outputs.Pack(price.String()) } -func (p precompileOracle) decomposeQueryExchangeRateArgs(args []any) ( +func (p precompileOracle) parseQueryExchangeRateArgs(args []any) ( pair string, err error, ) { diff --git a/x/evm/precompile/precompile.go b/x/evm/precompile/precompile.go index 40d0c74b4..234a27f4b 100644 --- a/x/evm/precompile/precompile.go +++ b/x/evm/precompile/precompile.go @@ -85,15 +85,15 @@ func methodById(abi *gethabi.ABI, sigdata []byte) (*gethabi.Method, error) { return nil, fmt.Errorf("no method with id: %#x", sigdata[:4]) } -func DecomposeInput( +func decomposeInput( abi *gethabi.ABI, input []byte, -) (method *gethabi.Method, args []interface{}, err error) { +) (method *gethabi.Method, args []any, err error) { // ABI method IDs are exactly 4 bytes according to "gethabi.ABI.MethodByID". if len(input) < 4 { - readableBz := collections.HumanizeBytes(input) - err = fmt.Errorf("input \"%s\" too short to extract method ID (less than 4 bytes)", readableBz) + err = fmt.Errorf("input \"%s\" too short to extract method ID (less than 4 bytes)", collections.HumanizeBytes(input)) return } + method, err = methodById(abi, input[:4]) if err != nil { err = fmt.Errorf("unable to parse ABI method by its 4-byte ID: %w", err) @@ -109,8 +109,8 @@ func DecomposeInput( return method, args, nil } -func RequiredGas(input []byte, abi *gethabi.ABI) uint64 { - method, _, err := DecomposeInput(abi, input) +func requiredGas(input []byte, abi *gethabi.ABI) uint64 { + method, err := methodById(abi, input[:4]) if err != nil { // It's appropriate to return a reasonable default here // because the error from DecomposeInput will be handled automatically by @@ -122,26 +122,27 @@ func RequiredGas(input []byte, abi *gethabi.ABI) uint64 { // Map access could panic. We know that it won't panic because all methods // are in the map, which is verified by unit tests. - methodIsTx := precompileMethodIsTxMap[PrecompileMethod(method.Name)] var costPerByte, costFlat uint64 - if methodIsTx { + if isMutation[PrecompileMethod(method.Name)] { costPerByte, costFlat = gasCfg.WriteCostPerByte, gasCfg.WriteCostFlat } else { costPerByte, costFlat = gasCfg.ReadCostPerByte, gasCfg.ReadCostFlat } - argsBzLen := uint64(len(input[4:])) - return (costPerByte * argsBzLen) + costFlat + // Calculate the total gas required based on the input size and flat cost + return (costPerByte * uint64(len(input[4:]))) + costFlat } +type PrecompileMethod string + type OnRunStartResult struct { // Args contains the decoded (ABI unpacked) arguments passed to the contract // as input. Args []any - // Ctx is a cached SDK context that allows isolated state + // CacheCtx is a cached SDK context that allows isolated state // operations to occur that can be reverted by the EVM's [statedb.StateDB]. - Ctx sdk.Context + CacheCtx sdk.Context // Method is the ABI method for the precompiled contract call. Method *gethabi.Method @@ -178,9 +179,9 @@ type OnRunStartResult struct { // } // ``` func OnRunStart( - evm *vm.EVM, contract *vm.Contract, abi *gethabi.ABI, + evm *vm.EVM, contractInput []byte, abi *gethabi.ABI, ) (res OnRunStartResult, err error) { - method, args, err := DecomposeInput(abi, contract.Input) + method, args, err := decomposeInput(abi, contractInput) if err != nil { return res, err } @@ -194,8 +195,8 @@ func OnRunStart( // journalEntry captures the state before precompile execution to enable // proper state reversal if the call fails or if [statedb.JournalChange] // is reverted in general. - cacheCtx, journalEntry := stateDB.CacheCtxForPrecompile(contract.Address()) - if err = stateDB.SavePrecompileCalledJournalChange(contract.Address(), journalEntry); err != nil { + cacheCtx, journalEntry := stateDB.CacheCtxForPrecompile() + if err = stateDB.SavePrecompileCalledJournalChange(journalEntry); err != nil { return res, err } if err = stateDB.CommitCacheCtx(); err != nil { @@ -203,14 +204,14 @@ func OnRunStart( } return OnRunStartResult{ - Args: args, - Ctx: cacheCtx, - Method: method, - StateDB: stateDB, + Args: args, + CacheCtx: cacheCtx, + Method: method, + StateDB: stateDB, }, nil } -var precompileMethodIsTxMap map[PrecompileMethod]bool = map[PrecompileMethod]bool{ +var isMutation map[PrecompileMethod]bool = map[PrecompileMethod]bool{ WasmMethod_execute: true, WasmMethod_instantiate: true, WasmMethod_executeMulti: true, diff --git a/x/evm/precompile/test/export.go b/x/evm/precompile/test/export.go index 28670e3e0..24700ce85 100644 --- a/x/evm/precompile/test/export.go +++ b/x/evm/precompile/test/export.go @@ -8,20 +8,17 @@ import ( "path" "strings" - serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasm "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/ethereum/go-ethereum/core/vm" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/suite" "github.com/NibiruChain/nibiru/v2/app" + serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" "github.com/NibiruChain/nibiru/v2/x/evm/evmtest" "github.com/NibiruChain/nibiru/v2/x/evm/precompile" - "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) // SetupWasmContracts stores all Wasm bytecode and has the "deps.Sender" @@ -31,68 +28,52 @@ func SetupWasmContracts(deps *evmtest.TestDeps, s *suite.Suite) ( ) { wasmCodes := DeployWasmBytecode(s, deps.Ctx, deps.Sender.NibiruAddr, deps.App) - otherArgs := []struct { - InstMsg []byte - Label string + instantiateArgs := []struct { + InstantiateMsg []byte + Label string }{ { - InstMsg: []byte("{}"), - Label: "https://github.com/NibiruChain/nibiru-wasm/blob/main/contracts/nibi-stargate/src/contract.rs", + InstantiateMsg: []byte("{}"), + Label: "https://github.com/NibiruChain/nibiru-wasm/blob/main/contracts/nibi-stargate/src/contract.rs", }, { - InstMsg: []byte(`{"count": 0}`), - Label: "https://github.com/NibiruChain/nibiru-wasm/tree/ec3ab9f09587a11fbdfbd4021c7617eca3912044/contracts/00-hello-world-counter", + InstantiateMsg: []byte(`{"count": 0}`), + Label: "https://github.com/NibiruChain/nibiru-wasm/tree/ec3ab9f09587a11fbdfbd4021c7617eca3912044/contracts/00-hello-world-counter", }, } - for wasmCodeIdx, wasmCode := range wasmCodes { + for i, wasmCode := range wasmCodes { s.T().Logf("Instantiate using Wasm precompile: %s", wasmCode.binPath) codeId := wasmCode.codeId m := wasm.MsgInstantiateContract{ Admin: "", CodeID: codeId, - Label: otherArgs[wasmCodeIdx].Label, - Msg: otherArgs[wasmCodeIdx].InstMsg, - Funds: []sdk.Coin{}, + Label: instantiateArgs[i].Label, + Msg: instantiateArgs[i].InstantiateMsg, } msgArgsBz, err := json.Marshal(m.Msg) s.NoError(err) - var funds []precompile.WasmBankCoin - fundsJson, err := m.Funds.MarshalJSON() - s.NoErrorf(err, "fundsJson: %s", fundsJson) - err = json.Unmarshal(fundsJson, &funds) - s.Require().NoError(err) - - callArgs := []any{m.Admin, m.CodeID, msgArgsBz, m.Label, funds} + callArgs := []any{m.Admin, m.CodeID, msgArgsBz, m.Label, []precompile.WasmBankCoin{}} input, err := embeds.SmartContract_Wasm.ABI.Pack( string(precompile.WasmMethod_instantiate), callArgs..., ) s.Require().NoError(err) - ethTxResp, evmObj, err := deps.EvmKeeper.CallContractWithInput( + ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) - // Finalize transaction - err = evmObj.StateDB.(*statedb.StateDB).Commit() - s.Require().NoError(err) - s.T().Log("Parse the response contract addr and response bytes") - var contractAddrStr string - var data []byte - err = embeds.SmartContract_Wasm.ABI.UnpackIntoInterface( - &[]any{&contractAddrStr, &data}, - string(precompile.WasmMethod_instantiate), - ethTxResp.Ret, - ) + vals, err := embeds.SmartContract_Wasm.ABI.Unpack(string(precompile.WasmMethod_instantiate), ethTxResp.Ret) s.Require().NoError(err) - contractAddr, err := sdk.AccAddressFromBech32(contractAddrStr) + + contractAddr, err := sdk.AccAddressFromBech32(vals[0].(string)) s.NoError(err) contracts = append(contracts, contractAddr) } @@ -118,7 +99,7 @@ func DeployWasmBytecode( rootPathBz, err := exec.Command("go", "list", "-m", "-f", "{{.Dir}}").Output() s.Require().NoError(err) rootPath := strings.Trim(string(rootPathBz), "\n") - for _, pathToWasmBin := range []string{ + for _, wasmFile := range []string{ // nibi_stargate.wasm is a compiled version of: // https://github.com/NibiruChain/nibiru-wasm/blob/main/contracts/nibi-stargate/src/contract.rs "x/tokenfactory/fixture/nibi_stargate.wasm", @@ -129,11 +110,11 @@ func DeployWasmBytecode( // Add other wasm bytecode here if needed... } { - pathToWasmBin = path.Join(string(rootPath), pathToWasmBin) - wasmBytecode, err := os.ReadFile(pathToWasmBin) + binPath := path.Join(rootPath, wasmFile) + wasmBytecode, err := os.ReadFile(binPath) s.Require().NoErrorf( err, - "rootPath %s, pathToWasmBin %s", rootPath, pathToWasmBin, + "path %s, pathToWasmBin %s", binPath, ) // The "Create" fn is private on the nibiru.WasmKeeper. By placing it as the @@ -150,7 +131,7 @@ func DeployWasmBytecode( codeIds = append(codeIds, struct { codeId uint64 binPath string - }{codeId, pathToWasmBin}) + }{codeId, binPath}) } return codeIds diff --git a/x/evm/precompile/wasm.go b/x/evm/precompile/wasm.go index f19511cb9..cddfc488e 100644 --- a/x/evm/precompile/wasm.go +++ b/x/evm/precompile/wasm.go @@ -37,27 +37,26 @@ func (p precompileWasm) Run( defer func() { err = ErrPrecompileRun(err, p) }() - start, err := OnRunStart(evm, contract, p.ABI()) + startResult, err := OnRunStart(evm, contract.Input, p.ABI()) if err != nil { return nil, err } - method := start.Method - switch PrecompileMethod(method.Name) { + switch PrecompileMethod(startResult.Method.Name) { case WasmMethod_execute: - bz, err = p.execute(start, contract.CallerAddress, readonly) + bz, err = p.execute(startResult, contract.CallerAddress, readonly) case WasmMethod_query: - bz, err = p.query(start, contract) + bz, err = p.query(startResult, contract) case WasmMethod_instantiate: - bz, err = p.instantiate(start, contract.CallerAddress, readonly) + bz, err = p.instantiate(startResult, contract.CallerAddress, readonly) case WasmMethod_executeMulti: - bz, err = p.executeMulti(start, contract.CallerAddress, readonly) + bz, err = p.executeMulti(startResult, contract.CallerAddress, readonly) case WasmMethod_queryRaw: - bz, err = p.queryRaw(start, contract) + bz, err = p.queryRaw(startResult, contract) default: // Note that this code path should be impossible to reach since // "DecomposeInput" parses methods directly from the ABI. - err = fmt.Errorf("invalid method called with name \"%s\"", method.Name) + err = fmt.Errorf("invalid method called with name \"%s\"", startResult.Method.Name) return } if err != nil { @@ -74,13 +73,13 @@ func (p precompileWasm) Address() gethcommon.Address { return PrecompileAddr_Wasm } -func (p precompileWasm) ABI() *gethabi.ABI { - return embeds.SmartContract_Wasm.ABI -} - // RequiredGas calculates the cost of calling the precompile in gas units. func (p precompileWasm) RequiredGas(input []byte) (gasCost uint64) { - return RequiredGas(input, p.ABI()) + return requiredGas(input, p.ABI()) +} + +func (p precompileWasm) ABI() *gethabi.ABI { + return embeds.SmartContract_Wasm.ABI } // Wasm: A struct embedding keepers for read and write operations in Wasm, such @@ -123,23 +122,22 @@ func (p precompileWasm) execute( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) } }() - - if err := assertNotReadonlyTx(readOnly, true); err != nil { - return bz, err + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } - wasmContract, msgArgs, funds, err := p.parseExecuteArgs(args) + + wasmContract, msgArgsBz, funds, err := p.parseExecuteArgs(args) if err != nil { err = ErrInvalidArgs(err) return } - callerBech32 := eth.EthAddrToNibiruAddr(caller) - data, err := p.Wasm.Execute(ctx, wasmContract, callerBech32, msgArgs, funds) + data, err := p.Wasm.Execute(ctx, wasmContract, eth.EthAddrToNibiruAddr(caller), msgArgsBz, funds) if err != nil { return } @@ -162,7 +160,7 @@ func (p precompileWasm) query( start OnRunStartResult, contract *vm.Contract, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) @@ -171,6 +169,7 @@ func (p precompileWasm) query( if err := assertContractQuery(contract); err != nil { return bz, err } + wasmContract, req, err := p.parseQueryArgs(args) if err != nil { err = ErrInvalidArgs(err) @@ -207,14 +206,14 @@ func (p precompileWasm) instantiate( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) } }() - if err := assertNotReadonlyTx(readOnly, true); err != nil { - return bz, err + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } callerBech32 := eth.EthAddrToNibiruAddr(caller) @@ -258,14 +257,14 @@ func (p precompileWasm) executeMulti( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) } }() - if err := assertNotReadonlyTx(readOnly, true); err != nil { - return bz, err + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } wasmExecMsgs, err := p.parseExecuteMultiArgs(args) @@ -327,7 +326,7 @@ func (p precompileWasm) queryRaw( start OnRunStartResult, contract *vm.Contract, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) diff --git a/x/evm/precompile/wasm_parse.go b/x/evm/precompile/wasm_parse.go index 80d950622..97a532753 100644 --- a/x/evm/precompile/wasm_parse.go +++ b/x/evm/precompile/wasm_parse.go @@ -16,51 +16,38 @@ type WasmBankCoin struct { Amount *big.Int `json:"amount"` } -func parseSdkCoins(unparsed []struct { - Denom string `json:"denom"` - Amount *big.Int `json:"amount"` -}, -) sdk.Coins { - parsed := sdk.Coins{} - for _, coin := range unparsed { - parsed = append( - parsed, - // Favor the sdk.Coin constructor over sdk.NewCoin because sdk.NewCoin - // is not panic-safe. Validation will be handled when the coin is used - // as an argument during the execution of a transaction. - sdk.Coin{ - Denom: coin.Denom, - Amount: sdk.NewIntFromBigInt(coin.Amount), - }, - ) - } - return parsed -} - // Parses [sdk.Coins] from a "BankCoin[]" solidity argument: // // ```solidity // BankCoin[] memory funds // ``` func parseFundsArg(arg any) (funds sdk.Coins, err error) { - bankCoinsUnparsed, ok := arg.([]struct { + if arg == nil { + return funds, nil + } + + raw, ok := arg.([]struct { Denom string `json:"denom"` Amount *big.Int `json:"amount"` }) - switch { - case arg == nil: - bankCoinsUnparsed = []struct { - Denom string `json:"denom"` - Amount *big.Int `json:"amount"` - }{} - case !ok: - err = ErrArgTypeValidation("BankCoin[] funds", arg) - return - case ok: - // Type assertion succeeded + + if !ok { + return funds, ErrArgTypeValidation("BankCoin[] funds", arg) } - funds = parseSdkCoins(bankCoinsUnparsed) - return + + for _, coin := range raw { + funds = append( + funds, + // Favor the sdk.Coin constructor over sdk.NewCoin because sdk.NewCoin + // is not panic-safe. Validation will be handled when the coin is used + // as an argument during the execution of a transaction. + sdk.Coin{ + Denom: coin.Denom, + Amount: sdk.NewIntFromBigInt(coin.Amount), + }, + ) + } + return funds, nil } // Parses [sdk.AccAddress] from a "string" solidity argument: @@ -148,6 +135,7 @@ func (p precompileWasm) parseExecuteArgs(args []any) ( return } + // contract address argIdx := 0 contractAddrStr, ok := args[argIdx].(string) if !ok { @@ -162,6 +150,7 @@ func (p precompileWasm) parseExecuteArgs(args []any) ( return } + // msg args argIdx++ msgArgs, ok = args[argIdx].([]byte) if !ok { @@ -174,6 +163,7 @@ func (p precompileWasm) parseExecuteArgs(args []any) ( return } + // funds argIdx++ funds, e := parseFundsArg(args[argIdx]) if e != nil { @@ -202,7 +192,11 @@ func (p precompileWasm) parseQueryArgs(args []any) ( } argsIdx++ - reqBz := args[argsIdx].([]byte) + reqBz, ok := args[argsIdx].([]byte) + if !ok { + err = ErrArgTypeValidation("bytes req", args[argsIdx]) + return + } req = wasm.RawContractMessage(reqBz) if e := req.ValidateBasic(); e != nil { err = e diff --git a/x/evm/statedb/journal_test.go b/x/evm/statedb/journal_test.go index 6390b640f..c1c74110c 100644 --- a/x/evm/statedb/journal_test.go +++ b/x/evm/statedb/journal_test.go @@ -31,13 +31,12 @@ func (s *Suite) TestComplexJournalChanges() { )) s.T().Log("Set up helloworldcounter.wasm") - - wasmContract := test.SetupWasmContracts(&deps, &s.Suite)[1] - fmt.Printf("wasmContract: %s\n", wasmContract) + helloWorldCounterWasm := test.SetupWasmContracts(&deps, &s.Suite)[1] + fmt.Printf("wasmContract: %s\n", helloWorldCounterWasm) s.T().Log("Assert before transition") test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 0, + &s.Suite, deps, helloWorldCounterWasm, 0, ) deployArgs := []any{"name", "SYMBOL", uint8(18)} @@ -129,11 +128,11 @@ func (s *Suite) TestComplexJournalChanges() { s.T().Log("commitEvmTx=true, expect 0 dirty journal entries") commitEvmTx := true evmObj = test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, &deps, wasmContract, 7, commitEvmTx, + &s.Suite, &deps, helloWorldCounterWasm, 7, commitEvmTx, ) // assertions after run test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, + &s.Suite, deps, helloWorldCounterWasm, 7, ) stateDB, ok := evmObj.StateDB.(*statedb.StateDB) s.Require().True(ok, "error retrieving StateDB from the EVM") @@ -145,7 +144,7 @@ func (s *Suite) TestComplexJournalChanges() { s.T().Log("commitEvmTx=false, expect dirty journal entries") commitEvmTx = false evmObj = test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, &deps, wasmContract, 5, commitEvmTx, + &s.Suite, &deps, helloWorldCounterWasm, 5, commitEvmTx, ) stateDB, ok = evmObj.StateDB.(*statedb.StateDB) s.Require().True(ok, "error retrieving StateDB from the EVM") @@ -158,7 +157,7 @@ func (s *Suite) TestComplexJournalChanges() { s.T().Log("Expect no change since the StateDB has not been committed") test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, // 7 = 7 + 0 + &s.Suite, deps, helloWorldCounterWasm, 7, // 7 = 7 + 0 ) s.T().Log("Expect change to persist on the StateDB cacheCtx") @@ -166,14 +165,14 @@ func (s *Suite) TestComplexJournalChanges() { s.NotNil(cacheCtx) deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 12, // 12 = 7 + 5 + &s.Suite, deps, helloWorldCounterWasm, 12, // 12 = 7 + 5 ) // NOTE: that the [StateDB.Commit] fn has not been called yet. We're still // mid-transaction. s.T().Log("EVM revert operation should bring about the old state") err = test.IncrementWasmCounterWithExecuteMultiViaVMCall( - &s.Suite, &deps, wasmContract, 50, commitEvmTx, evmObj, + &s.Suite, &deps, helloWorldCounterWasm, 50, commitEvmTx, evmObj, ) stateDBPtr := evmObj.StateDB.(*statedb.StateDB) s.Require().Equal(stateDB, stateDBPtr) @@ -185,7 +184,7 @@ snapshots and see the prior states.`)) cacheCtx = stateDB.GetCacheContext() deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7+5+50, + &s.Suite, deps, helloWorldCounterWasm, 7+5+50, ) errFn := common.TryCatch(func() { @@ -201,7 +200,7 @@ snapshots and see the prior states.`)) s.NotNil(cacheCtx) deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7+5, + &s.Suite, deps, helloWorldCounterWasm, 7+5, ) stateDB.RevertToSnapshot(0) @@ -209,13 +208,13 @@ snapshots and see the prior states.`)) s.NotNil(cacheCtx) deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, // state before precompile called + &s.Suite, deps, helloWorldCounterWasm, 7, // state before precompile called ) err = stateDB.Commit() deps.Ctx = stateDB.GetEvmTxContext() test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, // state before precompile called + &s.Suite, deps, helloWorldCounterWasm, 7, // state before precompile called ) }) } diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index a411660f9..4e93b127a 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -569,7 +569,7 @@ func (s *StateDB) commitCtx(ctx sdk.Context) error { return nil } -func (s *StateDB) CacheCtxForPrecompile(precompileAddr common.Address) ( +func (s *StateDB) CacheCtxForPrecompile() ( sdk.Context, PrecompileCalled, ) { if s.writeToCommitCtxFromCacheCtx == nil { @@ -590,15 +590,14 @@ func (s *StateDB) CacheCtxForPrecompile(precompileAddr common.Address) ( // // See [PrecompileCalled] for more info. func (s *StateDB) SavePrecompileCalledJournalChange( - precompileAddr common.Address, journalChange PrecompileCalled, ) error { s.Journal.append(journalChange) s.multistoreCacheCount++ if s.multistoreCacheCount > maxMultistoreCacheCount { return fmt.Errorf( - "exceeded maximum number Nibiru-specific precompiled contract calls in one transaction (%d). Called address %s", - maxMultistoreCacheCount, precompileAddr.Hex(), + "exceeded maximum number Nibiru-specific precompiled contract calls in one transaction (%d).", + maxMultistoreCacheCount, ) } return nil diff --git a/x/evm/vmtracer.go b/x/evm/vmtracer.go index 2a20f2b01..2078bdfe7 100644 --- a/x/evm/vmtracer.go +++ b/x/evm/vmtracer.go @@ -51,8 +51,8 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height // TxTraceResult is the result of a single transaction trace during a block trace. type TxTraceResult struct { - Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer - Error string `json:"error,omitempty"` // Trace failure produced by the tracer + Result any `json:"result,omitempty"` // Trace results produced by the tracer + Error string `json:"error,omitempty"` // Trace failure produced by the tracer } var _ vm.EVMLogger = &NoOpTracer{} diff --git a/x/inflation/types/params.go b/x/inflation/types/params.go index 1ca46623b..6b95bbb7c 100644 --- a/x/inflation/types/params.go +++ b/x/inflation/types/params.go @@ -71,7 +71,7 @@ func DefaultParams() Params { } } -func validatePolynomialFactors(i interface{}) error { +func validatePolynomialFactors(i any) error { v, ok := i.([]sdk.Dec) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -83,7 +83,7 @@ func validatePolynomialFactors(i interface{}) error { return nil } -func validateInflationDistribution(i interface{}) error { +func validateInflationDistribution(i any) error { v, ok := i.(InflationDistribution) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -109,7 +109,7 @@ func validateInflationDistribution(i interface{}) error { return nil } -func validateBool(i interface{}) error { +func validateBool(i any) error { _, ok := i.(bool) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -118,7 +118,7 @@ func validateBool(i interface{}) error { return nil } -func validateUint64(i interface{}) error { +func validateUint64(i any) error { _, ok := i.(uint64) if !ok { return fmt.Errorf("invalid genesis state type: %T", i) @@ -126,7 +126,7 @@ func validateUint64(i interface{}) error { return nil } -func validateEpochsPerPeriod(i interface{}) error { +func validateEpochsPerPeriod(i any) error { val, ok := i.(uint64) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -139,7 +139,7 @@ func validateEpochsPerPeriod(i interface{}) error { return nil } -func validatePeriodsPerYear(i interface{}) error { +func validatePeriodsPerYear(i any) error { val, ok := i.(uint64) if !ok { return fmt.Errorf("invalid parameter type: %T", i) diff --git a/x/oracle/types/hash.go b/x/oracle/types/hash.go index b9d816ecc..a828a6414 100644 --- a/x/oracle/types/hash.go +++ b/x/oracle/types/hash.go @@ -99,7 +99,7 @@ func (h AggregateVoteHash) MarshalJSON() ([]byte, error) { } // MarshalYAML marshals to YAML using Bech32. -func (h AggregateVoteHash) MarshalYAML() (interface{}, error) { +func (h AggregateVoteHash) MarshalYAML() (any, error) { return h.String(), nil } diff --git a/x/tokenfactory/types/codec.go b/x/tokenfactory/types/codec.go index e0e639c0d..c20e55ad4 100644 --- a/x/tokenfactory/types/codec.go +++ b/x/tokenfactory/types/codec.go @@ -58,7 +58,7 @@ func TX_MSG_TYPE_URLS() []string { // Amino JSON serialization and EIP-712 compatibility. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { for _, ele := range []struct { - MsgType interface{} + MsgType any Name string }{ {&MsgCreateDenom{}, "nibiru/tokenfactory/create-denom"}, From bf708393a17a135ebb0fd46605dd37cdbc1d7990 Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Thu, 31 Oct 2024 22:34:00 +0400 Subject: [PATCH 06/12] fix(evm): tx receipt proper marshalling (#2101) * fix(evm): tx receipt proper marshalling * test(evm): e2e for tx receipt * chore: justfile cleanup * fix: justfile * fix: minor timeout fix --- CHANGELOG.md | 1 + eth/rpc/backend/tx_info.go | 36 +- eth/rpc/backend/tx_info_test.go | 4 +- evm-e2e/.prettierrc | 10 + evm-e2e/contracts/EventsEmitter.sol | 10 + .../contracts/InfiniteLoopGasCompiled.json | 31 - evm-e2e/contracts/ReceiveNibiCompiled.json | 32 - evm-e2e/contracts/SendNibiCompiled.json | 50 - evm-e2e/contracts/TestERC20Compiled.json | 324 - evm-e2e/contracts/TransactionReverter.sol | 28 + evm-e2e/hardhat.config.js | 13 + evm-e2e/justfile | 23 +- evm-e2e/package-lock.json | 10518 ++++++++++++---- evm-e2e/package.json | 13 +- .../test/contract_infinite_loop_gas.test.ts | 28 +- evm-e2e/test/contract_send_nibi.test.ts | 79 +- evm-e2e/test/debug_queries.test.ts | 160 +- evm-e2e/test/erc20.test.ts | 40 +- evm-e2e/test/eth_queries.test.ts | 473 +- evm-e2e/test/native_transfer.test.ts | 60 +- evm-e2e/test/setup.ts | 12 +- evm-e2e/test/tx_receipt.test.ts | 123 + evm-e2e/test/utils.ts | 82 +- .../InfiniteLoopGasCompiled.ts | 91 - .../ethers-contracts/ReceiveNibiCompiled.ts | 87 - .../ethers-contracts/SendNibiCompiled.ts | 119 - .../ethers-contracts/TestERC20Compiled.ts | 286 - evm-e2e/types/ethers-contracts/common.ts | 131 - .../InfiniteLoopGasCompiled__factory.ts | 93 - .../factories/ReceiveNibiCompiled__factory.ts | 94 - .../factories/SendNibiCompiled__factory.ts | 106 - .../factories/TestERC20Compiled__factory.ts | 380 - .../types/ethers-contracts/factories/index.ts | 7 - evm-e2e/types/ethers-contracts/index.ts | 12 - 34 files changed, 8869 insertions(+), 4687 deletions(-) create mode 100644 evm-e2e/.prettierrc create mode 100644 evm-e2e/contracts/EventsEmitter.sol delete mode 100644 evm-e2e/contracts/InfiniteLoopGasCompiled.json delete mode 100644 evm-e2e/contracts/ReceiveNibiCompiled.json delete mode 100644 evm-e2e/contracts/SendNibiCompiled.json delete mode 100644 evm-e2e/contracts/TestERC20Compiled.json create mode 100644 evm-e2e/contracts/TransactionReverter.sol create mode 100644 evm-e2e/hardhat.config.js create mode 100644 evm-e2e/test/tx_receipt.test.ts delete mode 100644 evm-e2e/types/ethers-contracts/InfiniteLoopGasCompiled.ts delete mode 100644 evm-e2e/types/ethers-contracts/ReceiveNibiCompiled.ts delete mode 100644 evm-e2e/types/ethers-contracts/SendNibiCompiled.ts delete mode 100644 evm-e2e/types/ethers-contracts/TestERC20Compiled.ts delete mode 100644 evm-e2e/types/ethers-contracts/common.ts delete mode 100644 evm-e2e/types/ethers-contracts/factories/InfiniteLoopGasCompiled__factory.ts delete mode 100644 evm-e2e/types/ethers-contracts/factories/ReceiveNibiCompiled__factory.ts delete mode 100644 evm-e2e/types/ethers-contracts/factories/SendNibiCompiled__factory.ts delete mode 100644 evm-e2e/types/ethers-contracts/factories/TestERC20Compiled__factory.ts delete mode 100644 evm-e2e/types/ethers-contracts/factories/index.ts delete mode 100644 evm-e2e/types/ethers-contracts/index.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 88fa93ee9..46f412d48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ for (1) ERC20 transfers with tokens that return false success values instead of throwing an error and (2) ERC20 transfers with other operations that don't bring about the expected resulting balance for the transfer recipient. - [#2092](https://github.com/NibiruChain/nibiru/pull/2092) - feat(evm): add validation for wasm multi message execution +- [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/eth/rpc/backend/tx_info.go b/eth/rpc/backend/tx_info.go index 10f6d1bde..f9817448a 100644 --- a/eth/rpc/backend/tx_info.go +++ b/eth/rpc/backend/tx_info.go @@ -2,6 +2,7 @@ package backend import ( + "encoding/json" "fmt" "math" "math/big" @@ -134,10 +135,39 @@ func (b *Backend) getTransactionByHashPending(txHash gethcommon.Hash) (*rpc.EthT type TransactionReceipt struct { gethcore.Receipt - ContractAddress *gethcommon.Address `json:"contractAddress,omitempty"` + ContractAddress *gethcommon.Address From gethcommon.Address To *gethcommon.Address - EffectiveGasPrice *big.Int + EffectiveGasPrice *hexutil.Big +} + +// MarshalJSON is necessary because without it non gethcore.Receipt fields are omitted +func (r *TransactionReceipt) MarshalJSON() ([]byte, error) { + // Marshal / unmarshal gethcore.Receipt to produce map[string]interface{} + receiptJson, err := json.Marshal(r.Receipt) + if err != nil { + return nil, err + } + + var output map[string]interface{} + if err := json.Unmarshal(receiptJson, &output); err != nil { + return nil, err + } + + // Add extra (non gethcore.Receipt) fields: + if r.ContractAddress != nil && *r.ContractAddress != (gethcommon.Address{}) { + output["contractAddress"] = r.ContractAddress + } + if r.From != (gethcommon.Address{}) { + output["from"] = r.From + } + if r.To != nil { + output["to"] = r.To + } + if r.EffectiveGasPrice != nil { + output["effectiveGasPrice"] = r.EffectiveGasPrice + } + return json.Marshal(output) } // GetTransactionReceipt returns the transaction receipt identified by hash. @@ -253,7 +283,7 @@ func (b *Backend) GetTransactionReceipt(hash gethcommon.Hash) (*TransactionRecei // tolerate the error for pruned node. b.logger.Error("fetch basefee failed, node is pruned?", "height", res.Height, "error", err) } else { - receipt.EffectiveGasPrice = dynamicTx.EffectiveGasPriceWeiPerGas(baseFeeWei) + receipt.EffectiveGasPrice = (*hexutil.Big)(dynamicTx.EffectiveGasPriceWeiPerGas(baseFeeWei)) } } return &receipt, nil diff --git a/eth/rpc/backend/tx_info_test.go b/eth/rpc/backend/tx_info_test.go index b9cdda3a6..d0d1eb0e4 100644 --- a/eth/rpc/backend/tx_info_test.go +++ b/eth/rpc/backend/tx_info_test.go @@ -202,10 +202,10 @@ func (s *BackendSuite) TestReceiptMarshalJson() { ContractAddress: nil, From: evmtest.NewEthPrivAcc().EthAddr, To: &toAddr, - EffectiveGasPrice: big.NewInt(1), + EffectiveGasPrice: (*hexutil.Big)(big.NewInt(1)), } - jsonBz, err := json.Marshal(tr) + jsonBz, err := tr.MarshalJSON() s.Require().NoError(err) gethReceipt := new(gethcore.Receipt) diff --git a/evm-e2e/.prettierrc b/evm-e2e/.prettierrc new file mode 100644 index 000000000..0d3fe8121 --- /dev/null +++ b/evm-e2e/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 120, + "tabWidth": 2, + "importOrder": ["^@core/(.*)$", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true +} diff --git a/evm-e2e/contracts/EventsEmitter.sol b/evm-e2e/contracts/EventsEmitter.sol new file mode 100644 index 000000000..e9bd2920b --- /dev/null +++ b/evm-e2e/contracts/EventsEmitter.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract EventsEmitter { + event TestEvent(address indexed sender, uint256 value); + + function emitEvent(uint256 value) public { + emit TestEvent(msg.sender, value); + } +} \ No newline at end of file diff --git a/evm-e2e/contracts/InfiniteLoopGasCompiled.json b/evm-e2e/contracts/InfiniteLoopGasCompiled.json deleted file mode 100644 index 3868bd1d1..000000000 --- a/evm-e2e/contracts/InfiniteLoopGasCompiled.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "InifiniteLoopGas", - "sourceName": "contracts/InfiniteLoopGas.sol", - "abi": [ - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "forever", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x60806040526000805534801561001457600080fd5b5061015e806100246000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806361bc221a1461003b5780639ff9a60314610059575b600080fd5b610043610063565b60405161005091906100aa565b60405180910390f35b610061610069565b005b60005481565b5b60011561008f57600160008082825461008391906100f4565b9250508190555061006a565b565b6000819050919050565b6100a481610091565b82525050565b60006020820190506100bf600083018461009b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100ff82610091565b915061010a83610091565b9250828201905080821115610122576101216100c5565b5b9291505056fea2646970667358221220946d430ff7d8c16c5401d4156ff1b5d75c112460fbba0fb343581bd3c86cfe1c64736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806361bc221a1461003b5780639ff9a60314610059575b600080fd5b610043610063565b60405161005091906100aa565b60405180910390f35b610061610069565b005b60005481565b5b60011561008f57600160008082825461008391906100f4565b9250508190555061006a565b565b6000819050919050565b6100a481610091565b82525050565b60006020820190506100bf600083018461009b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100ff82610091565b915061010a83610091565b9250828201905080821115610122576101216100c5565b5b9291505056fea2646970667358221220946d430ff7d8c16c5401d4156ff1b5d75c112460fbba0fb343581bd3c86cfe1c64736f6c63430008180033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/evm-e2e/contracts/ReceiveNibiCompiled.json b/evm-e2e/contracts/ReceiveNibiCompiled.json deleted file mode 100644 index 979c40c63..000000000 --- a/evm-e2e/contracts/ReceiveNibiCompiled.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ReceiveNibi", - "sourceName": "contracts/SendReceiveNibi.sol", - "abi": [ - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b5060bb8061001f6000396000f3fe608060405260043610601f5760003560e01c806312065fe0146027576025565b36602557005b005b348015603257600080fd5b506039604d565b60405160449190606c565b60405180910390f35b600047905090565b6000819050919050565b6066816055565b82525050565b6000602082019050607f6000830184605f565b9291505056fea2646970667358221220f4ee193ceac7d6ffbf8d62d675a1d21fed9c154b8e9407c7aba0f7301ef0db6b64736f6c63430008180033", - "deployedBytecode": "0x608060405260043610601f5760003560e01c806312065fe0146027576025565b36602557005b005b348015603257600080fd5b506039604d565b60405160449190606c565b60405180910390f35b600047905090565b6000819050919050565b6066816055565b82525050565b6000602082019050607f6000830184605f565b9291505056fea2646970667358221220f4ee193ceac7d6ffbf8d62d675a1d21fed9c154b8e9407c7aba0f7301ef0db6b64736f6c63430008180033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/evm-e2e/contracts/SendNibiCompiled.json b/evm-e2e/contracts/SendNibiCompiled.json deleted file mode 100644 index 621e8db3e..000000000 --- a/evm-e2e/contracts/SendNibiCompiled.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "SendNibi", - "sourceName": "contracts/SendReceiveNibi.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "sendViaCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "sendViaSend", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "sendViaTransfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b50610390806100206000396000f3fe6080604052600436106100345760003560e01c8063636e082b1461003957806374be480614610055578063830c29ae14610071575b600080fd5b610053600480360381019061004e919061026a565b61008d565b005b61006f600480360381019061006a919061026a565b6100d7565b005b61008b6004803603810190610086919061026a565b610154565b005b8073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156100d3573d6000803e3d6000fd5b5050565b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050905080610150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610147906102f4565b60405180910390fd5b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163460405161017b90610345565b60006040518083038185875af1925050503d80600081146101b8576040519150601f19603f3d011682016040523d82523d6000602084013e6101bd565b606091505b509150915081610202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f9906102f4565b60405180910390fd5b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102378261020c565b9050919050565b6102478161022c565b811461025257600080fd5b50565b6000813590506102648161023e565b92915050565b6000602082840312156102805761027f610207565b5b600061028e84828501610255565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204e69626900000000000000000000000000600082015250565b60006102de601383610297565b91506102e9826102a8565b602082019050919050565b6000602082019050818103600083015261030d816102d1565b9050919050565b600081905092915050565b50565b600061032f600083610314565b915061033a8261031f565b600082019050919050565b600061035082610322565b915081905091905056fea26469706673582212201fcd9f47953315963ca2a2687073914cbb3f29161100cec83979926b96714b2b64736f6c63430008180033", - "deployedBytecode": "0x6080604052600436106100345760003560e01c8063636e082b1461003957806374be480614610055578063830c29ae14610071575b600080fd5b610053600480360381019061004e919061026a565b61008d565b005b61006f600480360381019061006a919061026a565b6100d7565b005b61008b6004803603810190610086919061026a565b610154565b005b8073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156100d3573d6000803e3d6000fd5b5050565b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050905080610150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610147906102f4565b60405180910390fd5b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163460405161017b90610345565b60006040518083038185875af1925050503d80600081146101b8576040519150601f19603f3d011682016040523d82523d6000602084013e6101bd565b606091505b509150915081610202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f9906102f4565b60405180910390fd5b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102378261020c565b9050919050565b6102478161022c565b811461025257600080fd5b50565b6000813590506102648161023e565b92915050565b6000602082840312156102805761027f610207565b5b600061028e84828501610255565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204e69626900000000000000000000000000600082015250565b60006102de601383610297565b91506102e9826102a8565b602082019050919050565b6000602082019050818103600083015261030d816102d1565b9050919050565b600081905092915050565b50565b600061032f600083610314565b915061033a8261031f565b600082019050919050565b600061035082610322565b915081905091905056fea26469706673582212201fcd9f47953315963ca2a2687073914cbb3f29161100cec83979926b96714b2b64736f6c63430008180033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/evm-e2e/contracts/TestERC20Compiled.json b/evm-e2e/contracts/TestERC20Compiled.json deleted file mode 100644 index f5ecf6af5..000000000 --- a/evm-e2e/contracts/TestERC20Compiled.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "TestERC20", - "sourceName": "contracts/TestERC20.sol", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "allowance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientAllowance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC20InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC20InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC20InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "ERC20InvalidSpender", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x60806040523480156200001157600080fd5b506040518060400160405280600881526020017f46756e546f6b656e0000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f46554e000000000000000000000000000000000000000000000000000000000081525081600390816200008f9190620005fd565b508060049081620000a19190620005fd565b505050620000c03369d3c21bcecceda1000000620000c660201b60201c565b6200081b565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036200013b5760006040517fec442f0500000000000000000000000000000000000000000000000000000000815260040162000132919062000729565b60405180910390fd5b6200014f600083836200015360201b60201c565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603620001a95780600260008282546200019c919062000775565b925050819055506200027f565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101562000238578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016200022f93929190620007c1565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620002ca578060026000828254039250508190555062000317565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620003769190620007fe565b60405180910390a3505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200040557607f821691505b6020821081036200041b576200041a620003bd565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000446565b62000491868362000446565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620004de620004d8620004d284620004a9565b620004b3565b620004a9565b9050919050565b6000819050919050565b620004fa83620004bd565b620005126200050982620004e5565b84845462000453565b825550505050565b600090565b620005296200051a565b62000536818484620004ef565b505050565b5b818110156200055e57620005526000826200051f565b6001810190506200053c565b5050565b601f821115620005ad57620005778162000421565b620005828462000436565b8101602085101562000592578190505b620005aa620005a18562000436565b8301826200053b565b50505b505050565b600082821c905092915050565b6000620005d260001984600802620005b2565b1980831691505092915050565b6000620005ed8383620005bf565b9150826002028217905092915050565b620006088262000383565b67ffffffffffffffff8111156200062457620006236200038e565b5b620006308254620003ec565b6200063d82828562000562565b600060209050601f83116001811462000675576000841562000660578287015190505b6200066c8582620005df565b865550620006dc565b601f198416620006858662000421565b60005b82811015620006af5784890151825560018201915060208501945060208101905062000688565b86831015620006cf5784890151620006cb601f891682620005bf565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200071182620006e4565b9050919050565b620007238162000704565b82525050565b600060208201905062000740600083018462000718565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200078282620004a9565b91506200078f83620004a9565b9250828201905080821115620007aa57620007a962000746565b5b92915050565b620007bb81620004a9565b82525050565b6000606082019050620007d8600083018662000718565b620007e76020830185620007b0565b620007f66040830184620007b0565b949350505050565b6000602082019050620008156000830184620007b0565b92915050565b610e55806200082b6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063313ce56711610066578063313ce5671461013457806370a082311461015257806395d89b4114610182578063a9059cbb146101a0578063dd62ed3e146101d057610093565b806306fdde0314610098578063095ea7b3146100b657806318160ddd146100e657806323b872dd14610104575b600080fd5b6100a0610200565b6040516100ad9190610aa9565b60405180910390f35b6100d060048036038101906100cb9190610b64565b610292565b6040516100dd9190610bbf565b60405180910390f35b6100ee6102b5565b6040516100fb9190610be9565b60405180910390f35b61011e60048036038101906101199190610c04565b6102bf565b60405161012b9190610bbf565b60405180910390f35b61013c6102ee565b6040516101499190610c73565b60405180910390f35b61016c60048036038101906101679190610c8e565b6102f7565b6040516101799190610be9565b60405180910390f35b61018a61033f565b6040516101979190610aa9565b60405180910390f35b6101ba60048036038101906101b59190610b64565b6103d1565b6040516101c79190610bbf565b60405180910390f35b6101ea60048036038101906101e59190610cbb565b6103f4565b6040516101f79190610be9565b60405180910390f35b60606003805461020f90610d2a565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610d2a565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b60008061029d61047b565b90506102aa818585610483565b600191505092915050565b6000600254905090565b6000806102ca61047b565b90506102d7858285610495565b6102e2858585610529565b60019150509392505050565b60006012905090565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60606004805461034e90610d2a565b80601f016020809104026020016040519081016040528092919081815260200182805461037a90610d2a565b80156103c75780601f1061039c576101008083540402835291602001916103c7565b820191906000526020600020905b8154815290600101906020018083116103aa57829003601f168201915b5050505050905090565b6000806103dc61047b565b90506103e9818585610529565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b610490838383600161061d565b505050565b60006104a184846103f4565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105235781811015610513578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161050a93929190610d6a565b60405180910390fd5b6105228484848403600061061d565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361059b5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105929190610da1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361060d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106049190610da1565b60405180910390fd5b6106188383836107f4565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361068f5760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016106869190610da1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107015760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016106f89190610da1565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156107ee578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516107e59190610be9565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361084657806002600082825461083a9190610deb565b92505081905550610919565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156108d2578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016108c993929190610d6a565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361096257806002600082825403925050819055506109af565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610a0c9190610be9565b60405180910390a3505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610a53578082015181840152602081019050610a38565b60008484015250505050565b6000601f19601f8301169050919050565b6000610a7b82610a19565b610a858185610a24565b9350610a95818560208601610a35565b610a9e81610a5f565b840191505092915050565b60006020820190508181036000830152610ac38184610a70565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610afb82610ad0565b9050919050565b610b0b81610af0565b8114610b1657600080fd5b50565b600081359050610b2881610b02565b92915050565b6000819050919050565b610b4181610b2e565b8114610b4c57600080fd5b50565b600081359050610b5e81610b38565b92915050565b60008060408385031215610b7b57610b7a610acb565b5b6000610b8985828601610b19565b9250506020610b9a85828601610b4f565b9150509250929050565b60008115159050919050565b610bb981610ba4565b82525050565b6000602082019050610bd46000830184610bb0565b92915050565b610be381610b2e565b82525050565b6000602082019050610bfe6000830184610bda565b92915050565b600080600060608486031215610c1d57610c1c610acb565b5b6000610c2b86828701610b19565b9350506020610c3c86828701610b19565b9250506040610c4d86828701610b4f565b9150509250925092565b600060ff82169050919050565b610c6d81610c57565b82525050565b6000602082019050610c886000830184610c64565b92915050565b600060208284031215610ca457610ca3610acb565b5b6000610cb284828501610b19565b91505092915050565b60008060408385031215610cd257610cd1610acb565b5b6000610ce085828601610b19565b9250506020610cf185828601610b19565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610d4257607f821691505b602082108103610d5557610d54610cfb565b5b50919050565b610d6481610af0565b82525050565b6000606082019050610d7f6000830186610d5b565b610d8c6020830185610bda565b610d996040830184610bda565b949350505050565b6000602082019050610db66000830184610d5b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610df682610b2e565b9150610e0183610b2e565b9250828201905080821115610e1957610e18610dbc565b5b9291505056fea26469706673582212200260074039b179ca88933aa33752c910c15aa2062c21e8c76d09940bd406048b64736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063313ce56711610066578063313ce5671461013457806370a082311461015257806395d89b4114610182578063a9059cbb146101a0578063dd62ed3e146101d057610093565b806306fdde0314610098578063095ea7b3146100b657806318160ddd146100e657806323b872dd14610104575b600080fd5b6100a0610200565b6040516100ad9190610aa9565b60405180910390f35b6100d060048036038101906100cb9190610b64565b610292565b6040516100dd9190610bbf565b60405180910390f35b6100ee6102b5565b6040516100fb9190610be9565b60405180910390f35b61011e60048036038101906101199190610c04565b6102bf565b60405161012b9190610bbf565b60405180910390f35b61013c6102ee565b6040516101499190610c73565b60405180910390f35b61016c60048036038101906101679190610c8e565b6102f7565b6040516101799190610be9565b60405180910390f35b61018a61033f565b6040516101979190610aa9565b60405180910390f35b6101ba60048036038101906101b59190610b64565b6103d1565b6040516101c79190610bbf565b60405180910390f35b6101ea60048036038101906101e59190610cbb565b6103f4565b6040516101f79190610be9565b60405180910390f35b60606003805461020f90610d2a565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610d2a565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b60008061029d61047b565b90506102aa818585610483565b600191505092915050565b6000600254905090565b6000806102ca61047b565b90506102d7858285610495565b6102e2858585610529565b60019150509392505050565b60006012905090565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60606004805461034e90610d2a565b80601f016020809104026020016040519081016040528092919081815260200182805461037a90610d2a565b80156103c75780601f1061039c576101008083540402835291602001916103c7565b820191906000526020600020905b8154815290600101906020018083116103aa57829003601f168201915b5050505050905090565b6000806103dc61047b565b90506103e9818585610529565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b610490838383600161061d565b505050565b60006104a184846103f4565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105235781811015610513578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161050a93929190610d6a565b60405180910390fd5b6105228484848403600061061d565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361059b5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105929190610da1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361060d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106049190610da1565b60405180910390fd5b6106188383836107f4565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361068f5760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016106869190610da1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107015760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016106f89190610da1565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156107ee578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516107e59190610be9565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361084657806002600082825461083a9190610deb565b92505081905550610919565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156108d2578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016108c993929190610d6a565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361096257806002600082825403925050819055506109af565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610a0c9190610be9565b60405180910390a3505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610a53578082015181840152602081019050610a38565b60008484015250505050565b6000601f19601f8301169050919050565b6000610a7b82610a19565b610a858185610a24565b9350610a95818560208601610a35565b610a9e81610a5f565b840191505092915050565b60006020820190508181036000830152610ac38184610a70565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610afb82610ad0565b9050919050565b610b0b81610af0565b8114610b1657600080fd5b50565b600081359050610b2881610b02565b92915050565b6000819050919050565b610b4181610b2e565b8114610b4c57600080fd5b50565b600081359050610b5e81610b38565b92915050565b60008060408385031215610b7b57610b7a610acb565b5b6000610b8985828601610b19565b9250506020610b9a85828601610b4f565b9150509250929050565b60008115159050919050565b610bb981610ba4565b82525050565b6000602082019050610bd46000830184610bb0565b92915050565b610be381610b2e565b82525050565b6000602082019050610bfe6000830184610bda565b92915050565b600080600060608486031215610c1d57610c1c610acb565b5b6000610c2b86828701610b19565b9350506020610c3c86828701610b19565b9250506040610c4d86828701610b4f565b9150509250925092565b600060ff82169050919050565b610c6d81610c57565b82525050565b6000602082019050610c886000830184610c64565b92915050565b600060208284031215610ca457610ca3610acb565b5b6000610cb284828501610b19565b91505092915050565b60008060408385031215610cd257610cd1610acb565b5b6000610ce085828601610b19565b9250506020610cf185828601610b19565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610d4257607f821691505b602082108103610d5557610d54610cfb565b5b50919050565b610d6481610af0565b82525050565b6000606082019050610d7f6000830186610d5b565b610d8c6020830185610bda565b610d996040830184610bda565b949350505050565b6000602082019050610db66000830184610d5b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610df682610b2e565b9150610e0183610b2e565b9250828201905080821115610e1957610e18610dbc565b5b9291505056fea26469706673582212200260074039b179ca88933aa33752c910c15aa2062c21e8c76d09940bd406048b64736f6c63430008180033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/evm-e2e/contracts/TransactionReverter.sol b/evm-e2e/contracts/TransactionReverter.sol new file mode 100644 index 000000000..81d7c0949 --- /dev/null +++ b/evm-e2e/contracts/TransactionReverter.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +contract TransactionReverter { + uint256 public value; + + error CustomRevertReason(uint256 providedValue); + + // Will try to set state and revert unconditionally + function setAndRevert(uint256 newValue) public { + value = newValue; + revert("Transaction reverted after state change"); + } + + // Will revert with custom error + function revertWithCustomError(uint256 newValue) public { + value = newValue; + revert CustomRevertReason(newValue); + } + + // Will emit event and then revert + event ValueUpdateAttempted(address sender, uint256 value); + function emitAndRevert(uint256 newValue) public { + emit ValueUpdateAttempted(msg.sender, newValue); + value = newValue; + revert("Reverted after event emission"); + } +} \ No newline at end of file diff --git a/evm-e2e/hardhat.config.js b/evm-e2e/hardhat.config.js new file mode 100644 index 000000000..898700747 --- /dev/null +++ b/evm-e2e/hardhat.config.js @@ -0,0 +1,13 @@ +require("@nomicfoundation/hardhat-toolbox"); +require('@typechain/hardhat'); + +/** @type import('hardhat/config').HardhatUserConfig */ +module.exports = { + solidity: "0.8.24", + typechain: { + outDir: "types", + target: "ethers-v6", + alwaysGenerateOverloads: false, + dontOverrideCompile: false, + }, +}; diff --git a/evm-e2e/justfile b/evm-e2e/justfile index 8ab9fb7d1..d8153d37e 100644 --- a/evm-e2e/justfile +++ b/evm-e2e/justfile @@ -7,25 +7,10 @@ setup: #!/usr/bin/env bash just -l - # Install all dependencies -install: - #!/usr/bin/env bash - - # Check if the given binary is in the $PATH. - the_cmd="bun" - if which "$the_cmd" >/dev/null 2>&1; then - echo "✅ bun is installed." - else - log_error "$the_cmd is not present in \$PATH" - npm install -g bun@1.1.12 - fi - - bun install - -# Generate types from compiled contracts -gen-types: - bun run typechain --target=ethers-v6 contracts/*Compiled.json +install: + npm install + npx hardhat typechain # Runs the E2E tests test: @@ -33,4 +18,4 @@ test: # Format fmt: - bun run prettier --write "test/**/*.ts" + npm run format diff --git a/evm-e2e/package-lock.json b/evm-e2e/package-lock.json index 155bc648a..77f7df55d 100644 --- a/evm-e2e/package-lock.json +++ b/evm-e2e/package-lock.json @@ -10,10 +10,11 @@ "license": "ISC", "devDependencies": { "@jest/globals": "^29.7.0", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@openzeppelin/contracts": "^5.1.0", "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", "@types/jest": "^29.5.12", - "bun": "^1.1.30", - "bun-types": "^1.0.3", "dotenv": "^16.4.5", "eslint": "^8.0.0", "eslint-config-airbnb": "^19.0.4", @@ -22,8 +23,11 @@ "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-prettier": "^5.1.3", "ethers": "^6.12.1", + "hardhat": "^2.22.15", "jest": "^29.7.0", - "ts-jest": "^29.2.4" + "prettier": "^3.3.3", + "ts-jest": "^29.2.4", + "typechain": "^8.3.2" }, "engines": { "node": ">=0.18.0" @@ -620,6 +624,32 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -676,1013 +706,4423 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "license": "MPL-2.0", + "peer": true, + "bin": { + "rlp": "bin/rlp" }, "engines": { - "node": ">=10.10.0" + "node": ">=14" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", "dev": true, + "license": "MPL-2.0", + "peer": true, + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, "engines": { - "node": ">=12.22" + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.4.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@ethereumjs/util/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@ethereumjs/util/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "sprintf-js": "~1.0.2" + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", "dev": true, - "engines": { - "node": ">=8" + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@ethersproject/basex": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", + "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", "dev": true, - "engines": { - "node": ">=8" + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", + "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", + "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", + "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", + "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", + "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@ethersproject/random": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", + "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", + "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", + "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", + "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", + "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", + "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "ansi-escapes": "^4.2.1", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@metamask/eth-sig-util": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", + "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "ethereumjs-abi": "^0.6.8", + "ethereumjs-util": "^6.2.1", + "ethjs-util": "^0.1.6", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nomicfoundation/edr": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.4.tgz", + "integrity": "sha512-YgrSuT3yo5ZQkbvBGqQ7hG+RDvz3YygSkddg4tb1Z0Y6pLXFzwrcEwWaJCFAVeeZxdxGfCgGMUYgRVneK+WXkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/edr-darwin-arm64": "0.6.4", + "@nomicfoundation/edr-darwin-x64": "0.6.4", + "@nomicfoundation/edr-linux-arm64-gnu": "0.6.4", + "@nomicfoundation/edr-linux-arm64-musl": "0.6.4", + "@nomicfoundation/edr-linux-x64-gnu": "0.6.4", + "@nomicfoundation/edr-linux-x64-musl": "0.6.4", + "@nomicfoundation/edr-win32-x64-msvc": "0.6.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.4.tgz", + "integrity": "sha512-QNQErISLgssV9+qia8sIjRANqtbW8snSDvjspixT/kSQ5ZSGxxctTg7x72wPSrcu8+EBEveIe5uqENIp5GH8HQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.4.tgz", + "integrity": "sha512-cjVmREiwByyc9+oGfvAh49IAw+oVJHF9WWYRD+Tm/ZlSpnEVWxrGNBak2bd/JSYjn+mZE7gmWS4SMRi4nKaLUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.4.tgz", + "integrity": "sha512-96o9kRIVD6W5VkgKvUOGpWyUGInVQ5BRlME2Fa36YoNsRQMaKtmYJEU0ACosYES6ZTpYC8U5sjMulvPtVoEfOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.4.tgz", + "integrity": "sha512-+JVEW9e5plHrUfQlSgkEj/UONrIU6rADTEk+Yp9pbe+mzNkJdfJYhs5JYiLQRP4OjxH4QOrXI97bKU6FcEbt5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.4.tgz", + "integrity": "sha512-nzYWW+fO3EZItOeP4CrdMgDXfaGBIBkKg0Y/7ySpUxLqzut40O4Mb0/+quqLAFkacUSWMlFp8nsmypJfOH5zoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.4.tgz", + "integrity": "sha512-QFRoE9qSQ2boRrVeQ1HdzU+XN7NUgwZ1SIy5DQt4d7jCP+5qTNsq8LBNcqhRBOATgO63nsweNUhxX/Suj5r1Sw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.4.tgz", + "integrity": "sha512-2yopjelNkkCvIjUgBGhrn153IBPLwnsDeNiq6oA0WkeM8tGmQi4td+PGi9jAriUDAkc59Yoi2q9hYA6efiY7Zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/ethereumjs-common": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", + "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/ethereumjs-util": "9.0.4" + } + }, + "node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", + "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", + "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", + "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + } + }, + "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz", + "integrity": "sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "chai": "^4.2.0", + "ethers": "^6.1.0", + "hardhat": "^2.9.4" + } + }, + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz", + "integrity": "sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.7.tgz", + "integrity": "sha512-RFhGazR0/JqHxuuIxjjMmM+nWFqEvA7wcVqcX7vUqqmAIGuok4HhnWQH8aOvBaVguiXvvlFDJL0PIlxmkFgIUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nomicfoundation/ignition-core": "^0.15.7", + "@nomicfoundation/ignition-ui": "^0.15.7", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "json5": "^2.2.3", + "prompts": "^2.4.2" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-verify": "^2.0.1", + "hardhat": "^2.18.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition-ethers": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.7.tgz", + "integrity": "sha512-pUZWQeFNMwDe6F/yKIJsCo+87elk/M/Edjp6AnWWIBplRyPa13Nh63+yOqMSSd9Mx9lLuBaEGnYXoI2Uz2wYZA==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-ignition": "^0.15.7", + "@nomicfoundation/ignition-core": "^0.15.7", + "ethers": "^6.7.0", + "hardhat": "^2.18.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@nomicfoundation/hardhat-network-helpers": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.12.tgz", + "integrity": "sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ethereumjs-util": "^7.1.4" + }, + "peerDependencies": { + "hardhat": "^2.9.5" + } + }, + "node_modules/@nomicfoundation/hardhat-network-helpers/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@nomicfoundation/hardhat-network-helpers/node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@nomicfoundation/hardhat-toolbox": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", + "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=18.0.0", + "chai": "^4.2.0", + "ethers": "^6.4.0", + "hardhat": "^2.11.0", + "hardhat-gas-reporter": "^1.0.8", + "solidity-coverage": "^0.8.1", + "ts-node": ">=8.0.0", + "typechain": "^8.3.0", + "typescript": ">=4.5.0" + } + }, + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.11.tgz", + "integrity": "sha512-lGIo4dNjVQFdsiEgZp3KP6ntLiF7xJEJsbNHfSyIiFCyI0Yv0518ElsFtMC5uCuHEChiBBMrib9jWQvHHT+X3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "lodash.clonedeep": "^4.5.0", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.0.4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/ignition-core": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.7.tgz", + "integrity": "sha512-C4/0V/q2gNxKDt88cMr+Oxlf4NINQ7QgmJyciQ1/6UdCRUg+/Pgdgpd3vgGXQVTotq50Q/BU4ofNUAD/8HRqtg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/address": "5.6.1", + "@nomicfoundation/solidity-analyzer": "^0.1.1", + "cbor": "^9.0.0", + "debug": "^4.3.2", + "ethers": "^6.7.0", + "fs-extra": "^10.0.0", + "immer": "10.0.2", + "lodash": "4.17.21", + "ndjson": "2.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-ui": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.7.tgz", + "integrity": "sha512-pj2LmXylgbHOTNrkFqFrre/FAOjcwYl4VKIKVH/QMMBH/DatbiT8aC5n9o2fbLD8uwlPEesD+uXZuKCE71KFBg==", + "dev": true, + "peer": true + }, + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", + "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + }, + "optionalDependencies": { + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", + "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", + "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", + "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", + "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", + "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", + "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", + "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@openzeppelin/contracts": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.1.0.tgz", + "integrity": "sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@sentry/core": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", + "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/hub": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", + "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/minimal": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/node": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", + "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/core": "5.30.0", + "@sentry/hub": "5.30.0", + "@sentry/tracing": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/tracing": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", + "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/tracing/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", + "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@typechain/ethers-v6": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", + "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" + } + }, + "node_modules/@typechain/hardhat": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", + "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^9.1.0" + }, + "peerDependencies": { + "@typechain/ethers-v6": "^0.5.1", + "ethers": "^6.1.0", + "hardhat": "^2.9.9", + "typechain": "^8.3.2" + } + }, + "node_modules/@typechain/hardhat/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typechain/hardhat/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@typechain/hardhat/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bn.js": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/concat-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", + "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/form-data": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", + "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/mocha": { + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/node": { + "version": "20.12.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/secp256k1": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", + "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "dev": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "dev": true, + "license": "BSD-3-Clause OR MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "peer": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "peer": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "peer": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "peer": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "peer": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base-x": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", + "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, + "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "nofilter": "^3.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.19" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/chai-as-promised": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", "dev": true, + "license": "WTFPL", + "peer": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "check-error": "^1.0.2" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "chai": ">= 2.1.2 < 6" } }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/chai/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, "engines": { "node": ">=10" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "license": "BSD-3-Clause", + "peer": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "get-func-name": "^2.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "readdirp": "^4.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6" + }, + "optionalDependencies": { + "colors": "^1.1.2" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/cli-table3/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" } }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "node_modules/cli-table3/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@noble/hashes": "1.3.2" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=4" } }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "node_modules/cli-table3/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, - "engines": { - "node": ">= 16" + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^3.0.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=4" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "engines": { - "node": ">= 8" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 8" + "node": ">=7.0.0" } }, - "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.30.tgz", - "integrity": "sha512-D07QioP+QXlouvIqQIS+7r2zq4lTNd6he79rhKsRQRZGFf9i3NPu87zspUpCaFEu//DZ35DYTt+5anQpAzpoxA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.30.tgz", - "integrity": "sha512-xZ4gTehS6QwN6bsJfDycCNneKoUMaFUQhQg24bJzXS4JPDxeKg1W7PS5AE+U9apz5Dx6//+D4RwVpAPG2LXt0w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.30.tgz", - "integrity": "sha512-1kFUCxHx7WuEbLDmqm0m2UKBd3S4Ln6qKQ4gxU4umMLFkmvDJn6PszDruFInxGKFLoTAmbXNYNVWkkG/ekt/Lg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.30.tgz", - "integrity": "sha512-SfHHLlph6fptDXyyChcUkeDbEZr2ww1p2BucV6OrvzwTOPi8pVmXA4360YT8ggR/3AHPp4GO36VaD+FU2Ocbxw==", - "cpu": [ - "arm64" - ], + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "engines": { + "node": ">=0.1.90" + } }, - "node_modules/@oven/bun-linux-x64": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.30.tgz", - "integrity": "sha512-1mC39jQSaECytEKAZdCZmv3ZreMsp7aoxnBwmJtVd2Z7urnw17PKi4dKkZd/R+AubsNYtXtW4jeM8SEa5sUJRw==", - "cpu": [ - "x64" - ], + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, - "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.30.tgz", - "integrity": "sha512-/b/VuNOaAYmsVk9MvfwKcCYARJPUg78hebxNyD5DSajAf3dqtUSnf7QYcq/3mxWH++N+gM7uRTrGksGS63+ZUw==", - "cpu": [ - "x64" - ], + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "license": "MIT" }, - "node_modules/@oven/bun-windows-x64": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.30.tgz", - "integrity": "sha512-mdRjNtD9NIA8CiH6N1zrIVE6oAtDko/c29H1s00UA+5O/WhXhg95G8IyInD8hN3vAEz8H2lGBgLG2EGfSFxnGg==", - "cpu": [ - "x64" - ], + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } }, - "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.30.tgz", - "integrity": "sha512-ERQ4/ogzbFvHjpyHcnruc8bnryvDvUoiWi6vczfQ4M/idJc+Kg5VSEJiF5k7946rIZGamG6QWgRxtpIglD4/Zw==", - "cpu": [ - "x64" - ], + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" }, - "funding": { - "url": "https://opencollective.com/unts" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/command-line-usage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { - "type-detect": "4.0.8" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/@typechain/ethers-v6": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", - "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", + "node_modules/command-line-usage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "peerDependencies": { - "ethers": "6.x", - "typechain": "^8.3.2", - "typescript": ">=4.7.0" + "engines": { + "node": ">=4" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/command-line-usage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "color-name": "1.1.3" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "node_modules/command-line-usage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/command-line-usage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "license": "MIT", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "node_modules/command-line-usage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" + "license": "MIT", + "engines": { + "node": ">=4" } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/command-line-usage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" + "license": "MIT", + "engines": { + "node": ">= 12" } }, - "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "peer": true, "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, + "license": "MIT", "peer": true }, - "node_modules/@types/node": { - "version": "20.12.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", - "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "undici-types": "~5.26.4" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT", "peer": true }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@types/yargs-parser": "*" + "safe-buffer": "~5.1.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">= 0.6" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "dev": true + "license": "MIT", + "peer": true }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "bin": { + "create-jest": "bin/create-jest.js" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT", + "peer": true }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, - "peer": true, "dependencies": { - "deep-equal": "^2.0.5" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "peer": true, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/array-buffer-byte-length": { + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "peer": true + }, + "node_modules/data-view-buffer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1691,19 +5131,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, "peer": true, "dependencies": { "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1712,19 +5149,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "is-data-view": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1733,57 +5167,96 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "node_modules/death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", + "dev": true, + "peer": true + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, - "peer": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "ms": "2.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "type-detect": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -1792,38 +5265,57 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.tosorted": { + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, - "peer": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "peer": true, "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -1832,2092 +5324,2352 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, - "peer": true + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", "dev": true, "peer": true, "dependencies": { - "possible-typed-array-names": "^1.0.0" + "heap": ">= 0.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "peer": true, + "dependencies": { + "path-type": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "peer": true, "dependencies": { - "deep-equal": "^2.0.5" + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "node_modules/electron-to-chromium": { + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.11.tgz", + "integrity": "sha512-R1CccCDYqndR25CaXFd6hp/u9RaaMcftMkphmvuepXr5b1vfLkRml6aWVeBhXJ7rbevHkKEMJtz8XqPf7ffmew==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "peer": true + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, + "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=8.6" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" + "is-arrayish": "^0.2.1" } }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "peer": true, "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "dependencies": { - "fast-json-stable-stringify": "2.x" + "get-intrinsic": "^1.2.4" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" + "node": ">= 0.4" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bun": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.30.tgz", - "integrity": "sha512-ysRL1pq10Xba0jqVLPrKU3YIv0ohfp3cTajCPtpjCyppbn3lfiAVNpGoHfyaxS17OlPmWmR67UZRPw/EueQuug==", - "cpu": [ - "arm64", - "x64" - ], + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "os": [ - "darwin", - "linux", - "win32" - ], - "bin": { - "bun": "bin/bun.exe", - "bunx": "bin/bun.exe" - }, - "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.30", - "@oven/bun-darwin-x64": "1.1.30", - "@oven/bun-darwin-x64-baseline": "1.1.30", - "@oven/bun-linux-aarch64": "1.1.30", - "@oven/bun-linux-x64": "1.1.30", - "@oven/bun-linux-x64-baseline": "1.1.30", - "@oven/bun-windows-x64": "1.1.30", - "@oven/bun-windows-x64-baseline": "1.1.30" + "engines": { + "node": ">= 0.4" } }, - "node_modules/bun-types": { - "version": "1.1.24", - "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.1.24.tgz", - "integrity": "sha512-UNEcYawHWOVw9GYQdOgjJvTQduYlPckmRMqpBqfkWpUzeK2CZfEP/JOYBH6SMypyfkNg/Zsqf0olN6vMrSPg3w==", + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", "dev": true, + "peer": true, "dependencies": { - "@types/node": "~20.12.8", - "@types/ws": "~8.5.10" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "dev": true, + "peer": true, "dependencies": { - "es-define-property": "^1.0.0", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "peer": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001651", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", - "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "peer": true, + "dependencies": { + "hasown": "^2.0.0" + } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "peer": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", "dev": true, + "license": "BSD-2-Clause", + "peer": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/escodegen/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", "dev": true, - "license": "MIT", "peer": true, - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, "engines": { - "node": ">=4.0.0" + "node": ">=0.10.0" } }, - "node_modules/command-line-usage": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", - "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "array-back": "^4.0.2", - "chalk": "^2.4.2", - "table-layout": "^1.0.2", - "typical": "^5.2.0" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.8.0" } }, - "node_modules/command-line-usage/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "color-convert": "^1.9.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true, - "license": "MIT", "peer": true, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/command-line-usage/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/escodegen/node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", "dev": true, - "license": "MIT", + "optional": true, "peer": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "amdefine": ">=0.0.4" }, "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/command-line-usage/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "color-name": "1.1.3" + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/command-line-usage/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/command-line-usage/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, - "license": "MIT", - "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, "engines": { - "node": ">=0.8.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/command-line-usage/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", "dev": true, - "license": "MIT", - "peer": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + }, "engines": { - "node": ">=4" + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" } }, - "node_modules/command-line-usage/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, - "license": "MIT", - "peer": true, "dependencies": { - "has-flag": "^3.0.0" + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" }, "engines": { - "node": ">=4" + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" } }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "debug": "^3.2.7" }, "engines": { - "node": ">= 8" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true + "dependencies": { + "ms": "^2.1.1" + } }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "^2.1.1" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" }, "engines": { - "node": ">=6.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { - "babel-plugin-macros": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { "optional": true } } }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "node_modules/eslint-plugin-react": { + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", "dev": true, "peer": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", "dev": true, - "license": "MIT", "peer": true, "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "peer": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/eslint/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6.0.0" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "peer": true, "dependencies": { - "esutils": "^2.0.2" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=4.0" } }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-gas-reporter": { + "version": "0.2.27", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", + "integrity": "sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "jake": "^10.8.5" + "@solidity-parser/parser": "^0.14.0", + "axios": "^1.5.1", + "cli-table3": "^0.5.0", + "colors": "1.4.0", + "ethereum-cryptography": "^1.0.3", + "ethers": "^5.7.2", + "fs-readdir-recursive": "^1.1.0", + "lodash": "^4.17.14", + "markdown-table": "^1.1.3", + "mocha": "^10.2.0", + "req-cwd": "^2.0.0", + "sha1": "^1.1.1", + "sync-request": "^6.0.0" }, - "bin": { - "ejs": "bin/cli.js" + "peerDependencies": { + "@codechecks/client": "^0.1.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependenciesMeta": { + "@codechecks/client": { + "optional": true + } } }, - "node_modules/electron-to-chromium": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.11.tgz", - "integrity": "sha512-R1CccCDYqndR25CaXFd6hp/u9RaaMcftMkphmvuepXr5b1vfLkRml6aWVeBhXJ7rbevHkKEMJtz8XqPf7ffmew==", - "dev": true + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/ethereum-bloom-filters": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", + "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "^1.4.0" + } }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/ethereum-bloom-filters/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=12" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "peer": true - }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "deprecated": "This library has been deprecated and usage is discouraged.", "dev": true, + "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" } }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "node_modules/ethereumjs-abi/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true, - "peer": true, + "license": "MIT" + }, + "node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "license": "MPL-2.0", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + }, + "node_modules/ethereumjs-util/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" + "@types/node": "*" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/ethereumjs-util/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true, - "engines": { - "node": ">= 0.4" - } + "license": "MIT" }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" } }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "node_modules/ethers": { + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", + "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", "dev": true, - "peer": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" }, "engines": { - "node": ">= 0.4" + "node": ">=14.0.0" } }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "dev": true + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "es-errors": "^1.3.0" + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6.5.0", + "npm": ">=3" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", "dev": true, - "peer": true, + "license": "MIT", + "peer": true + }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6.5.0", + "npm": ">=3" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "peer": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-config-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "engines": { - "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" } }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" + "is-glob": "^4.0.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" + "node": ">= 6" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } + "license": "BSD-3-Clause", + "peer": true }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, - "peer": true, "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "reusify": "^1.0.4" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "peer": true, "dependencies": { - "ms": "^2.1.1" + "bser": "2.1.1" } }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" + "flat-cache": "^3.0.4" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "minimatch": "^5.0.1" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "ms": "^2.1.1" + "balanced-match": "^1.0.0" } }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "peer": true, "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "node": ">=10" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "peer": true, "dependencies": { - "ms": "^2.1.1" + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", - "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "aria-query": "~5.1.3", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.9.1", - "axobject-query": "~3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" + "array-back": "^3.0.1" }, "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "node": ">=4.0.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" }, "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { + "debug": { "optional": true } } }, - "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "peer": true, "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + "is-callable": "^1.1.3" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, + "license": "MIT", "peer": true, - "engines": { - "node": ">=10" + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "engines": { + "node": ">= 6" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "node_modules/fp-ts": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", "dev": true, - "peer": true, + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "peer": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, + "peer": true, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "license": "MIT", + "peer": true, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=8.0.0" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/ethers": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", - "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/ethers-io/" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", - "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", - "ws": "8.17.1" - }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { - "node": ">=14.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "peer": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", "dev": true, - "engines": { - "node": ">= 0.8.0" + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/ghost-testrpc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", + "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", "dev": true, + "license": "ISC", + "peer": true, "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "chalk": "^2.4.2", + "node-emoji": "^1.10.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "testrpc-sc": "index.js" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/ghost-testrpc/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=4" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/ghost-testrpc/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "is-glob": "^4.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/ghost-testrpc/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "reusify": "^1.0.4" + "color-name": "1.1.3" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/ghost-testrpc/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, - "dependencies": { - "bser": "2.1.1" + "license": "MIT", + "peer": true + }, + "node_modules/ghost-testrpc/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/ghost-testrpc/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, + "license": "MIT", + "peer": true, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=4" } }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "node_modules/ghost-testrpc/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "minimatch": "^5.0.1" + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=10" + "node": ">=10.13.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "to-regex-range": "^5.0.1" + "global-prefix": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/find-replace": { + "node_modules/global-prefix": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "array-back": "^3.0.1" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "engines": { - "node": ">=4.0.0" + "node": ">=6" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", + "peer": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "peer": true, "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "is-callable": "^1.1.3" + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, - "license": "MIT", - "peer": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">=6 <7 || >=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "node_modules/hardhat": { + "version": "2.22.15", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.15.tgz", + "integrity": "sha512-BpTGa9PE/sKAaHi4s/S1e9WGv63DR1m7Lzfd60C8gSEchDPfAJssVRSq0MZ2v2k76ig9m0kHAwVLf5teYwu/Mw==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "@ethersproject/abi": "^5.1.2", + "@metamask/eth-sig-util": "^4.0.0", + "@nomicfoundation/edr": "^0.6.4", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "@nomicfoundation/solidity-analyzer": "^0.1.0", + "@sentry/node": "^5.18.1", + "@types/bn.js": "^5.1.0", + "@types/lru-cache": "^5.1.0", + "adm-zip": "^0.4.16", + "aggregate-error": "^3.0.0", + "ansi-escapes": "^4.3.0", + "boxen": "^5.1.2", + "chalk": "^2.4.2", + "chokidar": "^4.0.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "ethereum-cryptography": "^1.0.3", + "ethereumjs-abi": "^0.6.8", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "7.2.0", + "immutable": "^4.0.0-rc.12", + "io-ts": "1.10.4", + "json-stream-stringify": "^3.1.4", + "keccak": "^3.0.2", + "lodash": "^4.17.11", + "mnemonist": "^0.38.0", + "mocha": "^10.0.0", + "p-map": "^4.0.0", + "raw-body": "^2.4.1", + "resolve": "1.17.0", + "semver": "^6.3.0", + "solc": "0.8.26", + "source-map-support": "^0.5.13", + "stacktrace-parser": "^0.1.10", + "tsort": "0.0.1", + "undici": "^5.14.0", + "uuid": "^8.3.2", + "ws": "^7.4.6" }, - "engines": { - "node": ">= 0.4" + "bin": { + "hardhat": "internal/cli/bootstrap.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "ts-node": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/hardhat-gas-reporter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", + "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", "dev": true, + "license": "MIT", "peer": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "array-uniq": "1.0.3", + "eth-gas-reporter": "^0.2.25", + "sha1": "^1.1.1" + }, + "peerDependencies": { + "hardhat": "^2.0.2" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/hardhat/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/hardhat/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=4" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/hardhat/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/hardhat/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "color-name": "1.1.3" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/hardhat/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, + "license": "MIT" + }, + "node_modules/hardhat/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=0.8.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/hardhat/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, - "engines": { - "node": ">=10" + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "node_modules/hardhat/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "peer": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/get-tsconfig": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", - "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "node_modules/hardhat/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "license": "MIT", + "engines": { + "node": ">=4" } }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/hardhat/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/hardhat/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "p-try": "^1.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=4" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/hardhat/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "p-limit": "^1.1.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "node_modules/hardhat/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, - "peer": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/hardhat/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3" + "path-parse": "^1.0.6" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "node_modules/hardhat/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "node_modules/hardhat/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/has-bigints": { "version": "1.0.2", @@ -3990,6 +7742,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4002,12 +7780,109 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-basic": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", + "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4017,6 +7892,19 @@ "node": ">=10.17.0" } }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -4026,6 +7914,25 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "dev": true, + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -4070,6 +7977,16 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4087,6 +8004,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -4102,6 +8027,27 @@ "node": ">= 0.4" } }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/io-ts": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", + "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fp-ts": "^1.0.0" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -4171,6 +8117,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -4316,6 +8275,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -4376,6 +8346,16 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4482,6 +8462,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -5217,8 +9210,7 @@ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -5274,6 +9266,24 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stream-stringify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", + "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=7.10.1" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -5293,9 +9303,19 @@ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonschema": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "dev": true, + "license": "MIT", "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": "*" } }, "node_modules/jsx-ast-utils": { @@ -5314,6 +9334,22 @@ "node": ">=4.0" } }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5323,6 +9359,17 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -5407,6 +9454,21 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true, + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true, "license": "MIT", "peer": true }, @@ -5422,6 +9484,31 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -5435,6 +9522,24 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5453,108 +9558,388 @@ "semver": "^7.5.3" }, "engines": { - "node": ">=10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mnemonist": { + "version": "0.38.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", + "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "obliterator": "^2.0.0" + } + }, + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/mocha/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { - "tmpl": "1.0.5" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "engines": { - "node": ">= 8" - } + "license": "MIT" }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "node_modules/mocha/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=8.6" + "node": ">=8.10.0" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "peer": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, + "license": "ISC", "engines": { "node": ">=10" } @@ -5571,6 +9956,65 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "ndjson": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", + "dev": true, + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -5583,6 +10027,31 @@ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5604,6 +10073,30 @@ "node": ">=8" } }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5737,6 +10230,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "dev": true, + "license": "MIT" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5778,6 +10278,24 @@ "node": ">= 0.8.0" } }, + "node_modules/ordinal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", + "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -5808,6 +10326,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -5829,6 +10363,13 @@ "node": ">=6" } }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", + "dev": true, + "peer": true + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -5880,6 +10421,45 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", @@ -5898,6 +10478,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -5995,7 +10586,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, - "peer": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -6050,6 +10641,25 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -6075,6 +10685,14 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -6100,6 +10718,23 @@ } ] }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6120,6 +10755,32 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -6127,13 +10788,68 @@ "dev": true, "peer": true }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "peer": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -6179,6 +10895,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/req-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", + "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "req-from": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", + "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -6188,6 +10943,17 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -6279,6 +11045,30 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rlp": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", + "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6321,6 +11111,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -6339,6 +11150,237 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sc-istanbul": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", + "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/sc-istanbul/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/sc-istanbul/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/sc-istanbul/node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sc-istanbul/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/sc-istanbul/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/sc-istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sc-istanbul/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true, + "license": "MIT" + }, + "node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/secp256k1/node_modules/elliptic": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6348,6 +11390,16 @@ "semver": "bin/semver.js" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6381,6 +11433,49 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6402,6 +11497,25 @@ "node": ">=8" } }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -6442,6 +11556,215 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/solc": { + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solidity-coverage": { + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.13.tgz", + "integrity": "sha512-RiBoI+kF94V3Rv0+iwOj3HQVSqNzA9qm/qDP1ZDXK5IX0Cvho1qiz8hAXTsAo6KOIUeP73jfscq0KlLqVxzGWA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.0.9", + "@solidity-parser/parser": "^0.18.0", + "chalk": "^2.4.2", + "death": "^1.1.0", + "difflib": "^0.2.4", + "fs-extra": "^8.1.0", + "ghost-testrpc": "^0.0.2", + "global-modules": "^2.0.0", + "globby": "^10.0.1", + "jsonschema": "^1.2.4", + "lodash": "^4.17.21", + "mocha": "^10.2.0", + "node-emoji": "^1.10.0", + "pify": "^4.0.1", + "recursive-readdir": "^2.2.2", + "sc-istanbul": "^0.4.5", + "semver": "^7.3.4", + "shelljs": "^0.8.3", + "web3-utils": "^1.3.6" + }, + "bin": { + "solidity-coverage": "plugins/bin.js" + }, + "peerDependencies": { + "hardhat": "^2.11.0" + } + }, + "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", + "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/solidity-coverage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/solidity-coverage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/solidity-coverage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/solidity-coverage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solidity-coverage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6461,6 +11784,17 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6488,6 +11822,39 @@ "node": ">=8" } }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -6501,13 +11868,22 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-format": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", "dev": true, - "license": "WTFPL OR MIT", - "peer": true + "license": "WTFPL OR MIT" }, "node_modules/string-length": { "version": "4.0.2", @@ -6674,6 +12050,20 @@ "node": ">=6" } }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6710,6 +12100,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sync-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", + "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "http-response-object": "^3.0.1", + "sync-rpc": "^1.2.1", + "then-request": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sync-rpc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", + "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "get-port": "^3.1.0" + } + }, "node_modules/synckit": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", @@ -6726,19 +12143,36 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/synckit/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true - }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/table-layout": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", @@ -6755,7 +12189,6 @@ "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -6766,11 +12199,36 @@ "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, + "node_modules/table/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -6800,6 +12258,79 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/then-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/then-request/node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/then-request/node_modules/form-data": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", + "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -6827,13 +12358,22 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/ts-command-line-args": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "chalk": "^4.1.0", "command-line-args": "^5.1.1", @@ -6926,6 +12466,62 @@ "node": ">=10" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -6945,6 +12541,27 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, + "node_modules/tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true, + "license": "Unlicense" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6984,7 +12601,6 @@ "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/prettier": "^2.1.1", "debug": "^4.3.1", @@ -7010,7 +12626,6 @@ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -7098,6 +12713,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -7118,11 +12741,25 @@ "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "peer": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -7139,6 +12776,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -7151,11 +12801,20 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", @@ -7195,6 +12854,39 @@ "punycode": "^2.1.0" } }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -7218,6 +12910,100 @@ "makeerror": "1.0.12" } }, + "node_modules/web3-utils": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", + "dev": true, + "license": "LGPL-3.0", + "peer": true, + "dependencies": { + "@ethereumjs/util": "^8.1.0", + "bn.js": "^5.2.1", + "ethereum-bloom-filters": "^1.0.6", + "ethereum-cryptography": "^2.1.2", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-utils/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7316,6 +13102,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -7325,13 +13124,20 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" @@ -7346,11 +13152,17 @@ "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -7450,6 +13262,46 @@ "node": ">=12" } }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/evm-e2e/package.json b/evm-e2e/package.json index f1ed51dac..149b78524 100644 --- a/evm-e2e/package.json +++ b/evm-e2e/package.json @@ -11,9 +11,8 @@ "devDependencies": { "@jest/globals": "^29.7.0", "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", "@types/jest": "^29.5.12", - "bun": "^1.1.30", - "bun-types": "^1.0.3", "dotenv": "^16.4.5", "eslint": "^8.0.0", "eslint-config-airbnb": "^19.0.4", @@ -23,10 +22,16 @@ "eslint-plugin-prettier": "^5.1.3", "ethers": "^6.12.1", "jest": "^29.7.0", - "ts-jest": "^29.2.4" + "prettier": "^3.3.3", + "ts-jest": "^29.2.4", + "typechain": "^8.3.2", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@openzeppelin/contracts": "^5.1.0", + "hardhat": "^2.22.15" }, "scripts": { "test": "jest", - "gen-types": "typechain --target=ethers-v6 contracts/*Compiled.json" + "format": "prettier --write \"test/**/*.ts\"", + "format:check": "prettier --check \"test/**/*.ts\"" } } diff --git a/evm-e2e/test/contract_infinite_loop_gas.test.ts b/evm-e2e/test/contract_infinite_loop_gas.test.ts index 0c48a6e93..6508e0dce 100644 --- a/evm-e2e/test/contract_infinite_loop_gas.test.ts +++ b/evm-e2e/test/contract_infinite_loop_gas.test.ts @@ -1,21 +1,21 @@ -import { describe, expect, it } from "@jest/globals" -import { toBigInt } from "ethers" -import { deployContractInfiniteLoopGas } from "./utils" +import { describe, expect, it } from '@jest/globals'; +import { toBigInt } from 'ethers'; +import { deployContractInfiniteLoopGas } from './utils'; -describe("Infinite loop gas contract", () => { - it("should fail due to out of gas error", async () => { - const contract = await deployContractInfiniteLoopGas() +describe('Infinite loop gas contract', () => { + it('should fail due to out of gas error', async () => { + const contract = await deployContractInfiniteLoopGas(); - expect(contract.counter()).resolves.toBe(toBigInt(0)) + expect(contract.counter()).resolves.toBe(toBigInt(0)); try { - const tx = await contract.forever({ gasLimit: 1e6 }) - await tx.wait() - throw new Error("The transaction should have failed but did not.") + const tx = await contract.forever({ gasLimit: 1e6 }); + await tx.wait(); + throw new Error('The transaction should have failed but did not.'); } catch (error) { - expect(error.message).toContain("transaction execution reverted") + expect(error.message).toContain('transaction execution reverted'); } - expect(contract.counter()).resolves.toBe(toBigInt(0)) - }, 20e3) -}) + expect(contract.counter()).resolves.toBe(toBigInt(0)); + }, 20e3); +}); diff --git a/evm-e2e/test/contract_send_nibi.test.ts b/evm-e2e/test/contract_send_nibi.test.ts index 2c47e0ca2..fa474b434 100644 --- a/evm-e2e/test/contract_send_nibi.test.ts +++ b/evm-e2e/test/contract_send_nibi.test.ts @@ -9,32 +9,29 @@ * The methods tested are from the smart contract, * "evm-e2e/contracts/SendReceiveNibi.sol". */ -import { describe, expect, it } from "@jest/globals" -import { parseEther, toBigInt, Wallet } from "ethers" -import { account, provider } from "./setup" -import { deployContractSendNibi } from "./utils" +import { describe, expect, it } from '@jest/globals'; +import { parseEther, toBigInt, Wallet } from 'ethers'; +import { account, provider } from './setup'; +import { deployContractSendNibi } from './utils'; -async function testSendNibi( - method: "sendViaTransfer" | "sendViaSend" | "sendViaCall", - weiToSend: bigint, -) { - const contract = await deployContractSendNibi() - const recipient = Wallet.createRandom() +async function testSendNibi(method: 'sendViaTransfer' | 'sendViaSend' | 'sendViaCall', weiToSend: bigint) { + const contract = await deployContractSendNibi(); + const recipient = Wallet.createRandom(); - const ownerBalanceBefore = await provider.getBalance(account) - const recipientBalanceBefore = await provider.getBalance(recipient) - expect(recipientBalanceBefore).toEqual(BigInt(0)) + const ownerBalanceBefore = await provider.getBalance(account); + const recipientBalanceBefore = await provider.getBalance(recipient); + expect(recipientBalanceBefore).toEqual(BigInt(0)); - const tx = await contract[method](recipient, { value: weiToSend }) - const receipt = await tx.wait(1, 5e3) + const tx = await contract[method](recipient, { value: weiToSend }); + const receipt = await tx.wait(1, 5e3); - const tenPow12 = toBigInt(1e12) - const txCostMicronibi = weiToSend / tenPow12 + receipt.gasUsed - const txCostWei = txCostMicronibi * tenPow12 - const expectedOwnerWei = ownerBalanceBefore - txCostWei + const tenPow12 = toBigInt(1e12); + const txCostMicronibi = weiToSend / tenPow12 + receipt.gasUsed; + const txCostWei = txCostMicronibi * tenPow12; + const expectedOwnerWei = ownerBalanceBefore - txCostWei; - const ownerBalanceAfter = await provider.getBalance(account) - const recipientBalanceAfter = await provider.getBalance(recipient) + const ownerBalanceAfter = await provider.getBalance(account); + const recipientBalanceAfter = await provider.getBalance(recipient); console.debug(`DEBUG method ${method} %o:`, { ownerBalanceBefore, @@ -47,39 +44,39 @@ async function testSendNibi( gasPrice: `${receipt.gasPrice.toString()}`, to: receipt.to, from: receipt.from, - }) - expect(recipientBalanceAfter).toBe(weiToSend) - const delta = ownerBalanceAfter - expectedOwnerWei - const deltaFromExpectation = delta >= 0 ? delta : -delta - expect(deltaFromExpectation).toBeLessThan(parseEther("0.1")) + }); + expect(recipientBalanceAfter).toBe(weiToSend); + const delta = ownerBalanceAfter - expectedOwnerWei; + const deltaFromExpectation = delta >= 0 ? delta : -delta; + expect(deltaFromExpectation).toBeLessThan(parseEther('0.1')); } -describe("Send NIBI via smart contract", () => { - const TIMEOUT_MS = 20e3 +describe('Send NIBI via smart contract', () => { + const TIMEOUT_MS = 20e3; it( - "method sendViaTransfer", + 'method sendViaTransfer', async () => { - const weiToSend: bigint = toBigInt(5e12) * toBigInt(1e6) - await testSendNibi("sendViaTransfer", weiToSend) + const weiToSend: bigint = toBigInt(5e12) * toBigInt(1e6); + await testSendNibi('sendViaTransfer', weiToSend); }, TIMEOUT_MS, - ) + ); it( - "method sendViaSend", + 'method sendViaSend', async () => { - const weiToSend: bigint = toBigInt(100e12) * toBigInt(1e6) - await testSendNibi("sendViaSend", weiToSend) + const weiToSend: bigint = toBigInt(100e12) * toBigInt(1e6); + await testSendNibi('sendViaSend', weiToSend); }, TIMEOUT_MS, - ) + ); it( - "method sendViaCall", + 'method sendViaCall', async () => { - const weiToSend: bigint = toBigInt(100e12) * toBigInt(1e6) - await testSendNibi("sendViaCall", weiToSend) + const weiToSend: bigint = toBigInt(100e12) * toBigInt(1e6); + await testSendNibi('sendViaCall', weiToSend); }, TIMEOUT_MS, - ) -}) + ); +}); diff --git a/evm-e2e/test/debug_queries.test.ts b/evm-e2e/test/debug_queries.test.ts index 180ef2ab6..e58901c31 100644 --- a/evm-e2e/test/debug_queries.test.ts +++ b/evm-e2e/test/debug_queries.test.ts @@ -1,131 +1,125 @@ -import { describe, expect, it, beforeAll } from "@jest/globals" -import { TransactionReceipt, parseEther } from "ethers" -import { provider } from "./setup" -import { alice, deployContractTestERC20, hexify } from "./utils" -import { TestERC20Compiled__factory } from "../types/ethers-contracts" +import { describe, expect, it, beforeAll } from '@jest/globals'; +import { TransactionReceipt, parseEther } from 'ethers'; +import { provider } from './setup'; +import { alice, deployContractTestERC20, hexify } from './utils'; +import { TestERC20__factory } from '../types'; -describe("debug queries", () => { - let contractAddress: string - let txHash: string - let txIndex: number - let blockNumber: number - let blockHash: string +describe('debug queries', () => { + let contractAddress: string; + let txHash: string; + let txIndex: number; + let blockNumber: number; + let blockHash: string; beforeAll(async () => { // Deploy ERC-20 contract - const contract = await deployContractTestERC20() - contractAddress = await contract.getAddress() + const contract = await deployContractTestERC20(); + contractAddress = await contract.getAddress(); // Execute some contract TX - const txResponse = await contract.transfer(alice, parseEther("0.01")) - await txResponse.wait(1, 5e3) + const txResponse = await contract.transfer(alice, parseEther('0.01')); + await txResponse.wait(1, 5e3); - const receipt: TransactionReceipt = await provider.getTransactionReceipt( - txResponse.hash, - ) - txHash = txResponse.hash - txIndex = txResponse.index - blockNumber = receipt.blockNumber - blockHash = receipt.blockHash - }, 20e3) + const receipt: TransactionReceipt = await provider.getTransactionReceipt(txResponse.hash); + txHash = txResponse.hash; + txIndex = txResponse.index; + blockNumber = receipt.blockNumber; + blockHash = receipt.blockHash; + }, 20e3); - it("debug_traceBlockByNumber", async () => { - const traceResult = await provider.send("debug_traceBlockByNumber", [ + it('debug_traceBlockByNumber', async () => { + const traceResult = await provider.send('debug_traceBlockByNumber', [ blockNumber, { - tracer: "callTracer", - timeout: "3000s", + tracer: 'callTracer', + timeout: '3000s', tracerConfig: { onlyTopCall: false }, }, - ]) - expectTrace(traceResult) - }) + ]); + expectTrace(traceResult); + }); - it("debug_traceBlockByHash", async () => { - const traceResult = await provider.send("debug_traceBlockByHash", [ + it('debug_traceBlockByHash', async () => { + const traceResult = await provider.send('debug_traceBlockByHash', [ blockHash, { - tracer: "callTracer", - timeout: "3000s", + tracer: 'callTracer', + timeout: '3000s', tracerConfig: { onlyTopCall: false }, }, - ]) - expectTrace(traceResult) - }) + ]); + expectTrace(traceResult); + }); - it("debug_traceTransaction", async () => { - const traceResult = await provider.send("debug_traceTransaction", [ + it('debug_traceTransaction', async () => { + const traceResult = await provider.send('debug_traceTransaction', [ txHash, { - tracer: "callTracer", - timeout: "3000s", + tracer: 'callTracer', + timeout: '3000s', tracerConfig: { onlyTopCall: false }, }, - ]) - expectTrace([{ result: traceResult }]) - }) + ]); + expectTrace([{ result: traceResult }]); + }); - it("debug_traceCall", async () => { - const contractInterface = TestERC20Compiled__factory.createInterface() - const callData = contractInterface.encodeFunctionData("totalSupply") + it('debug_traceCall', async () => { + const contractInterface = TestERC20__factory.createInterface(); + const callData = contractInterface.encodeFunctionData('totalSupply'); const tx = { to: contractAddress, data: callData, gas: hexify(1000_000), - } - const traceResult = await provider.send("debug_traceCall", [ + }; + const traceResult = await provider.send('debug_traceCall', [ tx, - "latest", + 'latest', { - tracer: "callTracer", - timeout: "3000s", + tracer: 'callTracer', + timeout: '3000s', tracerConfig: { onlyTopCall: false }, }, - ]) - expectTrace([{ result: traceResult }]) - }) + ]); + expectTrace([{ result: traceResult }]); + }); // TODO: impl in EVM - it("debug_getBadBlocks", async () => { + it('debug_getBadBlocks', async () => { try { - const traceResult = await provider.send("debug_getBadBlocks", [txHash]) - expect(traceResult).toBeDefined() + const traceResult = await provider.send('debug_getBadBlocks', [txHash]); + expect(traceResult).toBeDefined(); } catch (err) { - expect(err.message).toContain( - "the method debug_getBadBlocks does not exist", - ) + expect(err.message).toContain('the method debug_getBadBlocks does not exist'); } - }) + }); // TODO: impl in EVM - it("debug_storageRangeAt", async () => { + it('debug_storageRangeAt', async () => { try { - const traceResult = await provider.send("debug_storageRangeAt", [ + const traceResult = await provider.send('debug_storageRangeAt', [ blockNumber, txIndex, contractAddress, - "0x0", + '0x0', 100, - ]) - expect(traceResult).toBeDefined() + ]); + expect(traceResult).toBeDefined(); } catch (err) { - expect(err.message).toContain( - "the method debug_storageRangeAt does not exist", - ) + expect(err.message).toContain('the method debug_storageRangeAt does not exist'); } - }) -}) + }); +}); const expectTrace = (traceResult: any[]) => { - expect(traceResult).toBeDefined() - expect(traceResult.length).toBeGreaterThan(0) + expect(traceResult).toBeDefined(); + expect(traceResult.length).toBeGreaterThan(0); - const trace = traceResult[0]["result"] - expect(trace).toHaveProperty("from") - expect(trace).toHaveProperty("to") - expect(trace).toHaveProperty("gas") - expect(trace).toHaveProperty("gasUsed") - expect(trace).toHaveProperty("input") - expect(trace).toHaveProperty("output") - expect(trace).toHaveProperty("type", "CALL") -} + const trace = traceResult[0]['result']; + expect(trace).toHaveProperty('from'); + expect(trace).toHaveProperty('to'); + expect(trace).toHaveProperty('gas'); + expect(trace).toHaveProperty('gasUsed'); + expect(trace).toHaveProperty('input'); + expect(trace).toHaveProperty('output'); + expect(trace).toHaveProperty('type', 'CALL'); +}; diff --git a/evm-e2e/test/erc20.test.ts b/evm-e2e/test/erc20.test.ts index d30bba208..1405253ea 100644 --- a/evm-e2e/test/erc20.test.ts +++ b/evm-e2e/test/erc20.test.ts @@ -1,27 +1,25 @@ -import { describe, expect, it } from "@jest/globals" -import { parseUnits, toBigInt, Wallet } from "ethers" -import { account } from "./setup" -import { deployContractTestERC20 } from "./utils" +import { describe, expect, it } from '@jest/globals'; +import { parseUnits, toBigInt, Wallet } from 'ethers'; +import { account } from './setup'; +import { deployContractTestERC20 } from './utils'; -describe("ERC-20 contract tests", () => { - it("should send properly", async () => { - const contract = await deployContractTestERC20() - expect(contract.getAddress()).resolves.toBeDefined() +describe('ERC-20 contract tests', () => { + it('should send properly', async () => { + const contract = await deployContractTestERC20(); + expect(contract.getAddress()).resolves.toBeDefined(); - const ownerInitialBalance = parseUnits("1000000", 18) - const alice = Wallet.createRandom() + const ownerInitialBalance = parseUnits('1000000', 18); + const alice = Wallet.createRandom(); - expect(contract.balanceOf(account)).resolves.toEqual(ownerInitialBalance) - expect(contract.balanceOf(alice)).resolves.toEqual(toBigInt(0)) + expect(contract.balanceOf(account)).resolves.toEqual(ownerInitialBalance); + expect(contract.balanceOf(alice)).resolves.toEqual(toBigInt(0)); // send to alice - const amountToSend = parseUnits("1000", 18) // contract tokens - let tx = await contract.transfer(alice, amountToSend) - await tx.wait() + const amountToSend = parseUnits('1000', 18); // contract tokens + let tx = await contract.transfer(alice, amountToSend); + await tx.wait(); - expect(contract.balanceOf(account)).resolves.toEqual( - ownerInitialBalance - amountToSend, - ) - expect(contract.balanceOf(alice)).resolves.toEqual(amountToSend) - }, 20e3) -}) + expect(contract.balanceOf(account)).resolves.toEqual(ownerInitialBalance - amountToSend); + expect(contract.balanceOf(alice)).resolves.toEqual(amountToSend); + }, 20e3); +}); diff --git a/evm-e2e/test/eth_queries.test.ts b/evm-e2e/test/eth_queries.test.ts index c45b0e452..13bcb13a0 100644 --- a/evm-e2e/test/eth_queries.test.ts +++ b/evm-e2e/test/eth_queries.test.ts @@ -1,6 +1,6 @@ -import { describe, expect, it, jest } from "@jest/globals" -import { parseEther, keccak256, AbiCoder } from "ethers" -import { account, provider } from "./setup" +import { describe, expect, it, jest } from '@jest/globals'; +import { parseEther, keccak256, AbiCoder } from 'ethers'; +import { account, provider } from './setup'; import { INTRINSIC_TX_GAS, alice, @@ -8,294 +8,257 @@ import { deployContractSendNibi, hexify, sendTestNibi, -} from "./utils" +} from './utils'; -describe("eth queries", () => { - jest.setTimeout(15e3) +describe('eth queries', () => { + jest.setTimeout(15e3); - it("eth_accounts", async () => { - const accounts = await provider.listAccounts() - expect(accounts).not.toHaveLength(0) - }) + it('eth_accounts', async () => { + const accounts = await provider.listAccounts(); + expect(accounts).not.toHaveLength(0); + }); - it("eth_estimateGas", async () => { + it('eth_estimateGas', async () => { const tx = { from: account.address, to: alice, - value: parseEther("0.01"), // Sending 0.01 Ether - } - const estimatedGas = await provider.estimateGas(tx) - expect(estimatedGas).toBeGreaterThan(BigInt(0)) - expect(estimatedGas).toEqual(INTRINSIC_TX_GAS) - }) - - it("eth_feeHistory", async () => { - const blockCount = 5 // Number of blocks in the requested history - const newestBlock = "latest" // Can be a block number or 'latest' - const rewardPercentiles = [25, 50, 75] // Example percentiles for priority fees - - const feeHistory = await provider.send("eth_feeHistory", [ - blockCount, - newestBlock, - rewardPercentiles, - ]) - expect(feeHistory).toBeDefined() - expect(feeHistory).toHaveProperty("baseFeePerGas") - expect(feeHistory).toHaveProperty("gasUsedRatio") - expect(feeHistory).toHaveProperty("oldestBlock") - expect(feeHistory).toHaveProperty("reward") - }) - - it("eth_gasPrice", async () => { - const gasPrice = await provider.send("eth_gasPrice", []) - expect(gasPrice).toBeDefined() - expect(gasPrice).toEqual(hexify(1000000000000)) // 1 micronibi == 10^{12} wei - }) - - it("eth_getBalance", async () => { - const balance = await provider.getBalance(account.address) - expect(balance).toBeGreaterThan(0) - }) - - it("eth_getBlockByNumber, eth_getBlockByHash", async () => { - const blockNumber = 1 - const blockByNumber = await provider.send("eth_getBlockByNumber", [ - blockNumber, - false, - ]) - expect(blockByNumber).toBeDefined() - expect(blockByNumber).toHaveProperty("hash") - - const blockByHash = await provider.send("eth_getBlockByHash", [ - blockByNumber.hash, - false, - ]) - expect(blockByHash).toBeDefined() - expect(blockByHash.hash).toEqual(blockByNumber.hash) - expect(blockByHash.number).toEqual(blockByNumber.number) - }) - - it("eth_getBlockTransactionCountByHash", async () => { - const blockNumber = 1 - const block = await provider.send("eth_getBlockByNumber", [ - blockNumber, - false, - ]) - const txCount = await provider.send("eth_getBlockTransactionCountByHash", [ - block.hash, - ]) - expect(parseInt(txCount)).toBeGreaterThanOrEqual(0) - }) - - it("eth_getBlockTransactionCountByNumber", async () => { - const blockNumber = 1 - const txCount = await provider.send( - "eth_getBlockTransactionCountByNumber", - [blockNumber], - ) - expect(parseInt(txCount)).toBeGreaterThanOrEqual(0) - }) - - it("eth_getCode", async () => { - const contract = await deployContractSendNibi() - const contractAddr = await contract.getAddress() - const code = await provider.send("eth_getCode", [contractAddr, "latest"]) - expect(code).toBeDefined() - }) - - it("eth_getFilterChanges", async () => { + value: parseEther('0.01'), // Sending 0.01 Ether + }; + const estimatedGas = await provider.estimateGas(tx); + expect(estimatedGas).toBeGreaterThan(BigInt(0)); + expect(estimatedGas).toEqual(INTRINSIC_TX_GAS); + }); + + it('eth_feeHistory', async () => { + const blockCount = 5; // Number of blocks in the requested history + const newestBlock = 'latest'; // Can be a block number or 'latest' + const rewardPercentiles = [25, 50, 75]; // Example percentiles for priority fees + + const feeHistory = await provider.send('eth_feeHistory', [blockCount, newestBlock, rewardPercentiles]); + expect(feeHistory).toBeDefined(); + expect(feeHistory).toHaveProperty('baseFeePerGas'); + expect(feeHistory).toHaveProperty('gasUsedRatio'); + expect(feeHistory).toHaveProperty('oldestBlock'); + expect(feeHistory).toHaveProperty('reward'); + }); + + it('eth_gasPrice', async () => { + const gasPrice = await provider.send('eth_gasPrice', []); + expect(gasPrice).toBeDefined(); + expect(gasPrice).toEqual(hexify(1000000000000)); // 1 micronibi == 10^{12} wei + }); + + it('eth_getBalance', async () => { + const balance = await provider.getBalance(account.address); + expect(balance).toBeGreaterThan(0); + }); + + it('eth_getBlockByNumber, eth_getBlockByHash', async () => { + const blockNumber = 1; + const blockByNumber = await provider.send('eth_getBlockByNumber', [blockNumber, false]); + expect(blockByNumber).toBeDefined(); + expect(blockByNumber).toHaveProperty('hash'); + + const blockByHash = await provider.send('eth_getBlockByHash', [blockByNumber.hash, false]); + expect(blockByHash).toBeDefined(); + expect(blockByHash.hash).toEqual(blockByNumber.hash); + expect(blockByHash.number).toEqual(blockByNumber.number); + }); + + it('eth_getBlockTransactionCountByHash', async () => { + const blockNumber = 1; + const block = await provider.send('eth_getBlockByNumber', [blockNumber, false]); + const txCount = await provider.send('eth_getBlockTransactionCountByHash', [block.hash]); + expect(parseInt(txCount)).toBeGreaterThanOrEqual(0); + }); + + it('eth_getBlockTransactionCountByNumber', async () => { + const blockNumber = 1; + const txCount = await provider.send('eth_getBlockTransactionCountByNumber', [blockNumber]); + expect(parseInt(txCount)).toBeGreaterThanOrEqual(0); + }); + + it('eth_getCode', async () => { + const contract = await deployContractSendNibi(); + const contractAddr = await contract.getAddress(); + const code = await provider.send('eth_getCode', [contractAddr, 'latest']); + expect(code).toBeDefined(); + }); + + it('eth_getFilterChanges', async () => { // Deploy ERC-20 contract - const contract = await deployContractTestERC20() - const contractAddr = await contract.getAddress() + const contract = await deployContractTestERC20(); + const contractAddr = await contract.getAddress(); const filter = { - fromBlock: "0x1", + fromBlock: '0x1', address: contractAddr, - } + }; // Create the filter for a contract - const filterId = await provider.send("eth_newFilter", [filter]) - expect(filterId).toBeDefined() + const filterId = await provider.send('eth_newFilter', [filter]); + expect(filterId).toBeDefined(); // Execute some contract TX - const tx = await contract.transfer(alice, parseEther("0.01")) - await tx.wait(1, 5e3) - await new Promise((resolve) => setTimeout(resolve, 3000)) + const tx = await contract.transfer(alice, parseEther('0.01')); + await tx.wait(1, 5e3); + await new Promise((resolve) => setTimeout(resolve, 3000)); // Assert logs - const changes = await provider.send("eth_getFilterChanges", [filterId]) - expect(changes.length).toBeGreaterThan(0) - expect(changes[0]).toHaveProperty("address") - expect(changes[0]).toHaveProperty("data") - expect(changes[0]).toHaveProperty("topics") + const changes = await provider.send('eth_getFilterChanges', [filterId]); + expect(changes.length).toBeGreaterThan(0); + expect(changes[0]).toHaveProperty('address'); + expect(changes[0]).toHaveProperty('data'); + expect(changes[0]).toHaveProperty('topics'); - const success = await provider.send("eth_uninstallFilter", [filterId]) - expect(success).toBeTruthy() - }) + const success = await provider.send('eth_uninstallFilter', [filterId]); + expect(success).toBeTruthy(); + }); - it("eth_getFilterLogs", async () => { + it('eth_getFilterLogs', async () => { // Deploy ERC-20 contract - const contract = await deployContractTestERC20() - const contractAddr = await contract.getAddress() + const contract = await deployContractTestERC20(); + const contractAddr = await contract.getAddress(); const filter = { - fromBlock: "0x1", + fromBlock: '0x1', address: contractAddr, - } + }; // Execute some contract TX - const tx = await contract.transfer(alice, parseEther("0.01")) - await tx.wait(1, 5e3) - await new Promise((resolve) => setTimeout(resolve, 3000)) + const tx = await contract.transfer(alice, parseEther('0.01')); + await tx.wait(1, 5e3); + await new Promise((resolve) => setTimeout(resolve, 3000)); // Create the filter for a contract - const filterId = await provider.send("eth_newFilter", [filter]) - expect(filterId).toBeDefined() + const filterId = await provider.send('eth_newFilter', [filter]); + expect(filterId).toBeDefined(); // Assert logs - const changes = await provider.send("eth_getFilterLogs", [filterId]) - expect(changes.length).toBeGreaterThan(0) - expect(changes[0]).toHaveProperty("address") - expect(changes[0]).toHaveProperty("data") - expect(changes[0]).toHaveProperty("topics") - }) - - it("eth_getLogs", async () => { + const changes = await provider.send('eth_getFilterLogs', [filterId]); + expect(changes.length).toBeGreaterThan(0); + expect(changes[0]).toHaveProperty('address'); + expect(changes[0]).toHaveProperty('data'); + expect(changes[0]).toHaveProperty('topics'); + }); + + it('eth_getLogs', async () => { // Deploy ERC-20 contract - const contract = await deployContractTestERC20() - const contractAddr = await contract.getAddress() + const contract = await deployContractTestERC20(); + const contractAddr = await contract.getAddress(); const filter = { - fromBlock: "0x1", + fromBlock: '0x1', address: contractAddr, - } + }; // Execute some contract TX - const tx = await contract.transfer(alice, parseEther("0.01")) - await tx.wait(1, 5e3) - await new Promise((resolve) => setTimeout(resolve, 3000)) + const tx = await contract.transfer(alice, parseEther('0.01')); + await tx.wait(1, 5e3); + await new Promise((resolve) => setTimeout(resolve, 3000)); // Assert logs - const changes = await provider.send("eth_getLogs", [filter]) - expect(changes.length).toBeGreaterThan(0) - expect(changes[0]).toHaveProperty("address") - expect(changes[0]).toHaveProperty("data") - expect(changes[0]).toHaveProperty("topics") - }) - - it("eth_getProof", async () => { + const changes = await provider.send('eth_getLogs', [filter]); + expect(changes.length).toBeGreaterThan(0); + expect(changes[0]).toHaveProperty('address'); + expect(changes[0]).toHaveProperty('data'); + expect(changes[0]).toHaveProperty('topics'); + }); + + it('eth_getProof', async () => { // Deploy ERC-20 contract - const contract = await deployContractTestERC20() - const contractAddr = await contract.getAddress() - - const slot = 1 // Assuming balanceOf is at slot 1 - const storageKey = keccak256( - AbiCoder.defaultAbiCoder().encode( - ["address", "uint256"], - [account.address, slot], - ), - ) - const proof = await provider.send("eth_getProof", [ - contractAddr, - [storageKey], - "latest", - ]) + const contract = await deployContractTestERC20(); + const contractAddr = await contract.getAddress(); + + const slot = 1; // Assuming balanceOf is at slot 1 + const storageKey = keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'uint256'], [account.address, slot])); + const proof = await provider.send('eth_getProof', [contractAddr, [storageKey], 'latest']); // Assert proof structure - expect(proof).toHaveProperty("address") - expect(proof).toHaveProperty("balance") - expect(proof).toHaveProperty("codeHash") - expect(proof).toHaveProperty("nonce") - expect(proof).toHaveProperty("storageProof") + expect(proof).toHaveProperty('address'); + expect(proof).toHaveProperty('balance'); + expect(proof).toHaveProperty('codeHash'); + expect(proof).toHaveProperty('nonce'); + expect(proof).toHaveProperty('storageProof'); if (proof.storageProof.length > 0) { - expect(proof.storageProof[0]).toHaveProperty("key", storageKey) - expect(proof.storageProof[0]).toHaveProperty("value") - expect(proof.storageProof[0]).toHaveProperty("proof") + expect(proof.storageProof[0]).toHaveProperty('key', storageKey); + expect(proof.storageProof[0]).toHaveProperty('value'); + expect(proof.storageProof[0]).toHaveProperty('proof'); } - }) + }); - it("eth_getStorageAt", async () => { - const contract = await deployContractTestERC20() - const contractAddr = await contract.getAddress() + it('eth_getStorageAt', async () => { + const contract = await deployContractTestERC20(); + const contractAddr = await contract.getAddress(); - const value = await provider.getStorage(contractAddr, 1) - expect(value).toBeDefined() - }) + const value = await provider.getStorage(contractAddr, 1); + expect(value).toBeDefined(); + }); - it("eth_getTransactionByBlockHashAndIndex, eth_getTransactionByBlockNumberAndIndex", async () => { + it('eth_getTransactionByBlockHashAndIndex, eth_getTransactionByBlockNumberAndIndex', async () => { // Execute EVM transfer - const txResponse = await sendTestNibi() - const block = await txResponse.getBlock() - - const txByBlockHash = await provider.send( - "eth_getTransactionByBlockHashAndIndex", - [block.hash, "0x0"], - ) - expect(txByBlockHash).toBeDefined() - expect(txByBlockHash).toHaveProperty("from") - expect(txByBlockHash).toHaveProperty("to") - expect(txByBlockHash).toHaveProperty("blockHash") - expect(txByBlockHash).toHaveProperty("blockNumber") - expect(txByBlockHash).toHaveProperty("value") - - const txByBlockNumber = await provider.send( - "eth_getTransactionByBlockNumberAndIndex", - [block.number, "0x0"], - ) - - expect(txByBlockNumber).toBeDefined() - expect(txByBlockNumber["from"]).toEqual(txByBlockHash["from"]) - expect(txByBlockNumber["to"]).toEqual(txByBlockHash["to"]) - expect(txByBlockNumber["value"]).toEqual(txByBlockHash["value"]) - }) - - it("eth_getTransactionByHash", async () => { - const txResponse = await sendTestNibi() - const txByHash = await provider.getTransaction(txResponse.hash) - expect(txByHash).toBeDefined() - expect(txByHash.hash).toEqual(txResponse.hash) - }) - - it("eth_getTransactionCount", async () => { - const txCount = await provider.getTransactionCount(account.address) - expect(txCount).toBeGreaterThanOrEqual(0) - }) - - it("eth_getTransactionReceipt", async () => { - const txResponse = await sendTestNibi() - const txReceipt = await provider.getTransactionReceipt(txResponse.hash) - expect(txReceipt).toBeDefined() - expect(txReceipt.hash).toEqual(txResponse.hash) - }) - - it("eth_getUncleCountByBlockHash", async () => { - const latestBlock = await provider.getBlockNumber() - const block = await provider.getBlock(latestBlock) - const uncleCount = await provider.send("eth_getUncleCountByBlockHash", [ - block.hash, - ]) - expect(parseInt(uncleCount)).toBeGreaterThanOrEqual(0) - }) - - it("eth_getUncleCountByBlockNumber", async () => { - const latestBlock = await provider.getBlockNumber() - const uncleCount = await provider.send("eth_getUncleCountByBlockNumber", [ - latestBlock, - ]) - expect(parseInt(uncleCount)).toBeGreaterThanOrEqual(0) - }) - - it("eth_maxPriorityFeePerGas", async () => { - const maxPriorityGas = await provider.send("eth_maxPriorityFeePerGas", []) - expect(parseInt(maxPriorityGas)).toBeGreaterThanOrEqual(0) - }) - - it("eth_newBlockFilter", async () => { - const filterId = await provider.send("eth_newBlockFilter", []) - expect(filterId).toBeDefined() - }) - - it("eth_newPendingTransactionFilter", async () => { - const filterId = await provider.send("eth_newPendingTransactionFilter", []) - expect(filterId).toBeDefined() - }) - - it("eth_syncing", async () => { - const syncing = await provider.send("eth_syncing", []) - expect(syncing).toBeFalsy() - }) -}) + const txResponse = await sendTestNibi(); + const block = await txResponse.getBlock(); + + const txByBlockHash = await provider.send('eth_getTransactionByBlockHashAndIndex', [block.hash, '0x0']); + expect(txByBlockHash).toBeDefined(); + expect(txByBlockHash).toHaveProperty('from'); + expect(txByBlockHash).toHaveProperty('to'); + expect(txByBlockHash).toHaveProperty('blockHash'); + expect(txByBlockHash).toHaveProperty('blockNumber'); + expect(txByBlockHash).toHaveProperty('value'); + + const txByBlockNumber = await provider.send('eth_getTransactionByBlockNumberAndIndex', [block.number, '0x0']); + + expect(txByBlockNumber).toBeDefined(); + expect(txByBlockNumber['from']).toEqual(txByBlockHash['from']); + expect(txByBlockNumber['to']).toEqual(txByBlockHash['to']); + expect(txByBlockNumber['value']).toEqual(txByBlockHash['value']); + }); + + it('eth_getTransactionByHash', async () => { + const txResponse = await sendTestNibi(); + const txByHash = await provider.getTransaction(txResponse.hash); + expect(txByHash).toBeDefined(); + expect(txByHash.hash).toEqual(txResponse.hash); + }); + + it('eth_getTransactionCount', async () => { + const txCount = await provider.getTransactionCount(account.address); + expect(txCount).toBeGreaterThanOrEqual(0); + }); + + it('eth_getTransactionReceipt', async () => { + const txResponse = await sendTestNibi(); + const txReceipt = await provider.getTransactionReceipt(txResponse.hash); + expect(txReceipt).toBeDefined(); + expect(txReceipt.hash).toEqual(txResponse.hash); + }); + + it('eth_getUncleCountByBlockHash', async () => { + const latestBlock = await provider.getBlockNumber(); + const block = await provider.getBlock(latestBlock); + const uncleCount = await provider.send('eth_getUncleCountByBlockHash', [block.hash]); + expect(parseInt(uncleCount)).toBeGreaterThanOrEqual(0); + }); + + it('eth_getUncleCountByBlockNumber', async () => { + const latestBlock = await provider.getBlockNumber(); + const uncleCount = await provider.send('eth_getUncleCountByBlockNumber', [latestBlock]); + expect(parseInt(uncleCount)).toBeGreaterThanOrEqual(0); + }); + + it('eth_maxPriorityFeePerGas', async () => { + const maxPriorityGas = await provider.send('eth_maxPriorityFeePerGas', []); + expect(parseInt(maxPriorityGas)).toBeGreaterThanOrEqual(0); + }); + + it('eth_newBlockFilter', async () => { + const filterId = await provider.send('eth_newBlockFilter', []); + expect(filterId).toBeDefined(); + }); + + it('eth_newPendingTransactionFilter', async () => { + const filterId = await provider.send('eth_newPendingTransactionFilter', []); + expect(filterId).toBeDefined(); + }); + + it('eth_syncing', async () => { + const syncing = await provider.send('eth_syncing', []); + expect(syncing).toBeFalsy(); + }); +}); diff --git a/evm-e2e/test/native_transfer.test.ts b/evm-e2e/test/native_transfer.test.ts index 803dfd43b..475ab270b 100644 --- a/evm-e2e/test/native_transfer.test.ts +++ b/evm-e2e/test/native_transfer.test.ts @@ -1,45 +1,45 @@ -import { describe, expect, it } from "@jest/globals" -import { parseEther, toBigInt } from "ethers" -import { account, provider } from "./setup" -import { alice } from "./utils" +import { describe, expect, it } from '@jest/globals'; +import { parseEther, toBigInt } from 'ethers'; +import { account, provider } from './setup'; +import { alice } from './utils'; -describe("native transfer", () => { - it("simple transfer, balance check", async () => { - const amountToSend = toBigInt(5e12) * toBigInt(1e6) // unibi - const senderBalanceBefore = await provider.getBalance(account) - const recipientBalanceBefore = await provider.getBalance(alice) - expect(senderBalanceBefore).toBeGreaterThan(0) - expect(recipientBalanceBefore).toEqual(BigInt(0)) +describe('native transfer', () => { + it('simple transfer, balance check', async () => { + const amountToSend = toBigInt(5e12) * toBigInt(1e6); // unibi + const senderBalanceBefore = await provider.getBalance(account); + const recipientBalanceBefore = await provider.getBalance(alice); + expect(senderBalanceBefore).toBeGreaterThan(0); + expect(recipientBalanceBefore).toEqual(BigInt(0)); // Execute EVM transfer const transaction = { gasLimit: toBigInt(100e3), to: alice, value: amountToSend, - } - const txResponse = await account.sendTransaction(transaction) - await txResponse.wait(1, 10e3) - expect(txResponse).toHaveProperty("blockHash") + }; + const txResponse = await account.sendTransaction(transaction); + await txResponse.wait(1, 10e3); + expect(txResponse).toHaveProperty('blockHash'); - const senderBalanceAfter = await provider.getBalance(account) - const recipientBalanceAfter = await provider.getBalance(alice) + const senderBalanceAfter = await provider.getBalance(account); + const recipientBalanceAfter = await provider.getBalance(alice); // Assert balances with logging - const tenPow12 = toBigInt(1e12) - const gasUsed = transaction.gasLimit - const txCostMicronibi = amountToSend / tenPow12 + gasUsed - const txCostWei = txCostMicronibi * tenPow12 - const expectedSenderWei = senderBalanceBefore - txCostWei - console.debug("DEBUG should send via transfer method %o:", { + const tenPow12 = toBigInt(1e12); + const gasUsed = transaction.gasLimit; + const txCostMicronibi = amountToSend / tenPow12 + gasUsed; + const txCostWei = txCostMicronibi * tenPow12; + const expectedSenderWei = senderBalanceBefore - txCostWei; + console.debug('DEBUG should send via transfer method %o:', { senderBalanceBefore, amountToSend, expectedSenderWei, senderBalanceAfter, txResponse, - }) - expect(recipientBalanceAfter).toEqual(amountToSend) - const delta = senderBalanceAfter - expectedSenderWei - const deltaFromExpectation = delta >= 0 ? delta : -delta - expect(deltaFromExpectation).toBeLessThan(parseEther("0.1")) - }, 20e3) -}) + }); + expect(recipientBalanceAfter).toEqual(amountToSend); + const delta = senderBalanceAfter - expectedSenderWei; + const deltaFromExpectation = delta >= 0 ? delta : -delta; + expect(deltaFromExpectation).toBeLessThan(parseEther('0.1')); + }, 20e3); +}); diff --git a/evm-e2e/test/setup.ts b/evm-e2e/test/setup.ts index dd3232b55..ec2fe24b7 100644 --- a/evm-e2e/test/setup.ts +++ b/evm-e2e/test/setup.ts @@ -1,9 +1,9 @@ -import { config } from "dotenv" -import { ethers, getDefaultProvider, Wallet } from "ethers" +import { config } from 'dotenv'; +import { ethers, getDefaultProvider, Wallet } from 'ethers'; -config() +config(); -const provider = new ethers.JsonRpcProvider(process.env.JSON_RPC_ENDPOINT) -const account = Wallet.fromPhrase(process.env.MNEMONIC, provider) +const provider = new ethers.JsonRpcProvider(process.env.JSON_RPC_ENDPOINT); +const account = Wallet.fromPhrase(process.env.MNEMONIC, provider); -export { account, provider } +export { account, provider }; diff --git a/evm-e2e/test/tx_receipt.test.ts b/evm-e2e/test/tx_receipt.test.ts new file mode 100644 index 000000000..adc91286a --- /dev/null +++ b/evm-e2e/test/tx_receipt.test.ts @@ -0,0 +1,123 @@ +import { describe, expect, it, jest } from '@jest/globals'; +import { ethers, TransactionReceipt, Log } from 'ethers'; +import { account } from './setup'; +import { deployContractEventsEmitter, deployContractTransactionReverter, TENPOW12 } from './utils'; +import { TestERC20__factory } from '../types'; + +describe('Transaction Receipt Tests', () => { + jest.setTimeout(15e3); + + let recipient = ethers.Wallet.createRandom().address; + + it('simple transfer receipt', async () => { + const value = ethers.parseEther('1'); + const tx = await account.sendTransaction({ + to: recipient, + value, + }); + const receipt = await tx.wait(); + + assertBaseReceiptFields(receipt); + expect(receipt.to).toEqual(recipient); + expect(receipt.logs).toHaveLength(0); // ETH transfers have no logs + }); + + it('contract deployment receipt', async () => { + const factory = new TestERC20__factory(account); + const deployTx = await factory.deploy({ maxFeePerGas: TENPOW12 }); + const receipt = await deployTx.deploymentTransaction().wait(); + + assertBaseReceiptFields(receipt); + expect(receipt.to).toBeNull(); // Contract creation has no 'to' address + expect(receipt.contractAddress).toBeDefined(); + + // Verify the deployed contract address is valid + const code = await account.provider.getCode(receipt.contractAddress!); + expect(code).not.toEqual('0x'); + }); + + it('receipt with logs / events', async () => { + const contract = await deployContractEventsEmitter(); + const expectedValue = 123n; + + const tx = await contract.emitEvent(expectedValue); + const receipt = await tx.wait(); + + assertBaseReceiptFields(receipt); + expect(receipt.to).toEqual(contract.target.toString()); + + // Event specific checks + expect(receipt.logs.length).toEqual(1); + const event = receipt.logs[0]; + assertEventLogFields(event, contract.target.toString()); + + // Event data checks + const eventSignature = 'TestEvent(address,uint256)'; + expect(event.topics[0]).toEqual(ethers.id(eventSignature)); + expect(event.topics.length).toEqual(2); // topic[0] is hash, topic[1] is indexed param + expect(event['args'].sender).toEqual(account.address); + expect(event['args'].value).toEqual(expectedValue); + + // Verify indexed parameter encoding + expect(event.topics[1]).toEqual(ethers.zeroPadValue(account.address, 32)); // indexed address param + }); +}); + +function assertBaseReceiptFields(receipt: TransactionReceipt) { + // Basic transaction info + expect(receipt.status).toEqual(1); + expect([0, 1, 2]).toContain(receipt.type); + expect(receipt.hash).toMatch(/^0x[a-fA-F0-9]{64}$/); + expect(typeof receipt.index).toBe('number'); + + // Block info + expect(typeof receipt.blockNumber).toBe('number'); + expect(receipt.blockNumber).toBeGreaterThan(0); + expect(receipt.blockHash).toMatch(/^0x[a-fA-F0-9]{64}$/); + + // Address fields + expect(receipt.from).toEqual(account.address); + expect(receipt.from).toMatch(/^0x[a-fA-F0-9]{40}$/); + + // Gas fields + expect(typeof receipt.gasUsed).toBe('bigint'); + expect(receipt.gasUsed).toBeGreaterThan(0n); + expect(typeof receipt.cumulativeGasUsed).toBe('bigint'); + expect(receipt.cumulativeGasUsed).toBeGreaterThanOrEqual(receipt.gasUsed); + + // Logs + expect(receipt.logsBloom).toMatch(/^0x[a-fA-F0-9]{512}$/); + expect(Array.isArray(receipt.logs)).toBeTruthy(); + + // Optional fields + if (receipt.to !== null) { + expect(receipt.to).toMatch(/^0x[a-fA-F0-9]{40}$/); + } + if (receipt.contractAddress !== null) { + expect(receipt.contractAddress).toMatch(/^0x[a-fA-F0-9]{40}$/); + } +} + +function assertEventLogFields(log: Log, expectedContractAddress: string) { + // Block info + expect(typeof log.blockNumber).toBe('number'); + expect(log.blockNumber).toBeGreaterThan(0); + expect(log.blockHash).toMatch(/^0x[a-fA-F0-9]{64}$/); + + // Transaction info + expect(typeof log.index).toBe('number'); + expect(log.transactionHash).toMatch(/^0x[a-fA-F0-9]{64}$/); + + // Address validation + expect(log.address).toEqual(expectedContractAddress); + expect(log.address).toMatch(/^0x[a-fA-F0-9]{40}$/); + + // Topics validation + expect(Array.isArray(log.topics)).toBeTruthy(); + log.topics.forEach((topic) => { + expect(topic).toMatch(/^0x[a-fA-F0-9]{64}$/); + }); + + // Data field + expect(log.data).toMatch(/^0x([a-fA-F0-9]{2})*$/); +} diff --git a/evm-e2e/test/utils.ts b/evm-e2e/test/utils.ts index c2676c27b..a50528f91 100644 --- a/evm-e2e/test/utils.ts +++ b/evm-e2e/test/utils.ts @@ -1,52 +1,68 @@ +import { account } from './setup'; +import { parseEther, toBigInt, TransactionRequest, Wallet } from 'ethers'; import { - InfiniteLoopGasCompiled__factory, - SendNibiCompiled__factory, - TestERC20Compiled__factory, -} from "../types/ethers-contracts" -import { account } from "./setup" -import { parseEther, toBigInt, TransactionRequest, Wallet } from "ethers" + InifiniteLoopGas__factory, + SendNibi__factory, + TestERC20__factory, + EventsEmitter__factory, + TransactionReverter__factory, +} from '../types'; -export const alice = Wallet.createRandom() +export const alice = Wallet.createRandom(); export const hexify = (x: number): string => { - return "0x" + x.toString(16) -} + return '0x' + x.toString(16); +}; /** 10 to the power of 12 */ -export const TENPOW12 = toBigInt(1e12) +export const TENPOW12 = toBigInt(1e12); -export const INTRINSIC_TX_GAS: bigint = 21000n +export const INTRINSIC_TX_GAS: bigint = 21000n; export const deployContractTestERC20 = async () => { - const factory = new TestERC20Compiled__factory(account) - const contract = await factory.deploy({ maxFeePerGas: TENPOW12 }) - await contract.waitForDeployment() - return contract -} + const factory = new TestERC20__factory(account); + const contract = await factory.deploy({ maxFeePerGas: TENPOW12 }); + await contract.waitForDeployment(); + return contract; +}; export const deployContractSendNibi = async () => { - const factory = new SendNibiCompiled__factory(account) - const contract = await factory.deploy({ maxFeePerGas: TENPOW12 }) - await contract.waitForDeployment() - return contract -} + const factory = new SendNibi__factory(account); + const contract = await factory.deploy({ maxFeePerGas: TENPOW12 }); + await contract.waitForDeployment(); + return contract; +}; export const deployContractInfiniteLoopGas = async () => { - const factory = new InfiniteLoopGasCompiled__factory(account) - const contract = await factory.deploy({ maxFeePerGas: TENPOW12 }) - await contract.waitForDeployment() - return contract -} + const factory = new InifiniteLoopGas__factory(account); + const contract = await factory.deploy({ maxFeePerGas: TENPOW12 }); + await contract.waitForDeployment(); + return contract; +}; + +export const deployContractEventsEmitter = async () => { + const factory = new EventsEmitter__factory(account); + const contract = await factory.deploy(); + await contract.waitForDeployment(); + return contract; +}; + +export const deployContractTransactionReverter = async () => { + const factory = new TransactionReverter__factory(account); + const contract = await factory.deploy(); + await contract.waitForDeployment(); + return contract; +}; export const sendTestNibi = async () => { const transaction: TransactionRequest = { gasLimit: toBigInt(100e3), to: alice, - value: parseEther("0.01"), + value: parseEther('0.01'), maxFeePerGas: TENPOW12, - } - const txResponse = await account.sendTransaction(transaction) - await txResponse.wait(1, 10e3) - console.log(txResponse) - return txResponse -} + }; + const txResponse = await account.sendTransaction(transaction); + await txResponse.wait(1, 10e3); + console.log(txResponse); + return txResponse; +}; diff --git a/evm-e2e/types/ethers-contracts/InfiniteLoopGasCompiled.ts b/evm-e2e/types/ethers-contracts/InfiniteLoopGasCompiled.ts deleted file mode 100644 index e28ceee72..000000000 --- a/evm-e2e/types/ethers-contracts/InfiniteLoopGasCompiled.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import type { - BaseContract, - BytesLike, - FunctionFragment, - Result, - Interface, - ContractRunner, - ContractMethod, - Listener, -} from "ethers"; -import type { - TypedContractEvent, - TypedDeferredTopicFilter, - TypedEventLog, - TypedListener, - TypedContractMethod, -} from "./common"; - -export interface InfiniteLoopGasCompiledInterface extends Interface { - getFunction(nameOrSignature: "counter" | "forever"): FunctionFragment; - - encodeFunctionData(functionFragment: "counter", values?: undefined): string; - encodeFunctionData(functionFragment: "forever", values?: undefined): string; - - decodeFunctionResult(functionFragment: "counter", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "forever", data: BytesLike): Result; -} - -export interface InfiniteLoopGasCompiled extends BaseContract { - connect(runner?: ContractRunner | null): InfiniteLoopGasCompiled; - waitForDeployment(): Promise; - - interface: InfiniteLoopGasCompiledInterface; - - queryFilter( - event: TCEvent, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - queryFilter( - filter: TypedDeferredTopicFilter, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - - on( - event: TCEvent, - listener: TypedListener - ): Promise; - on( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - once( - event: TCEvent, - listener: TypedListener - ): Promise; - once( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - listeners( - event: TCEvent - ): Promise>>; - listeners(eventName?: string): Promise>; - removeAllListeners( - event?: TCEvent - ): Promise; - - counter: TypedContractMethod<[], [bigint], "view">; - - forever: TypedContractMethod<[], [void], "nonpayable">; - - getFunction( - key: string | FunctionFragment - ): T; - - getFunction( - nameOrSignature: "counter" - ): TypedContractMethod<[], [bigint], "view">; - getFunction( - nameOrSignature: "forever" - ): TypedContractMethod<[], [void], "nonpayable">; - - filters: {}; -} diff --git a/evm-e2e/types/ethers-contracts/ReceiveNibiCompiled.ts b/evm-e2e/types/ethers-contracts/ReceiveNibiCompiled.ts deleted file mode 100644 index 7583a12c5..000000000 --- a/evm-e2e/types/ethers-contracts/ReceiveNibiCompiled.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import type { - BaseContract, - BytesLike, - FunctionFragment, - Result, - Interface, - ContractRunner, - ContractMethod, - Listener, -} from "ethers"; -import type { - TypedContractEvent, - TypedDeferredTopicFilter, - TypedEventLog, - TypedListener, - TypedContractMethod, -} from "./common"; - -export interface ReceiveNibiCompiledInterface extends Interface { - getFunction(nameOrSignature: "getBalance"): FunctionFragment; - - encodeFunctionData( - functionFragment: "getBalance", - values?: undefined - ): string; - - decodeFunctionResult(functionFragment: "getBalance", data: BytesLike): Result; -} - -export interface ReceiveNibiCompiled extends BaseContract { - connect(runner?: ContractRunner | null): ReceiveNibiCompiled; - waitForDeployment(): Promise; - - interface: ReceiveNibiCompiledInterface; - - queryFilter( - event: TCEvent, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - queryFilter( - filter: TypedDeferredTopicFilter, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - - on( - event: TCEvent, - listener: TypedListener - ): Promise; - on( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - once( - event: TCEvent, - listener: TypedListener - ): Promise; - once( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - listeners( - event: TCEvent - ): Promise>>; - listeners(eventName?: string): Promise>; - removeAllListeners( - event?: TCEvent - ): Promise; - - getBalance: TypedContractMethod<[], [bigint], "view">; - - getFunction( - key: string | FunctionFragment - ): T; - - getFunction( - nameOrSignature: "getBalance" - ): TypedContractMethod<[], [bigint], "view">; - - filters: {}; -} diff --git a/evm-e2e/types/ethers-contracts/SendNibiCompiled.ts b/evm-e2e/types/ethers-contracts/SendNibiCompiled.ts deleted file mode 100644 index 9a5814c57..000000000 --- a/evm-e2e/types/ethers-contracts/SendNibiCompiled.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import type { - BaseContract, - BytesLike, - FunctionFragment, - Result, - Interface, - AddressLike, - ContractRunner, - ContractMethod, - Listener, -} from "ethers"; -import type { - TypedContractEvent, - TypedDeferredTopicFilter, - TypedEventLog, - TypedListener, - TypedContractMethod, -} from "./common"; - -export interface SendNibiCompiledInterface extends Interface { - getFunction( - nameOrSignature: "sendViaCall" | "sendViaSend" | "sendViaTransfer" - ): FunctionFragment; - - encodeFunctionData( - functionFragment: "sendViaCall", - values: [AddressLike] - ): string; - encodeFunctionData( - functionFragment: "sendViaSend", - values: [AddressLike] - ): string; - encodeFunctionData( - functionFragment: "sendViaTransfer", - values: [AddressLike] - ): string; - - decodeFunctionResult( - functionFragment: "sendViaCall", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "sendViaSend", - data: BytesLike - ): Result; - decodeFunctionResult( - functionFragment: "sendViaTransfer", - data: BytesLike - ): Result; -} - -export interface SendNibiCompiled extends BaseContract { - connect(runner?: ContractRunner | null): SendNibiCompiled; - waitForDeployment(): Promise; - - interface: SendNibiCompiledInterface; - - queryFilter( - event: TCEvent, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - queryFilter( - filter: TypedDeferredTopicFilter, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - - on( - event: TCEvent, - listener: TypedListener - ): Promise; - on( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - once( - event: TCEvent, - listener: TypedListener - ): Promise; - once( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - listeners( - event: TCEvent - ): Promise>>; - listeners(eventName?: string): Promise>; - removeAllListeners( - event?: TCEvent - ): Promise; - - sendViaCall: TypedContractMethod<[_to: AddressLike], [void], "payable">; - - sendViaSend: TypedContractMethod<[_to: AddressLike], [void], "payable">; - - sendViaTransfer: TypedContractMethod<[_to: AddressLike], [void], "payable">; - - getFunction( - key: string | FunctionFragment - ): T; - - getFunction( - nameOrSignature: "sendViaCall" - ): TypedContractMethod<[_to: AddressLike], [void], "payable">; - getFunction( - nameOrSignature: "sendViaSend" - ): TypedContractMethod<[_to: AddressLike], [void], "payable">; - getFunction( - nameOrSignature: "sendViaTransfer" - ): TypedContractMethod<[_to: AddressLike], [void], "payable">; - - filters: {}; -} diff --git a/evm-e2e/types/ethers-contracts/TestERC20Compiled.ts b/evm-e2e/types/ethers-contracts/TestERC20Compiled.ts deleted file mode 100644 index 2cc91e2c0..000000000 --- a/evm-e2e/types/ethers-contracts/TestERC20Compiled.ts +++ /dev/null @@ -1,286 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import type { - BaseContract, - BigNumberish, - BytesLike, - FunctionFragment, - Result, - Interface, - EventFragment, - AddressLike, - ContractRunner, - ContractMethod, - Listener, -} from "ethers"; -import type { - TypedContractEvent, - TypedDeferredTopicFilter, - TypedEventLog, - TypedLogDescription, - TypedListener, - TypedContractMethod, -} from "./common"; - -export interface TestERC20CompiledInterface extends Interface { - getFunction( - nameOrSignature: - | "allowance" - | "approve" - | "balanceOf" - | "decimals" - | "name" - | "symbol" - | "totalSupply" - | "transfer" - | "transferFrom" - ): FunctionFragment; - - getEvent(nameOrSignatureOrTopic: "Approval" | "Transfer"): EventFragment; - - encodeFunctionData( - functionFragment: "allowance", - values: [AddressLike, AddressLike] - ): string; - encodeFunctionData( - functionFragment: "approve", - values: [AddressLike, BigNumberish] - ): string; - encodeFunctionData( - functionFragment: "balanceOf", - values: [AddressLike] - ): string; - encodeFunctionData(functionFragment: "decimals", values?: undefined): string; - encodeFunctionData(functionFragment: "name", values?: undefined): string; - encodeFunctionData(functionFragment: "symbol", values?: undefined): string; - encodeFunctionData( - functionFragment: "totalSupply", - values?: undefined - ): string; - encodeFunctionData( - functionFragment: "transfer", - values: [AddressLike, BigNumberish] - ): string; - encodeFunctionData( - functionFragment: "transferFrom", - values: [AddressLike, AddressLike, BigNumberish] - ): string; - - decodeFunctionResult(functionFragment: "allowance", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "approve", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "balanceOf", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "decimals", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "name", data: BytesLike): Result; - decodeFunctionResult(functionFragment: "symbol", data: BytesLike): Result; - decodeFunctionResult( - functionFragment: "totalSupply", - data: BytesLike - ): Result; - decodeFunctionResult(functionFragment: "transfer", data: BytesLike): Result; - decodeFunctionResult( - functionFragment: "transferFrom", - data: BytesLike - ): Result; -} - -export namespace ApprovalEvent { - export type InputTuple = [ - owner: AddressLike, - spender: AddressLike, - value: BigNumberish - ]; - export type OutputTuple = [owner: string, spender: string, value: bigint]; - export interface OutputObject { - owner: string; - spender: string; - value: bigint; - } - export type Event = TypedContractEvent; - export type Filter = TypedDeferredTopicFilter; - export type Log = TypedEventLog; - export type LogDescription = TypedLogDescription; -} - -export namespace TransferEvent { - export type InputTuple = [ - from: AddressLike, - to: AddressLike, - value: BigNumberish - ]; - export type OutputTuple = [from: string, to: string, value: bigint]; - export interface OutputObject { - from: string; - to: string; - value: bigint; - } - export type Event = TypedContractEvent; - export type Filter = TypedDeferredTopicFilter; - export type Log = TypedEventLog; - export type LogDescription = TypedLogDescription; -} - -export interface TestERC20Compiled extends BaseContract { - connect(runner?: ContractRunner | null): TestERC20Compiled; - waitForDeployment(): Promise; - - interface: TestERC20CompiledInterface; - - queryFilter( - event: TCEvent, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - queryFilter( - filter: TypedDeferredTopicFilter, - fromBlockOrBlockhash?: string | number | undefined, - toBlock?: string | number | undefined - ): Promise>>; - - on( - event: TCEvent, - listener: TypedListener - ): Promise; - on( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - once( - event: TCEvent, - listener: TypedListener - ): Promise; - once( - filter: TypedDeferredTopicFilter, - listener: TypedListener - ): Promise; - - listeners( - event: TCEvent - ): Promise>>; - listeners(eventName?: string): Promise>; - removeAllListeners( - event?: TCEvent - ): Promise; - - allowance: TypedContractMethod< - [owner: AddressLike, spender: AddressLike], - [bigint], - "view" - >; - - approve: TypedContractMethod< - [spender: AddressLike, value: BigNumberish], - [boolean], - "nonpayable" - >; - - balanceOf: TypedContractMethod<[account: AddressLike], [bigint], "view">; - - decimals: TypedContractMethod<[], [bigint], "view">; - - name: TypedContractMethod<[], [string], "view">; - - symbol: TypedContractMethod<[], [string], "view">; - - totalSupply: TypedContractMethod<[], [bigint], "view">; - - transfer: TypedContractMethod< - [to: AddressLike, value: BigNumberish], - [boolean], - "nonpayable" - >; - - transferFrom: TypedContractMethod< - [from: AddressLike, to: AddressLike, value: BigNumberish], - [boolean], - "nonpayable" - >; - - getFunction( - key: string | FunctionFragment - ): T; - - getFunction( - nameOrSignature: "allowance" - ): TypedContractMethod< - [owner: AddressLike, spender: AddressLike], - [bigint], - "view" - >; - getFunction( - nameOrSignature: "approve" - ): TypedContractMethod< - [spender: AddressLike, value: BigNumberish], - [boolean], - "nonpayable" - >; - getFunction( - nameOrSignature: "balanceOf" - ): TypedContractMethod<[account: AddressLike], [bigint], "view">; - getFunction( - nameOrSignature: "decimals" - ): TypedContractMethod<[], [bigint], "view">; - getFunction( - nameOrSignature: "name" - ): TypedContractMethod<[], [string], "view">; - getFunction( - nameOrSignature: "symbol" - ): TypedContractMethod<[], [string], "view">; - getFunction( - nameOrSignature: "totalSupply" - ): TypedContractMethod<[], [bigint], "view">; - getFunction( - nameOrSignature: "transfer" - ): TypedContractMethod< - [to: AddressLike, value: BigNumberish], - [boolean], - "nonpayable" - >; - getFunction( - nameOrSignature: "transferFrom" - ): TypedContractMethod< - [from: AddressLike, to: AddressLike, value: BigNumberish], - [boolean], - "nonpayable" - >; - - getEvent( - key: "Approval" - ): TypedContractEvent< - ApprovalEvent.InputTuple, - ApprovalEvent.OutputTuple, - ApprovalEvent.OutputObject - >; - getEvent( - key: "Transfer" - ): TypedContractEvent< - TransferEvent.InputTuple, - TransferEvent.OutputTuple, - TransferEvent.OutputObject - >; - - filters: { - "Approval(address,address,uint256)": TypedContractEvent< - ApprovalEvent.InputTuple, - ApprovalEvent.OutputTuple, - ApprovalEvent.OutputObject - >; - Approval: TypedContractEvent< - ApprovalEvent.InputTuple, - ApprovalEvent.OutputTuple, - ApprovalEvent.OutputObject - >; - - "Transfer(address,address,uint256)": TypedContractEvent< - TransferEvent.InputTuple, - TransferEvent.OutputTuple, - TransferEvent.OutputObject - >; - Transfer: TypedContractEvent< - TransferEvent.InputTuple, - TransferEvent.OutputTuple, - TransferEvent.OutputObject - >; - }; -} diff --git a/evm-e2e/types/ethers-contracts/common.ts b/evm-e2e/types/ethers-contracts/common.ts deleted file mode 100644 index 56b5f21e9..000000000 --- a/evm-e2e/types/ethers-contracts/common.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import type { - FunctionFragment, - Typed, - EventFragment, - ContractTransaction, - ContractTransactionResponse, - DeferredTopicFilter, - EventLog, - TransactionRequest, - LogDescription, -} from "ethers"; - -export interface TypedDeferredTopicFilter<_TCEvent extends TypedContractEvent> - extends DeferredTopicFilter {} - -export interface TypedContractEvent< - InputTuple extends Array = any, - OutputTuple extends Array = any, - OutputObject = any -> { - (...args: Partial): TypedDeferredTopicFilter< - TypedContractEvent - >; - name: string; - fragment: EventFragment; - getFragment(...args: Partial): EventFragment; -} - -type __TypechainAOutputTuple = T extends TypedContractEvent< - infer _U, - infer W -> - ? W - : never; -type __TypechainOutputObject = T extends TypedContractEvent< - infer _U, - infer _W, - infer V -> - ? V - : never; - -export interface TypedEventLog - extends Omit { - args: __TypechainAOutputTuple & __TypechainOutputObject; -} - -export interface TypedLogDescription - extends Omit { - args: __TypechainAOutputTuple & __TypechainOutputObject; -} - -export type TypedListener = ( - ...listenerArg: [ - ...__TypechainAOutputTuple, - TypedEventLog, - ...undefined[] - ] -) => void; - -export type MinEthersFactory = { - deploy(...a: ARGS[]): Promise; -}; - -export type GetContractTypeFromFactory = F extends MinEthersFactory< - infer C, - any -> - ? C - : never; -export type GetARGsTypeFromFactory = F extends MinEthersFactory - ? Parameters - : never; - -export type StateMutability = "nonpayable" | "payable" | "view"; - -export type BaseOverrides = Omit; -export type NonPayableOverrides = Omit< - BaseOverrides, - "value" | "blockTag" | "enableCcipRead" ->; -export type PayableOverrides = Omit< - BaseOverrides, - "blockTag" | "enableCcipRead" ->; -export type ViewOverrides = Omit; -export type Overrides = S extends "nonpayable" - ? NonPayableOverrides - : S extends "payable" - ? PayableOverrides - : ViewOverrides; - -export type PostfixOverrides, S extends StateMutability> = - | A - | [...A, Overrides]; -export type ContractMethodArgs< - A extends Array, - S extends StateMutability -> = PostfixOverrides<{ [I in keyof A]-?: A[I] | Typed }, S>; - -export type DefaultReturnType = R extends Array ? R[0] : R; - -// export interface ContractMethod = Array, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> { -export interface TypedContractMethod< - A extends Array = Array, - R = any, - S extends StateMutability = "payable" -> { - (...args: ContractMethodArgs): S extends "view" - ? Promise> - : Promise; - - name: string; - - fragment: FunctionFragment; - - getFragment(...args: ContractMethodArgs): FunctionFragment; - - populateTransaction( - ...args: ContractMethodArgs - ): Promise; - staticCall( - ...args: ContractMethodArgs - ): Promise>; - send(...args: ContractMethodArgs): Promise; - estimateGas(...args: ContractMethodArgs): Promise; - staticCallResult(...args: ContractMethodArgs): Promise; -} diff --git a/evm-e2e/types/ethers-contracts/factories/InfiniteLoopGasCompiled__factory.ts b/evm-e2e/types/ethers-contracts/factories/InfiniteLoopGasCompiled__factory.ts deleted file mode 100644 index f5f1e13b7..000000000 --- a/evm-e2e/types/ethers-contracts/factories/InfiniteLoopGasCompiled__factory.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import { - Contract, - ContractFactory, - ContractTransactionResponse, - Interface, -} from "ethers"; -import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers"; -import type { NonPayableOverrides } from "../common"; -import type { - InfiniteLoopGasCompiled, - InfiniteLoopGasCompiledInterface, -} from "../InfiniteLoopGasCompiled"; - -const _abi = [ - { - inputs: [], - name: "counter", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "forever", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, -] as const; - -const _bytecode = - "0x60806040526000805534801561001457600080fd5b5061015e806100246000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806361bc221a1461003b5780639ff9a60314610059575b600080fd5b610043610063565b60405161005091906100aa565b60405180910390f35b610061610069565b005b60005481565b5b60011561008f57600160008082825461008391906100f4565b9250508190555061006a565b565b6000819050919050565b6100a481610091565b82525050565b60006020820190506100bf600083018461009b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100ff82610091565b915061010a83610091565b9250828201905080821115610122576101216100c5565b5b9291505056fea2646970667358221220946d430ff7d8c16c5401d4156ff1b5d75c112460fbba0fb343581bd3c86cfe1c64736f6c63430008180033"; - -type InfiniteLoopGasCompiledConstructorParams = - | [signer?: Signer] - | ConstructorParameters; - -const isSuperArgs = ( - xs: InfiniteLoopGasCompiledConstructorParams -): xs is ConstructorParameters => xs.length > 1; - -export class InfiniteLoopGasCompiled__factory extends ContractFactory { - constructor(...args: InfiniteLoopGasCompiledConstructorParams) { - if (isSuperArgs(args)) { - super(...args); - } else { - super(_abi, _bytecode, args[0]); - } - } - - override getDeployTransaction( - overrides?: NonPayableOverrides & { from?: string } - ): Promise { - return super.getDeployTransaction(overrides || {}); - } - override deploy(overrides?: NonPayableOverrides & { from?: string }) { - return super.deploy(overrides || {}) as Promise< - InfiniteLoopGasCompiled & { - deploymentTransaction(): ContractTransactionResponse; - } - >; - } - override connect( - runner: ContractRunner | null - ): InfiniteLoopGasCompiled__factory { - return super.connect(runner) as InfiniteLoopGasCompiled__factory; - } - - static readonly bytecode = _bytecode; - static readonly abi = _abi; - static createInterface(): InfiniteLoopGasCompiledInterface { - return new Interface(_abi) as InfiniteLoopGasCompiledInterface; - } - static connect( - address: string, - runner?: ContractRunner | null - ): InfiniteLoopGasCompiled { - return new Contract( - address, - _abi, - runner - ) as unknown as InfiniteLoopGasCompiled; - } -} diff --git a/evm-e2e/types/ethers-contracts/factories/ReceiveNibiCompiled__factory.ts b/evm-e2e/types/ethers-contracts/factories/ReceiveNibiCompiled__factory.ts deleted file mode 100644 index ae1a161f0..000000000 --- a/evm-e2e/types/ethers-contracts/factories/ReceiveNibiCompiled__factory.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import { - Contract, - ContractFactory, - ContractTransactionResponse, - Interface, -} from "ethers"; -import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers"; -import type { NonPayableOverrides } from "../common"; -import type { - ReceiveNibiCompiled, - ReceiveNibiCompiledInterface, -} from "../ReceiveNibiCompiled"; - -const _abi = [ - { - stateMutability: "payable", - type: "fallback", - }, - { - inputs: [], - name: "getBalance", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - stateMutability: "payable", - type: "receive", - }, -] as const; - -const _bytecode = - "0x608060405234801561001057600080fd5b5060bb8061001f6000396000f3fe608060405260043610601f5760003560e01c806312065fe0146027576025565b36602557005b005b348015603257600080fd5b506039604d565b60405160449190606c565b60405180910390f35b600047905090565b6000819050919050565b6066816055565b82525050565b6000602082019050607f6000830184605f565b9291505056fea2646970667358221220f4ee193ceac7d6ffbf8d62d675a1d21fed9c154b8e9407c7aba0f7301ef0db6b64736f6c63430008180033"; - -type ReceiveNibiCompiledConstructorParams = - | [signer?: Signer] - | ConstructorParameters; - -const isSuperArgs = ( - xs: ReceiveNibiCompiledConstructorParams -): xs is ConstructorParameters => xs.length > 1; - -export class ReceiveNibiCompiled__factory extends ContractFactory { - constructor(...args: ReceiveNibiCompiledConstructorParams) { - if (isSuperArgs(args)) { - super(...args); - } else { - super(_abi, _bytecode, args[0]); - } - } - - override getDeployTransaction( - overrides?: NonPayableOverrides & { from?: string } - ): Promise { - return super.getDeployTransaction(overrides || {}); - } - override deploy(overrides?: NonPayableOverrides & { from?: string }) { - return super.deploy(overrides || {}) as Promise< - ReceiveNibiCompiled & { - deploymentTransaction(): ContractTransactionResponse; - } - >; - } - override connect( - runner: ContractRunner | null - ): ReceiveNibiCompiled__factory { - return super.connect(runner) as ReceiveNibiCompiled__factory; - } - - static readonly bytecode = _bytecode; - static readonly abi = _abi; - static createInterface(): ReceiveNibiCompiledInterface { - return new Interface(_abi) as ReceiveNibiCompiledInterface; - } - static connect( - address: string, - runner?: ContractRunner | null - ): ReceiveNibiCompiled { - return new Contract( - address, - _abi, - runner - ) as unknown as ReceiveNibiCompiled; - } -} diff --git a/evm-e2e/types/ethers-contracts/factories/SendNibiCompiled__factory.ts b/evm-e2e/types/ethers-contracts/factories/SendNibiCompiled__factory.ts deleted file mode 100644 index 403cf7010..000000000 --- a/evm-e2e/types/ethers-contracts/factories/SendNibiCompiled__factory.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import { - Contract, - ContractFactory, - ContractTransactionResponse, - Interface, -} from "ethers"; -import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers"; -import type { NonPayableOverrides } from "../common"; -import type { - SendNibiCompiled, - SendNibiCompiledInterface, -} from "../SendNibiCompiled"; - -const _abi = [ - { - inputs: [ - { - internalType: "address payable", - name: "_to", - type: "address", - }, - ], - name: "sendViaCall", - outputs: [], - stateMutability: "payable", - type: "function", - }, - { - inputs: [ - { - internalType: "address payable", - name: "_to", - type: "address", - }, - ], - name: "sendViaSend", - outputs: [], - stateMutability: "payable", - type: "function", - }, - { - inputs: [ - { - internalType: "address payable", - name: "_to", - type: "address", - }, - ], - name: "sendViaTransfer", - outputs: [], - stateMutability: "payable", - type: "function", - }, -] as const; - -const _bytecode = - "0x608060405234801561001057600080fd5b50610390806100206000396000f3fe6080604052600436106100345760003560e01c8063636e082b1461003957806374be480614610055578063830c29ae14610071575b600080fd5b610053600480360381019061004e919061026a565b61008d565b005b61006f600480360381019061006a919061026a565b6100d7565b005b61008b6004803603810190610086919061026a565b610154565b005b8073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156100d3573d6000803e3d6000fd5b5050565b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050905080610150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610147906102f4565b60405180910390fd5b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163460405161017b90610345565b60006040518083038185875af1925050503d80600081146101b8576040519150601f19603f3d011682016040523d82523d6000602084013e6101bd565b606091505b509150915081610202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f9906102f4565b60405180910390fd5b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102378261020c565b9050919050565b6102478161022c565b811461025257600080fd5b50565b6000813590506102648161023e565b92915050565b6000602082840312156102805761027f610207565b5b600061028e84828501610255565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204e69626900000000000000000000000000600082015250565b60006102de601383610297565b91506102e9826102a8565b602082019050919050565b6000602082019050818103600083015261030d816102d1565b9050919050565b600081905092915050565b50565b600061032f600083610314565b915061033a8261031f565b600082019050919050565b600061035082610322565b915081905091905056fea26469706673582212201fcd9f47953315963ca2a2687073914cbb3f29161100cec83979926b96714b2b64736f6c63430008180033"; - -type SendNibiCompiledConstructorParams = - | [signer?: Signer] - | ConstructorParameters; - -const isSuperArgs = ( - xs: SendNibiCompiledConstructorParams -): xs is ConstructorParameters => xs.length > 1; - -export class SendNibiCompiled__factory extends ContractFactory { - constructor(...args: SendNibiCompiledConstructorParams) { - if (isSuperArgs(args)) { - super(...args); - } else { - super(_abi, _bytecode, args[0]); - } - } - - override getDeployTransaction( - overrides?: NonPayableOverrides & { from?: string } - ): Promise { - return super.getDeployTransaction(overrides || {}); - } - override deploy(overrides?: NonPayableOverrides & { from?: string }) { - return super.deploy(overrides || {}) as Promise< - SendNibiCompiled & { - deploymentTransaction(): ContractTransactionResponse; - } - >; - } - override connect(runner: ContractRunner | null): SendNibiCompiled__factory { - return super.connect(runner) as SendNibiCompiled__factory; - } - - static readonly bytecode = _bytecode; - static readonly abi = _abi; - static createInterface(): SendNibiCompiledInterface { - return new Interface(_abi) as SendNibiCompiledInterface; - } - static connect( - address: string, - runner?: ContractRunner | null - ): SendNibiCompiled { - return new Contract(address, _abi, runner) as unknown as SendNibiCompiled; - } -} diff --git a/evm-e2e/types/ethers-contracts/factories/TestERC20Compiled__factory.ts b/evm-e2e/types/ethers-contracts/factories/TestERC20Compiled__factory.ts deleted file mode 100644 index c7fac001e..000000000 --- a/evm-e2e/types/ethers-contracts/factories/TestERC20Compiled__factory.ts +++ /dev/null @@ -1,380 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -import { - Contract, - ContractFactory, - ContractTransactionResponse, - Interface, -} from "ethers"; -import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers"; -import type { NonPayableOverrides } from "../common"; -import type { - TestERC20Compiled, - TestERC20CompiledInterface, -} from "../TestERC20Compiled"; - -const _abi = [ - { - inputs: [], - stateMutability: "nonpayable", - type: "constructor", - }, - { - inputs: [ - { - internalType: "address", - name: "spender", - type: "address", - }, - { - internalType: "uint256", - name: "allowance", - type: "uint256", - }, - { - internalType: "uint256", - name: "needed", - type: "uint256", - }, - ], - name: "ERC20InsufficientAllowance", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address", - }, - { - internalType: "uint256", - name: "balance", - type: "uint256", - }, - { - internalType: "uint256", - name: "needed", - type: "uint256", - }, - ], - name: "ERC20InsufficientBalance", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "approver", - type: "address", - }, - ], - name: "ERC20InvalidApprover", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "receiver", - type: "address", - }, - ], - name: "ERC20InvalidReceiver", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "sender", - type: "address", - }, - ], - name: "ERC20InvalidSender", - type: "error", - }, - { - inputs: [ - { - internalType: "address", - name: "spender", - type: "address", - }, - ], - name: "ERC20InvalidSpender", - type: "error", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "owner", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "spender", - type: "address", - }, - { - indexed: false, - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "Approval", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "from", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "to", - type: "address", - }, - { - indexed: false, - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "Transfer", - type: "event", - }, - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address", - }, - { - internalType: "address", - name: "spender", - type: "address", - }, - ], - name: "allowance", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "spender", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "approve", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "account", - type: "address", - }, - ], - name: "balanceOf", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "decimals", - outputs: [ - { - internalType: "uint8", - name: "", - type: "uint8", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "name", - outputs: [ - { - internalType: "string", - name: "", - type: "string", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "symbol", - outputs: [ - { - internalType: "string", - name: "", - type: "string", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "totalSupply", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "to", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "transfer", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "from", - type: "address", - }, - { - internalType: "address", - name: "to", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - ], - name: "transferFrom", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, -] as const; - -const _bytecode = - "0x60806040523480156200001157600080fd5b506040518060400160405280600881526020017f46756e546f6b656e0000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f46554e000000000000000000000000000000000000000000000000000000000081525081600390816200008f9190620005fd565b508060049081620000a19190620005fd565b505050620000c03369d3c21bcecceda1000000620000c660201b60201c565b6200081b565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036200013b5760006040517fec442f0500000000000000000000000000000000000000000000000000000000815260040162000132919062000729565b60405180910390fd5b6200014f600083836200015360201b60201c565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603620001a95780600260008282546200019c919062000775565b925050819055506200027f565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101562000238578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016200022f93929190620007c1565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603620002ca578060026000828254039250508190555062000317565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620003769190620007fe565b60405180910390a3505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200040557607f821691505b6020821081036200041b576200041a620003bd565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000446565b62000491868362000446565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620004de620004d8620004d284620004a9565b620004b3565b620004a9565b9050919050565b6000819050919050565b620004fa83620004bd565b620005126200050982620004e5565b84845462000453565b825550505050565b600090565b620005296200051a565b62000536818484620004ef565b505050565b5b818110156200055e57620005526000826200051f565b6001810190506200053c565b5050565b601f821115620005ad57620005778162000421565b620005828462000436565b8101602085101562000592578190505b620005aa620005a18562000436565b8301826200053b565b50505b505050565b600082821c905092915050565b6000620005d260001984600802620005b2565b1980831691505092915050565b6000620005ed8383620005bf565b9150826002028217905092915050565b620006088262000383565b67ffffffffffffffff8111156200062457620006236200038e565b5b620006308254620003ec565b6200063d82828562000562565b600060209050601f83116001811462000675576000841562000660578287015190505b6200066c8582620005df565b865550620006dc565b601f198416620006858662000421565b60005b82811015620006af5784890151825560018201915060208501945060208101905062000688565b86831015620006cf5784890151620006cb601f891682620005bf565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200071182620006e4565b9050919050565b620007238162000704565b82525050565b600060208201905062000740600083018462000718565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200078282620004a9565b91506200078f83620004a9565b9250828201905080821115620007aa57620007a962000746565b5b92915050565b620007bb81620004a9565b82525050565b6000606082019050620007d8600083018662000718565b620007e76020830185620007b0565b620007f66040830184620007b0565b949350505050565b6000602082019050620008156000830184620007b0565b92915050565b610e55806200082b6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063313ce56711610066578063313ce5671461013457806370a082311461015257806395d89b4114610182578063a9059cbb146101a0578063dd62ed3e146101d057610093565b806306fdde0314610098578063095ea7b3146100b657806318160ddd146100e657806323b872dd14610104575b600080fd5b6100a0610200565b6040516100ad9190610aa9565b60405180910390f35b6100d060048036038101906100cb9190610b64565b610292565b6040516100dd9190610bbf565b60405180910390f35b6100ee6102b5565b6040516100fb9190610be9565b60405180910390f35b61011e60048036038101906101199190610c04565b6102bf565b60405161012b9190610bbf565b60405180910390f35b61013c6102ee565b6040516101499190610c73565b60405180910390f35b61016c60048036038101906101679190610c8e565b6102f7565b6040516101799190610be9565b60405180910390f35b61018a61033f565b6040516101979190610aa9565b60405180910390f35b6101ba60048036038101906101b59190610b64565b6103d1565b6040516101c79190610bbf565b60405180910390f35b6101ea60048036038101906101e59190610cbb565b6103f4565b6040516101f79190610be9565b60405180910390f35b60606003805461020f90610d2a565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610d2a565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b60008061029d61047b565b90506102aa818585610483565b600191505092915050565b6000600254905090565b6000806102ca61047b565b90506102d7858285610495565b6102e2858585610529565b60019150509392505050565b60006012905090565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60606004805461034e90610d2a565b80601f016020809104026020016040519081016040528092919081815260200182805461037a90610d2a565b80156103c75780601f1061039c576101008083540402835291602001916103c7565b820191906000526020600020905b8154815290600101906020018083116103aa57829003601f168201915b5050505050905090565b6000806103dc61047b565b90506103e9818585610529565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b610490838383600161061d565b505050565b60006104a184846103f4565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105235781811015610513578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161050a93929190610d6a565b60405180910390fd5b6105228484848403600061061d565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361059b5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105929190610da1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361060d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106049190610da1565b60405180910390fd5b6106188383836107f4565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361068f5760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016106869190610da1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107015760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016106f89190610da1565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080156107ee578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516107e59190610be9565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361084657806002600082825461083a9190610deb565b92505081905550610919565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050818110156108d2578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016108c993929190610d6a565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361096257806002600082825403925050819055506109af565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610a0c9190610be9565b60405180910390a3505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610a53578082015181840152602081019050610a38565b60008484015250505050565b6000601f19601f8301169050919050565b6000610a7b82610a19565b610a858185610a24565b9350610a95818560208601610a35565b610a9e81610a5f565b840191505092915050565b60006020820190508181036000830152610ac38184610a70565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610afb82610ad0565b9050919050565b610b0b81610af0565b8114610b1657600080fd5b50565b600081359050610b2881610b02565b92915050565b6000819050919050565b610b4181610b2e565b8114610b4c57600080fd5b50565b600081359050610b5e81610b38565b92915050565b60008060408385031215610b7b57610b7a610acb565b5b6000610b8985828601610b19565b9250506020610b9a85828601610b4f565b9150509250929050565b60008115159050919050565b610bb981610ba4565b82525050565b6000602082019050610bd46000830184610bb0565b92915050565b610be381610b2e565b82525050565b6000602082019050610bfe6000830184610bda565b92915050565b600080600060608486031215610c1d57610c1c610acb565b5b6000610c2b86828701610b19565b9350506020610c3c86828701610b19565b9250506040610c4d86828701610b4f565b9150509250925092565b600060ff82169050919050565b610c6d81610c57565b82525050565b6000602082019050610c886000830184610c64565b92915050565b600060208284031215610ca457610ca3610acb565b5b6000610cb284828501610b19565b91505092915050565b60008060408385031215610cd257610cd1610acb565b5b6000610ce085828601610b19565b9250506020610cf185828601610b19565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610d4257607f821691505b602082108103610d5557610d54610cfb565b5b50919050565b610d6481610af0565b82525050565b6000606082019050610d7f6000830186610d5b565b610d8c6020830185610bda565b610d996040830184610bda565b949350505050565b6000602082019050610db66000830184610d5b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610df682610b2e565b9150610e0183610b2e565b9250828201905080821115610e1957610e18610dbc565b5b9291505056fea26469706673582212200260074039b179ca88933aa33752c910c15aa2062c21e8c76d09940bd406048b64736f6c63430008180033"; - -type TestERC20CompiledConstructorParams = - | [signer?: Signer] - | ConstructorParameters; - -const isSuperArgs = ( - xs: TestERC20CompiledConstructorParams -): xs is ConstructorParameters => xs.length > 1; - -export class TestERC20Compiled__factory extends ContractFactory { - constructor(...args: TestERC20CompiledConstructorParams) { - if (isSuperArgs(args)) { - super(...args); - } else { - super(_abi, _bytecode, args[0]); - } - } - - override getDeployTransaction( - overrides?: NonPayableOverrides & { from?: string } - ): Promise { - return super.getDeployTransaction(overrides || {}); - } - override deploy(overrides?: NonPayableOverrides & { from?: string }) { - return super.deploy(overrides || {}) as Promise< - TestERC20Compiled & { - deploymentTransaction(): ContractTransactionResponse; - } - >; - } - override connect(runner: ContractRunner | null): TestERC20Compiled__factory { - return super.connect(runner) as TestERC20Compiled__factory; - } - - static readonly bytecode = _bytecode; - static readonly abi = _abi; - static createInterface(): TestERC20CompiledInterface { - return new Interface(_abi) as TestERC20CompiledInterface; - } - static connect( - address: string, - runner?: ContractRunner | null - ): TestERC20Compiled { - return new Contract(address, _abi, runner) as unknown as TestERC20Compiled; - } -} diff --git a/evm-e2e/types/ethers-contracts/factories/index.ts b/evm-e2e/types/ethers-contracts/factories/index.ts deleted file mode 100644 index f45fe35ae..000000000 --- a/evm-e2e/types/ethers-contracts/factories/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -export { InfiniteLoopGasCompiled__factory } from "./InfiniteLoopGasCompiled__factory"; -export { ReceiveNibiCompiled__factory } from "./ReceiveNibiCompiled__factory"; -export { SendNibiCompiled__factory } from "./SendNibiCompiled__factory"; -export { TestERC20Compiled__factory } from "./TestERC20Compiled__factory"; diff --git a/evm-e2e/types/ethers-contracts/index.ts b/evm-e2e/types/ethers-contracts/index.ts deleted file mode 100644 index 567e7e58c..000000000 --- a/evm-e2e/types/ethers-contracts/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* Autogenerated file. Do not edit manually. */ -/* tslint:disable */ -/* eslint-disable */ -export type { InfiniteLoopGasCompiled } from "./InfiniteLoopGasCompiled"; -export type { ReceiveNibiCompiled } from "./ReceiveNibiCompiled"; -export type { SendNibiCompiled } from "./SendNibiCompiled"; -export type { TestERC20Compiled } from "./TestERC20Compiled"; -export * as factories from "./factories"; -export { InfiniteLoopGasCompiled__factory } from "./factories/InfiniteLoopGasCompiled__factory"; -export { ReceiveNibiCompiled__factory } from "./factories/ReceiveNibiCompiled__factory"; -export { SendNibiCompiled__factory } from "./factories/SendNibiCompiled__factory"; -export { TestERC20Compiled__factory } from "./factories/TestERC20Compiled__factory"; From ee5e29fc403616aa4e0019864858960d66cb8ab8 Mon Sep 17 00:00:00 2001 From: Helder Moreira Date: Thu, 31 Oct 2024 18:45:21 +0000 Subject: [PATCH 07/12] feat: enable wasm light clients on IBC (08-wasm) (#2068) * feat: enable wasm light clients on IBC (08-wasm) * chore: check if wasm client is already on params * chore(changelog): move to before evm audit --------- Co-authored-by: Kevin Yang <5478483+k-yang@users.noreply.github.com> --- CHANGELOG.md | 1 + app/app.go | 14 +++++++++++ app/keepers.go | 34 +++++++++++++++++++++++--- app/keepers/all_keepers.go | 2 ++ app/upgrades.go | 4 ++- app/upgrades/types.go | 4 ++- app/upgrades/v1_1_0/constants.go | 3 ++- app/upgrades/v1_2_0/constants.go | 3 ++- app/upgrades/v1_3_0/constants.go | 3 ++- app/upgrades/v1_4_0/constants.go | 3 ++- app/upgrades/v2_1_0/constants.go | 42 ++++++++++++++++++++++++++++++++ cmd/nibid/cmd/init.go | 9 +++++++ go.mod | 3 ++- go.sum | 6 +++-- 14 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 app/upgrades/v2_1_0/constants.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 46f412d48..dade1db65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ for (1) ERC20 transfers with tokens that return false success values instead of throwing an error and (2) ERC20 transfers with other operations that don't bring about the expected resulting balance for the transfer recipient. - [#2092](https://github.com/NibiruChain/nibiru/pull/2092) - feat(evm): add validation for wasm multi message execution +- [#2068](https://github.com/NibiruChain/nibiru/pull/2068) - feat: enable wasm light clients on IBC (08-wasm) - [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/app/app.go b/app/app.go index 9230a3553..2bc2618de 100644 --- a/app/app.go +++ b/app/app.go @@ -10,6 +10,9 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + cmtos "github.com/cometbft/cometbft/libs/os" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" "github.com/NibiruChain/nibiru/v2/app/ante" "github.com/NibiruChain/nibiru/v2/app/wasmext" @@ -240,6 +243,10 @@ func NewNibiruApp( app.CommitMultiStore(), &app.WasmKeeper, ), + ibcwasmkeeper.NewWasmSnapshotter( + app.CommitMultiStore(), + &app.WasmClientKeeper, + ), ); err != nil { panic("failed to add wasm snapshot extension.") } @@ -250,6 +257,13 @@ func NewNibiruApp( tmos.Exit(err.Error()) } + ctx := app.BaseApp.NewUncachedContext(true, cmtproto.Header{}) + + // Initialize pinned codes in wasmvm as they are not persisted there + if err := ibcwasmkeeper.InitializePinnedCodes(ctx, app.appCodec); err != nil { + cmtos.Exit(fmt.Sprintf("failed to initialize pinned codes %s", err)) + } + /* Applications that wish to enforce statically created ScopedKeepers should call `Seal` after creating their scoped modules in `NewApp` with `capabilityKeeper.ScopeToModule`. diff --git a/app/keepers.go b/app/keepers.go index 4c5721e83..156ef6413 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -4,6 +4,8 @@ import ( "path/filepath" "strings" + ibcwasm "github.com/cosmos/ibc-go/modules/light-clients/08-wasm" + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" ica "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts" icacontroller "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller" icacontrollerkeeper "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/keeper" @@ -16,6 +18,7 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvm "github.com/CosmWasm/wasmvm" _ "github.com/cosmos/cosmos-sdk/client/docs/statik" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" @@ -84,6 +87,7 @@ import ( // --------------------------------------------------------------- // IBC imports + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" icahostkeeper "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/keeper" ibcfee "github.com/cosmos/ibc-go/v7/modules/apps/29-fee" ibcfeekeeper "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/keeper" @@ -121,7 +125,7 @@ import ( "github.com/NibiruChain/nibiru/v2/x/inflation" inflationkeeper "github.com/NibiruChain/nibiru/v2/x/inflation/keeper" inflationtypes "github.com/NibiruChain/nibiru/v2/x/inflation/types" - oracle "github.com/NibiruChain/nibiru/v2/x/oracle" + "github.com/NibiruChain/nibiru/v2/x/oracle" oraclekeeper "github.com/NibiruChain/nibiru/v2/x/oracle/keeper" oracletypes "github.com/NibiruChain/nibiru/v2/x/oracle/types" @@ -129,11 +133,13 @@ import ( "github.com/NibiruChain/nibiru/v2/x/sudo/keeper" sudotypes "github.com/NibiruChain/nibiru/v2/x/sudo/types" - tokenfactory "github.com/NibiruChain/nibiru/v2/x/tokenfactory" + "github.com/NibiruChain/nibiru/v2/x/tokenfactory" tokenfactorykeeper "github.com/NibiruChain/nibiru/v2/x/tokenfactory/keeper" tokenfactorytypes "github.com/NibiruChain/nibiru/v2/x/tokenfactory/types" ) +const wasmVmContractMemoryLimit = 32 + type AppKeepers struct { keepers.PublicKeepers privateKeepers @@ -193,6 +199,7 @@ func initStoreKeys() ( ibcexported.StoreKey, icahosttypes.StoreKey, icacontrollertypes.StoreKey, + ibcwasmtypes.StoreKey, // nibiru x/ keys oracletypes.StoreKey, @@ -253,7 +260,7 @@ func (app *NibiruApp) InitKeepers( // seal capability keeper after scoping modules // app.capabilityKeeper.Seal() - // TODO: chore(upgrade): Potential breaking change on AccountKeeper dur + // TODO: chore(upgrade): Potential breaking change on AccountKeeper due // to ProtoBaseAccount replacement. app.AccountKeeper = authkeeper.NewAccountKeeper( appCodec, @@ -450,6 +457,13 @@ func (app *NibiruApp) InitKeepers( // For example, if there are bindings for the x/inflation module, then the app // passed to GetWasmOpts must already have a non-nil InflationKeeper. supportedFeatures := strings.Join(wasmdapp.AllCapabilities(), ",") + + // Create wasm VM outside keeper so it can be re-used in client keeper + wasmVM, err := wasmvm.NewVM(filepath.Join(wasmDir, "wasm"), supportedFeatures, wasmVmContractMemoryLimit, wasmConfig.ContractDebugMode, wasmConfig.MemoryCacheSize) + if err != nil { + panic(err) + } + app.WasmKeeper = wasmkeeper.NewKeeper( appCodec, keys[wasmtypes.StoreKey], @@ -468,7 +482,16 @@ func (app *NibiruApp) InitKeepers( wasmConfig, supportedFeatures, govModuleAddr, - GetWasmOpts(*app, appOpts)..., + append(GetWasmOpts(*app, appOpts), wasmkeeper.WithWasmEngine(wasmVM))..., + ) + + app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithVM( + appCodec, + keys[ibcwasmtypes.StoreKey], + app.ibcKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmVM, + app.GRPCQueryRouter(), ) // DevGas uses WasmKeeper @@ -632,6 +655,7 @@ func (app *NibiruApp) initAppModules( ibctransfer.NewAppModule(app.ibcTransferKeeper), ibcfee.NewAppModule(app.ibcFeeKeeper), ica.NewAppModule(&app.icaControllerKeeper, &app.icaHostKeeper), + ibcwasm.NewAppModule(app.WasmClientKeeper), evmmodule.NewAppModule(&app.EvmKeeper, app.AccountKeeper), @@ -703,6 +727,7 @@ func orderedModuleNames() []string { ibcexported.ModuleName, ibcfeetypes.ModuleName, icatypes.ModuleName, + ibcwasmtypes.ModuleName, // -------------------------------------------------------------------- evm.ModuleName, @@ -809,6 +834,7 @@ func ModuleBasicManager() module.BasicManager { ibctransfer.AppModuleBasic{}, ibctm.AppModuleBasic{}, ica.AppModuleBasic{}, + ibcwasm.AppModuleBasic{}, // native x/ evmmodule.AppModuleBasic{}, oracle.AppModuleBasic{}, diff --git a/app/keepers/all_keepers.go b/app/keepers/all_keepers.go index 7bbdc9c10..25303860f 100644 --- a/app/keepers/all_keepers.go +++ b/app/keepers/all_keepers.go @@ -10,6 +10,7 @@ import ( distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -68,4 +69,5 @@ type PublicKeepers struct { // WASM keepers WasmKeeper wasmkeeper.Keeper ScopedWasmKeeper capabilitykeeper.ScopedKeeper + WasmClientKeeper ibcwasmkeeper.Keeper } diff --git a/app/upgrades.go b/app/upgrades.go index 3f9851fd4..6c547c390 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -10,6 +10,7 @@ import ( "github.com/NibiruChain/nibiru/v2/app/upgrades/v1_2_0" "github.com/NibiruChain/nibiru/v2/app/upgrades/v1_3_0" "github.com/NibiruChain/nibiru/v2/app/upgrades/v1_4_0" + "github.com/NibiruChain/nibiru/v2/app/upgrades/v2_1_0" ) var Upgrades = []upgrades.Upgrade{ @@ -17,6 +18,7 @@ var Upgrades = []upgrades.Upgrade{ v1_2_0.Upgrade, v1_3_0.Upgrade, v1_4_0.Upgrade, + v2_1_0.Upgrade, } func (app *NibiruApp) setupUpgrades() { @@ -26,7 +28,7 @@ func (app *NibiruApp) setupUpgrades() { func (app *NibiruApp) setUpgradeHandlers() { for _, u := range Upgrades { - app.upgradeKeeper.SetUpgradeHandler(u.UpgradeName, u.CreateUpgradeHandler(app.ModuleManager, app.configurator)) + app.upgradeKeeper.SetUpgradeHandler(u.UpgradeName, u.CreateUpgradeHandler(app.ModuleManager, app.configurator, app.ibcKeeper.ClientKeeper)) } } diff --git a/app/upgrades/types.go b/app/upgrades/types.go index a2cdde4b5..88dd83c13 100644 --- a/app/upgrades/types.go +++ b/app/upgrades/types.go @@ -4,12 +4,14 @@ import ( store "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" ) type Upgrade struct { UpgradeName string - CreateUpgradeHandler func(*module.Manager, module.Configurator) types.UpgradeHandler + CreateUpgradeHandler func(*module.Manager, module.Configurator, clientkeeper.Keeper) types.UpgradeHandler StoreUpgrades store.StoreUpgrades } diff --git a/app/upgrades/v1_1_0/constants.go b/app/upgrades/v1_1_0/constants.go index 4fdebdf6c..bd119eb7a 100644 --- a/app/upgrades/v1_1_0/constants.go +++ b/app/upgrades/v1_1_0/constants.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" "github.com/NibiruChain/nibiru/v2/app/upgrades" inflationtypes "github.com/NibiruChain/nibiru/v2/x/inflation/types" @@ -14,7 +15,7 @@ const UpgradeName = "v1.1.0" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, - CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator, clientKeeper clientkeeper.Keeper) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return mm.RunMigrations(ctx, cfg, fromVM) } diff --git a/app/upgrades/v1_2_0/constants.go b/app/upgrades/v1_2_0/constants.go index 63718c21d..0805d4b66 100644 --- a/app/upgrades/v1_2_0/constants.go +++ b/app/upgrades/v1_2_0/constants.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" "github.com/NibiruChain/nibiru/v2/app/upgrades" ) @@ -13,7 +14,7 @@ const UpgradeName = "v1.2.0" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, - CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator, clientKeeper clientkeeper.Keeper) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return mm.RunMigrations(ctx, cfg, fromVM) } diff --git a/app/upgrades/v1_3_0/constants.go b/app/upgrades/v1_3_0/constants.go index 320bdae7c..263817ac0 100644 --- a/app/upgrades/v1_3_0/constants.go +++ b/app/upgrades/v1_3_0/constants.go @@ -14,6 +14,7 @@ import ( icahosttypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" "github.com/NibiruChain/nibiru/v2/app/upgrades" ) @@ -22,7 +23,7 @@ const UpgradeName = "v1.3.0" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, - CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator, clientKeeper clientkeeper.Keeper) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { // set the ICS27 consensus version so InitGenesis is not run fromVM[icatypes.ModuleName] = mm.GetVersionMap()[icatypes.ModuleName] diff --git a/app/upgrades/v1_4_0/constants.go b/app/upgrades/v1_4_0/constants.go index fbfa766ea..28d53df22 100644 --- a/app/upgrades/v1_4_0/constants.go +++ b/app/upgrades/v1_4_0/constants.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" "github.com/NibiruChain/nibiru/v2/app/upgrades" ) @@ -13,7 +14,7 @@ const UpgradeName = "v1.4.0" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, - CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator, clientKeeper clientkeeper.Keeper) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return mm.RunMigrations(ctx, cfg, fromVM) } diff --git a/app/upgrades/v2_1_0/constants.go b/app/upgrades/v2_1_0/constants.go new file mode 100644 index 000000000..f294c66a4 --- /dev/null +++ b/app/upgrades/v2_1_0/constants.go @@ -0,0 +1,42 @@ +package v2_1_0 + +import ( + "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + clientkeeper "github.com/cosmos/ibc-go/v7/modules/core/02-client/keeper" + + "github.com/NibiruChain/nibiru/v2/app/upgrades" +) + +const UpgradeName = "v2.1.0" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: func(mm *module.Manager, cfg module.Configurator, clientKeeper clientkeeper.Keeper) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // explicitly update the IBC 02-client params, adding the wasm client type if it is not there + params := clientKeeper.GetParams(ctx) + + hasWasmClient := false + for _, client := range params.AllowedClients { + if client == ibcwasmtypes.Wasm { + hasWasmClient = true + break + } + } + + if !hasWasmClient { + params.AllowedClients = append(params.AllowedClients, ibcwasmtypes.Wasm) + clientKeeper.SetParams(ctx, params) + } + + return mm.RunMigrations(ctx, cfg, fromVM) + } + }, + StoreUpgrades: types.StoreUpgrades{ + Added: []string{ibcwasmtypes.ModuleName}, + }, +} diff --git a/cmd/nibid/cmd/init.go b/cmd/nibid/cmd/init.go index 1d8c439a9..13de92198 100644 --- a/cmd/nibid/cmd/init.go +++ b/cmd/nibid/cmd/init.go @@ -8,6 +8,7 @@ import ( "path/filepath" tmcfg "github.com/cometbft/cometbft/config" + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" "github.com/NibiruChain/nibiru/v2/app/appconst" @@ -25,6 +26,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/genutil" + + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + ibctypes "github.com/cosmos/ibc-go/v7/modules/core/types" ) const ( @@ -129,6 +133,11 @@ func InitCmd(mbm module.BasicManager, defaultNodeHome string) *cobra.Command { } appGenState := mbm.DefaultGenesis(cdc) + // add 08-wasm to AllowedClients + ibcState := ibctypes.DefaultGenesisState() + ibcState.ClientGenesis.Params.AllowedClients = append(ibcState.ClientGenesis.Params.AllowedClients, ibcwasmtypes.Wasm) + appGenState[ibcexported.ModuleName] = cdc.MustMarshalJSON(ibcState) + appState, err := json.MarshalIndent(appGenState, "", " ") if err != nil { return errors.Wrap(err, "Failed to marshal default genesis state") diff --git a/go.mod b/go.mod index bc14078f3..99e351a4e 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( // Cosmos-SDK and IBC github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.47.11 - github.com/cosmos/ibc-go/v7 v7.3.2 + github.com/cosmos/ibc-go/v7 v7.4.0 github.com/ethereum/go-ethereum v1.10.17 ) @@ -57,6 +57,7 @@ require ( require ( cosmossdk.io/collections v0.4.0 cosmossdk.io/tools/rosetta v0.2.1 + github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.3.2-0.20240730185603-13c071f0b34d github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/gorilla/websocket v1.5.0 github.com/rs/cors v1.8.3 diff --git a/go.sum b/go.sum index 213ee9c84..616630872 100644 --- a/go.sum +++ b/go.sum @@ -438,8 +438,10 @@ github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoK github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= -github.com/cosmos/ibc-go/v7 v7.3.2 h1:FeUDcBX7VYY0e0iRmcVkPPUjYfAqIc//QuHXo8JHz9c= -github.com/cosmos/ibc-go/v7 v7.3.2/go.mod h1:IMeOXb7gwpZ+/nOG5BuUkdW4weM1ezvN4PQPws4uzOI= +github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.3.2-0.20240730185603-13c071f0b34d h1:QJK/Zr0HblNx6z1x5LXIHEblY7DCCftMkUBcjpKe1qY= +github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.3.2-0.20240730185603-13c071f0b34d/go.mod h1:5oIHokzX6RJ6q93tLcWZ7Thkrt9vrMGIz3He9HFE660= +github.com/cosmos/ibc-go/v7 v7.4.0 h1:8FqYMptvksgMvlbN4UW9jFxTXzsPyfAzEZurujXac8M= +github.com/cosmos/ibc-go/v7 v7.4.0/go.mod h1:L/KaEhzV5TGUCTfGysVgMBQtl5Dm7hHitfpk+GIeoAo= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw= From ecf3e476cf393384df582141fcedd0411ba6f470 Mon Sep 17 00:00:00 2001 From: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:15:01 -0500 Subject: [PATCH 08/12] fix(evm): Use a NibiruBankKeeper to automatically record ether balance changes on the StateDB journal (#2095) * statedb: add cacheing for multistore before precompile runs * messy, working first version that allows for precompile reversion * wip!: Save checkpoint. 1. Created NibiruBankKeeper with safety around NIBI transfers inside of EthereumTx. 2. The "PrecompileCalled" JournalChange now has a propery implementation and a strong test case to show that reverting the precompile calls works as intended. 3. Remove unneeded functions created for testing with low-level struct fields. * chore: changelog * finalize bank keeper changes * chore changelog * reset cache * finalize bank keeper changes * revert to previous commit 7f904a07ac4d5555d8c088411024fc50ff65d085 * fix strange ignored file issue * fix strange ignored file issue * remove new bank keeper * chore: comments from self-review * chore: changelo g * fix(deps): update bank module to remove concrete type assertion on AppModule.RegisterServices This makes it possible to plug in an alternative bankkeeper.Keeper implementation instead of bankkeeper.BaseKeeper. * chore: merge conflicts * revert experiment * finishing touch * fix incorrect arugmetn * feat(evmtest-erc20: Add optional descriptions to the assertions --- CHANGELOG.md | 22 ++- app/ante/gas_wanted_test.go | 2 +- app/ante/handler_opts.go | 2 +- app/evmante/evmante_can_transfer.go | 3 +- app/evmante/evmante_can_transfer_test.go | 4 +- app/evmante/evmante_emit_event_test.go | 4 +- app/evmante/evmante_gas_consume_test.go | 4 +- app/evmante/evmante_handler.go | 18 +- app/evmante/evmante_handler_test.go | 2 +- .../evmante_increment_sender_seq_test.go | 4 +- app/evmante/evmante_mempool_fees_test.go | 2 +- app/evmante/evmante_setup_ctx_test.go | 4 +- app/evmante/evmante_sigverify_test.go | 4 +- app/evmante/evmante_validate_basic_test.go | 4 +- app/evmante/evmante_verify_eth_acc_test.go | 4 +- app/keepers.go | 29 ++-- app/keepers/all_keepers.go | 2 +- go.mod | 2 +- go.sum | 4 +- .../TestNativeSendThenPrecompileSend.json | 4 +- .../TestNativeSendThenPrecompileSend.sol | 21 ++- x/evm/evmmodule/genesis_test.go | 4 +- x/evm/evmtest/erc20.go | 70 +++++++- x/evm/evmtest/eth_test.go | 13 +- x/evm/evmtest/smart_contract_test.go | 4 +- x/evm/evmtest/test_deps.go | 4 +- x/evm/evmtest/tx.go | 15 +- x/evm/keeper/bank_extension.go | 155 ++++++++++++++++++ x/evm/keeper/erc20.go | 4 +- x/evm/keeper/funtoken_from_coin.go | 2 +- x/evm/keeper/funtoken_from_coin_test.go | 133 +++++++++------ x/evm/keeper/funtoken_from_erc20.go | 4 +- x/evm/keeper/funtoken_from_erc20_test.go | 2 +- x/evm/keeper/gas_fees.go | 4 +- x/evm/keeper/grpc_query_test.go | 4 +- x/evm/keeper/keeper.go | 9 +- x/evm/keeper/msg_ethereum_tx_test.go | 8 +- x/evm/keeper/msg_server.go | 22 +-- x/evm/keeper/statedb.go | 20 +-- x/evm/keeper/statedb_test.go | 6 +- x/evm/precompile/funtoken.go | 82 ++------- x/evm/precompile/funtoken_test.go | 4 +- x/evm/precompile/wasm.go | 8 + x/evm/statedb/statedb.go | 4 + x/evm/statedb/statedb_test.go | 36 ++-- 45 files changed, 496 insertions(+), 266 deletions(-) create mode 100644 x/evm/keeper/bank_extension.go diff --git a/CHANGELOG.md b/CHANGELOG.md index dade1db65..884cc7e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,7 +68,12 @@ consistent setup and dynamic gas calculations, addressing the following tickets. - - [#2088](https://github.com/NibiruChain/nibiru/pull/2088) - refactor(evm): remove outdated comment and improper error message text - [#2089](https://github.com/NibiruChain/nibiru/pull/2089) - better handling of gas consumption within erc20 contract execution +- [#2090](https://github.com/NibiruChain/nibiru/pull/2090) - fix(evm): Account +for (1) ERC20 transfers with tokens that return false success values instead of +throwing an error and (2) ERC20 transfers with other operations that don't bring +about the expected resulting balance for the transfer recipient. - [#2091](https://github.com/NibiruChain/nibiru/pull/2091) - feat(evm): add fun token creation fee validation +- [#2092](https://github.com/NibiruChain/nibiru/pull/2092) - feat(evm): add validation for wasm multi message execution - [#2094](https://github.com/NibiruChain/nibiru/pull/2094) - fix(evm): Following from the changs in #2086, this pull request implements a new `JournalChange` struct that saves a deep copy of the state multi store before each @@ -78,12 +83,17 @@ non-EVM and EVM state will be in sync even if there are complex, multi-step Ethereum transactions, such as in the case of an EthereumTx that influences the `StateDB`, then calls a precompile that also changes non-EVM state, and then EVM reverts inside of a try-catch. -- [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb tests for race conditions within funtoken precompile -- [#2090](https://github.com/NibiruChain/nibiru/pull/2090) - fix(evm): Account -for (1) ERC20 transfers with tokens that return false success values instead of -throwing an error and (2) ERC20 transfers with other operations that don't bring -about the expected resulting balance for the transfer recipient. -- [#2092](https://github.com/NibiruChain/nibiru/pull/2092) - feat(evm): add validation for wasm multi message execution +- [#2095](https://github.com/NibiruChain/nibiru/pull/2095) - fix(evm): This +change records NIBI (ether) transfers on the `StateDB` during precompiled +contract calls using the `NibiruBankKeeper`, which is struct extension of +the `bankkeeper.BaseKeeper` that is used throughout Nibiru. +The `NibiruBankKeeper` holds a reference to the current EVM `StateDB` and records +balance changes in wei as journal changes automatically. This guarantees that +commits and reversions of the `StateDB` do not misalign with the state of the +Bank module. This code change uses the `NibiruBankKeeper` on all modules that +depend on x/bank, such as the EVM and Wasm modules. +- [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb +tests for race conditions within funtoken precompile - [#2068](https://github.com/NibiruChain/nibiru/pull/2068) - feat: enable wasm light clients on IBC (08-wasm) - [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling diff --git a/app/ante/gas_wanted_test.go b/app/ante/gas_wanted_test.go index d892a8217..92b5d1343 100644 --- a/app/ante/gas_wanted_test.go +++ b/app/ante/gas_wanted_test.go @@ -83,7 +83,7 @@ func (s *AnteTestSuite) TestGasWantedDecorator() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() + stateDB := deps.NewStateDB() anteDec := ante.AnteDecoratorGasWanted{} tx := tc.txSetup(&deps) diff --git a/app/ante/handler_opts.go b/app/ante/handler_opts.go index b516653c8..9c1d88301 100644 --- a/app/ante/handler_opts.go +++ b/app/ante/handler_opts.go @@ -20,7 +20,7 @@ type AnteHandlerOptions struct { IBCKeeper *ibckeeper.Keeper DevGasKeeper *devgaskeeper.Keeper DevGasBankKeeper devgasante.BankKeeper - EvmKeeper evmkeeper.Keeper + EvmKeeper *evmkeeper.Keeper AccountKeeper authkeeper.AccountKeeper TxCounterStoreKey types.StoreKey diff --git a/app/evmante/evmante_can_transfer.go b/app/evmante/evmante_can_transfer.go index 8af24d2f2..0f8cd0d06 100644 --- a/app/evmante/evmante_can_transfer.go +++ b/app/evmante/evmante_can_transfer.go @@ -72,9 +72,8 @@ func (ctd CanTransferDecorator) AnteHandle( BaseFeeWei: baseFeeWeiPerGas, } - stateDB := statedb.New( + stateDB := ctd.NewStateDB( ctx, - ctd.EVMKeeper, statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash().Bytes())), ) evmInstance := ctd.EVMKeeper.NewEVM(ctx, coreMsg, cfg, evm.NewNoOpTracer(), stateDB) diff --git a/app/evmante/evmante_can_transfer_test.go b/app/evmante/evmante_can_transfer_test.go index 2fa71c674..381597624 100644 --- a/app/evmante/evmante_can_transfer_test.go +++ b/app/evmante/evmante_can_transfer_test.go @@ -88,8 +88,8 @@ func (s *TestSuite) TestCanTransferDecorator() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.CanTransferDecorator{&deps.App.AppKeepers.EvmKeeper} + stateDB := deps.NewStateDB() + anteDec := evmante.CanTransferDecorator{deps.App.AppKeepers.EvmKeeper} tx := tc.txSetup(&deps) if tc.ctxSetup != nil { diff --git a/app/evmante/evmante_emit_event_test.go b/app/evmante/evmante_emit_event_test.go index 855165450..20ff36f5d 100644 --- a/app/evmante/evmante_emit_event_test.go +++ b/app/evmante/evmante_emit_event_test.go @@ -41,8 +41,8 @@ func (s *TestSuite) TestEthEmitEventDecorator() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.NewEthEmitEventDecorator(&deps.App.AppKeepers.EvmKeeper) + stateDB := deps.NewStateDB() + anteDec := evmante.NewEthEmitEventDecorator(deps.App.AppKeepers.EvmKeeper) tx := tc.txSetup(&deps) s.Require().NoError(stateDB.Commit()) diff --git a/app/evmante/evmante_gas_consume_test.go b/app/evmante/evmante_gas_consume_test.go index 1e3c6b1fe..3291c3349 100644 --- a/app/evmante/evmante_gas_consume_test.go +++ b/app/evmante/evmante_gas_consume_test.go @@ -59,9 +59,9 @@ func (s *TestSuite) TestAnteDecEthGasConsume() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() + stateDB := deps.NewStateDB() anteDec := evmante.NewAnteDecEthGasConsume( - &deps.App.AppKeepers.EvmKeeper, tc.maxGasWanted, + deps.App.AppKeepers.EvmKeeper, tc.maxGasWanted, ) tc.beforeTxSetup(&deps, stateDB) diff --git a/app/evmante/evmante_handler.go b/app/evmante/evmante_handler.go index 787be312e..a9c2f7d0f 100644 --- a/app/evmante/evmante_handler.go +++ b/app/evmante/evmante_handler.go @@ -13,16 +13,16 @@ func NewAnteHandlerEVM( ) sdk.AnteHandler { return sdk.ChainAnteDecorators( // outermost AnteDecorator. SetUpContext must be called first - NewEthSetUpContextDecorator(&options.EvmKeeper), - NewMempoolGasPriceDecorator(&options.EvmKeeper), - NewEthValidateBasicDecorator(&options.EvmKeeper), - NewEthSigVerificationDecorator(&options.EvmKeeper), - NewAnteDecVerifyEthAcc(&options.EvmKeeper, options.AccountKeeper), - CanTransferDecorator{&options.EvmKeeper}, - NewAnteDecEthGasConsume(&options.EvmKeeper, options.MaxTxGasWanted), - NewAnteDecEthIncrementSenderSequence(&options.EvmKeeper, options.AccountKeeper), + NewEthSetUpContextDecorator(options.EvmKeeper), + NewMempoolGasPriceDecorator(options.EvmKeeper), + NewEthValidateBasicDecorator(options.EvmKeeper), + NewEthSigVerificationDecorator(options.EvmKeeper), + NewAnteDecVerifyEthAcc(options.EvmKeeper, options.AccountKeeper), + CanTransferDecorator{options.EvmKeeper}, + NewAnteDecEthGasConsume(options.EvmKeeper, options.MaxTxGasWanted), + NewAnteDecEthIncrementSenderSequence(options.EvmKeeper, options.AccountKeeper), ante.AnteDecoratorGasWanted{}, // emit eth tx hash and index at the very last ante handler. - NewEthEmitEventDecorator(&options.EvmKeeper), + NewEthEmitEventDecorator(options.EvmKeeper), ) } diff --git a/app/evmante/evmante_handler_test.go b/app/evmante/evmante_handler_test.go index 62e7afb0d..5ab7e8a1f 100644 --- a/app/evmante/evmante_handler_test.go +++ b/app/evmante/evmante_handler_test.go @@ -69,7 +69,7 @@ func (s *TestSuite) TestAnteHandlerEVM() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() + stateDB := deps.NewStateDB() anteHandlerEVM := evmante.NewAnteHandlerEVM( ante.AnteHandlerOptions{ diff --git a/app/evmante/evmante_increment_sender_seq_test.go b/app/evmante/evmante_increment_sender_seq_test.go index ac358cbb0..b4503e675 100644 --- a/app/evmante/evmante_increment_sender_seq_test.go +++ b/app/evmante/evmante_increment_sender_seq_test.go @@ -66,8 +66,8 @@ func (s *TestSuite) TestAnteDecEthIncrementSenderSequence() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.NewAnteDecEthIncrementSenderSequence(&deps.App.EvmKeeper, deps.App.AccountKeeper) + stateDB := deps.NewStateDB() + anteDec := evmante.NewAnteDecEthIncrementSenderSequence(deps.App.EvmKeeper, deps.App.AccountKeeper) if tc.beforeTxSetup != nil { tc.beforeTxSetup(&deps, stateDB) diff --git a/app/evmante/evmante_mempool_fees_test.go b/app/evmante/evmante_mempool_fees_test.go index ef7b34e64..892bd9e57 100644 --- a/app/evmante/evmante_mempool_fees_test.go +++ b/app/evmante/evmante_mempool_fees_test.go @@ -82,7 +82,7 @@ func (s *TestSuite) TestMempoolGasFeeDecorator() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - anteDec := evmante.NewMempoolGasPriceDecorator(&deps.App.AppKeepers.EvmKeeper) + anteDec := evmante.NewMempoolGasPriceDecorator(deps.App.AppKeepers.EvmKeeper) tx := tc.txSetup(&deps) diff --git a/app/evmante/evmante_setup_ctx_test.go b/app/evmante/evmante_setup_ctx_test.go index 9df86ba17..028fceb52 100644 --- a/app/evmante/evmante_setup_ctx_test.go +++ b/app/evmante/evmante_setup_ctx_test.go @@ -12,8 +12,8 @@ import ( func (s *TestSuite) TestEthSetupContextDecorator() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.NewEthSetUpContextDecorator(&deps.App.EvmKeeper) + stateDB := deps.NewStateDB() + anteDec := evmante.NewEthSetUpContextDecorator(deps.App.EvmKeeper) s.Require().NoError(stateDB.Commit()) tx := evmtest.HappyCreateContractTx(&deps) diff --git a/app/evmante/evmante_sigverify_test.go b/app/evmante/evmante_sigverify_test.go index 63b290140..d6a7998b1 100644 --- a/app/evmante/evmante_sigverify_test.go +++ b/app/evmante/evmante_sigverify_test.go @@ -66,8 +66,8 @@ func (s *TestSuite) TestEthSigVerificationDecorator() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.NewEthSigVerificationDecorator(&deps.App.AppKeepers.EvmKeeper) + stateDB := deps.NewStateDB() + anteDec := evmante.NewEthSigVerificationDecorator(deps.App.AppKeepers.EvmKeeper) tx := tc.txSetup(&deps) s.Require().NoError(stateDB.Commit()) diff --git a/app/evmante/evmante_validate_basic_test.go b/app/evmante/evmante_validate_basic_test.go index 3f1263dee..2aa7910dd 100644 --- a/app/evmante/evmante_validate_basic_test.go +++ b/app/evmante/evmante_validate_basic_test.go @@ -198,8 +198,8 @@ func (s *TestSuite) TestEthValidateBasicDecorator() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.NewEthValidateBasicDecorator(&deps.App.AppKeepers.EvmKeeper) + stateDB := deps.NewStateDB() + anteDec := evmante.NewEthValidateBasicDecorator(deps.App.AppKeepers.EvmKeeper) tx := tc.txSetup(&deps) s.Require().NoError(stateDB.Commit()) diff --git a/app/evmante/evmante_verify_eth_acc_test.go b/app/evmante/evmante_verify_eth_acc_test.go index 6d7f9aeda..2af951aa5 100644 --- a/app/evmante/evmante_verify_eth_acc_test.go +++ b/app/evmante/evmante_verify_eth_acc_test.go @@ -64,8 +64,8 @@ func (s *TestSuite) TestAnteDecoratorVerifyEthAcc_CheckTx() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - stateDB := deps.StateDB() - anteDec := evmante.NewAnteDecVerifyEthAcc(&deps.App.AppKeepers.EvmKeeper, &deps.App.AppKeepers.AccountKeeper) + stateDB := deps.NewStateDB() + anteDec := evmante.NewAnteDecVerifyEthAcc(deps.App.AppKeepers.EvmKeeper, &deps.App.AppKeepers.AccountKeeper) tc.beforeTxSetup(&deps, stateDB) tx := tc.txSetup(&deps) diff --git a/app/keepers.go b/app/keepers.go index 156ef6413..e74b89167 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -146,7 +146,6 @@ type AppKeepers struct { } type privateKeepers struct { - bankBaseKeeper bankkeeper.BaseKeeper capabilityKeeper *capabilitykeeper.Keeper slashingKeeper slashingkeeper.Keeper crisisKeeper crisiskeeper.Keeper @@ -271,14 +270,17 @@ func (app *NibiruApp) InitKeepers( govModuleAddr, ) - app.bankBaseKeeper = bankkeeper.NewBaseKeeper( - appCodec, - keys[banktypes.StoreKey], - app.AccountKeeper, - BlockedAddresses(), - govModuleAddr, - ) - app.BankKeeper = app.bankBaseKeeper + nibiruBankKeeper := &evmkeeper.NibiruBankKeeper{ + BaseKeeper: bankkeeper.NewBaseKeeper( + appCodec, + keys[banktypes.StoreKey], + app.AccountKeeper, + BlockedAddresses(), + govModuleAddr, + ), + StateDB: nil, + } + app.BankKeeper = nibiruBankKeeper app.StakingKeeper = stakingkeeper.NewKeeper( appCodec, keys[stakingtypes.StoreKey], @@ -374,16 +376,17 @@ func (app *NibiruApp) InitKeepers( ), ) - app.EvmKeeper = evmkeeper.NewKeeper( + evmKeeper := evmkeeper.NewKeeper( appCodec, keys[evm.StoreKey], tkeys[evm.TransientKey], authtypes.NewModuleAddress(govtypes.ModuleName), app.AccountKeeper, - app.BankKeeper, + nibiruBankKeeper, app.StakingKeeper, cast.ToString(appOpts.Get("evm.tracer")), ) + app.EvmKeeper = &evmKeeper // ---------------------------------- IBC keepers @@ -631,7 +634,7 @@ func (app *NibiruApp) initAppModules( ), auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), - bank.NewAppModule(appCodec, app.bankBaseKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), capability.NewAppModule(appCodec, *app.capabilityKeeper, false), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), @@ -657,7 +660,7 @@ func (app *NibiruApp) initAppModules( ica.NewAppModule(&app.icaControllerKeeper, &app.icaHostKeeper), ibcwasm.NewAppModule(app.WasmClientKeeper), - evmmodule.NewAppModule(&app.EvmKeeper, app.AccountKeeper), + evmmodule.NewAppModule(app.EvmKeeper, app.AccountKeeper), // wasm wasm.NewAppModule( diff --git a/app/keepers/all_keepers.go b/app/keepers/all_keepers.go index 25303860f..0ebc82afd 100644 --- a/app/keepers/all_keepers.go +++ b/app/keepers/all_keepers.go @@ -64,7 +64,7 @@ type PublicKeepers struct { SudoKeeper keeper.Keeper DevGasKeeper devgaskeeper.Keeper TokenFactoryKeeper tokenfactorykeeper.Keeper - EvmKeeper evmkeeper.Keeper + EvmKeeper *evmkeeper.Keeper // WASM keepers WasmKeeper wasmkeeper.Keeper diff --git a/go.mod b/go.mod index 99e351a4e..c4546c826 100644 --- a/go.mod +++ b/go.mod @@ -246,7 +246,7 @@ replace ( cosmossdk.io/api => cosmossdk.io/api v0.3.1 github.com/CosmWasm/wasmd => github.com/NibiruChain/wasmd v0.44.0-nibiru - github.com/cosmos/cosmos-sdk => github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru + github.com/cosmos/cosmos-sdk => github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru.2 github.com/cosmos/iavl => github.com/cosmos/iavl v0.20.0 diff --git a/go.sum b/go.sum index 616630872..a4fec943d 100644 --- a/go.sum +++ b/go.sum @@ -235,8 +235,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NibiruChain/collections v0.5.0 h1:33pXpVTe1PK/tfdZlAJF1JF7AdzGNARG+iL9G/z3X7k= github.com/NibiruChain/collections v0.5.0/go.mod h1:43L6yjuF0BMre/mw4gqn/kUOZz1c2Y3huZ/RQfBFrOQ= -github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru h1:PgFpxDe+7+OzWHs4zXlml5j2i9sGq2Zpd3ndYQG29/0= -github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= +github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru.2 h1:HtLNrkp0HhgxtbpdNwsasOod4uUNFpuwYpyceFtbj3E= +github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru.2/go.mod h1:ADjORYzUQqQv/FxDi0H0K5gW/rAk1CiDR3ZKsExfJV0= github.com/NibiruChain/go-ethereum v1.10.27-nibiru h1:o6lRFt57izoYwzN5cG8tnnBtJcaO3X7MjjN7PGGNCFg= github.com/NibiruChain/go-ethereum v1.10.27-nibiru/go.mod h1:kvvL3nDceUcB+1qGUBAsVf5dW23RBR77fqxgx2PGNrQ= github.com/NibiruChain/wasmd v0.44.0-nibiru h1:b+stNdbMFsl0+o4KedXyF83qRnEpB/jCiTGZZgv2h2U= diff --git a/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json b/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json index 5b0046040..e4a2ccfb1 100644 --- a/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json +++ b/x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json @@ -43,8 +43,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b50604051610877380380610877833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b610760806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea2646970667358221220bd148fba67bf9e1966835ecfba5be560625fcf8c88f7890050149168488a782364736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a6004803603810190610045919061043c565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc9061051c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168486604051602401610115939291906105da565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161019f919061065f565b6000604051808303816000865af19150503d80600081146101dc576040519150601f19603f3d011682016040523d82523d6000602084013e6101e1565b606091505b50509050806040516020016101f5906106f3565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610708565b60405180910390fd5b50505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028d82610262565b9050919050565b61029d81610282565b81146102a857600080fd5b50565b6000813590506102ba81610294565b92915050565b6000819050919050565b6102d3816102c0565b81146102de57600080fd5b50565b6000813590506102f0816102ca565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61034982610300565b810181811067ffffffffffffffff8211171561036857610367610311565b5b80604052505050565b600061037b61024e565b90506103878282610340565b919050565b600067ffffffffffffffff8211156103a7576103a6610311565b5b6103b082610300565b9050602081019050919050565b82818337600083830152505050565b60006103df6103da8461038c565b610371565b9050828152602081018484840111156103fb576103fa6102fb565b5b6104068482856103bd565b509392505050565b600082601f830112610423576104226102f6565b5b81356104338482602086016103cc565b91505092915050565b6000806000806080858703121561045657610455610258565b5b6000610464878288016102ab565b9450506020610475878288016102e1565b935050604085013567ffffffffffffffff8111156104965761049561025d565b5b6104a28782880161040e565b92505060606104b3878288016102e1565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b6000610506601b836104bf565b9150610511826104d0565b602082019050919050565b60006020820190508181036000830152610535816104f9565b9050919050565b600061054782610262565b9050919050565b6105578161053c565b82525050565b610566816102c0565b82525050565b600081519050919050565b60005b8381101561059557808201518184015260208101905061057a565b60008484015250505050565b60006105ac8261056c565b6105b681856104bf565b93506105c6818560208601610577565b6105cf81610300565b840191505092915050565b60006060820190506105ef600083018661054e565b6105fc602083018561055d565b818103604083015261060e81846105a1565b9050949350505050565b600081519050919050565b600081905092915050565b600061063982610618565b6106438185610623565b9350610653818560208601610577565b80840191505092915050565b600061066b828461062e565b915081905092915050565b600081905092915050565b7f4661696c656420746f2063616c6c20707265636f6d70696c652062616e6b536560008201527f6e64000000000000000000000000000000000000000000000000000000000000602082015250565b60006106dd602283610676565b91506106e882610681565b602282019050919050565b60006106fe826106d0565b9150819050919050565b6000602082019050818103600083015261072281846105a1565b90509291505056fea2646970667358221220bd148fba67bf9e1966835ecfba5be560625fcf8c88f7890050149168488a782364736f6c63430008180033", + "bytecode": "0x608060405234801561001057600080fd5b50604051610afc380380610afc833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b6109e5806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a600480360381019061004591906105f9565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc906106d9565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685876040518463ffffffff1660e01b815260040161012693929190610797565b6020604051808303816000875af1158015610145573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061016991906107ea565b9050828114610177826101ea565b610180856101ea565b604051602001610191929190610911565b604051602081830303815290604052906101e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d8919061095e565b60405180910390fd5b50505050505050565b6060600060016101f9846102b8565b01905060008167ffffffffffffffff811115610218576102176104ce565b5b6040519080825280601f01601f19166020018201604052801561024a5781602001600182028036833780820191505090505b509050600082602001820190505b6001156102ad578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816102a1576102a0610980565b5b04945060008503610258575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610316577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161030c5761030b610980565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310610353576d04ee2d6d415b85acef8100000000838161034957610348610980565b5b0492506020810190505b662386f26fc10000831061038257662386f26fc10000838161037857610377610980565b5b0492506010810190505b6305f5e10083106103ab576305f5e10083816103a1576103a0610980565b5b0492506008810190505b61271083106103d05761271083816103c6576103c5610980565b5b0492506004810190505b606483106103f357606483816103e9576103e8610980565b5b0492506002810190505b600a8310610402576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061044a8261041f565b9050919050565b61045a8161043f565b811461046557600080fd5b50565b60008135905061047781610451565b92915050565b6000819050919050565b6104908161047d565b811461049b57600080fd5b50565b6000813590506104ad81610487565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610506826104bd565b810181811067ffffffffffffffff82111715610525576105246104ce565b5b80604052505050565b600061053861040b565b905061054482826104fd565b919050565b600067ffffffffffffffff821115610564576105636104ce565b5b61056d826104bd565b9050602081019050919050565b82818337600083830152505050565b600061059c61059784610549565b61052e565b9050828152602081018484840111156105b8576105b76104b8565b5b6105c384828561057a565b509392505050565b600082601f8301126105e0576105df6104b3565b5b81356105f0848260208601610589565b91505092915050565b6000806000806080858703121561061357610612610415565b5b600061062187828801610468565b94505060206106328782880161049e565b935050604085013567ffffffffffffffff8111156106535761065261041a565b5b61065f878288016105cb565b92505060606106708782880161049e565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b60006106c3601b8361067c565b91506106ce8261068d565b602082019050919050565b600060208201905081810360008301526106f2816106b6565b9050919050565b60006107048261041f565b9050919050565b610714816106f9565b82525050565b6107238161047d565b82525050565b600081519050919050565b60005b83811015610752578082015181840152602081019050610737565b60008484015250505050565b600061076982610729565b610773818561067c565b9350610783818560208601610734565b61078c816104bd565b840191505092915050565b60006060820190506107ac600083018661070b565b6107b9602083018561071a565b81810360408301526107cb818461075e565b9050949350505050565b6000815190506107e481610487565b92915050565b600060208284031215610800576107ff610415565b5b600061080e848285016107d5565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b600061087e603d83610817565b915061088982610822565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b60006108c582610729565b6108cf8185610817565b93506108df818560208601610734565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b600061091c82610871565b915061092782610894565b600b8201915061093782856108ba565b9150610942826108eb565b60098201915061095282846108ba565b91508190509392505050565b60006020820190508181036000830152610978818461075e565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220df7092cb424bd549df3b9d958db66a63c029a1e42d78f468fb93c7574ccea23864736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a4de557414610030575b600080fd5b61004a600480360381019061004591906105f9565b61004c565b005b60008473ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f193505050509050806100c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bc906106d9565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685876040518463ffffffff1660e01b815260040161012693929190610797565b6020604051808303816000875af1158015610145573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061016991906107ea565b9050828114610177826101ea565b610180856101ea565b604051602001610191929190610911565b604051602081830303815290604052906101e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d8919061095e565b60405180910390fd5b50505050505050565b6060600060016101f9846102b8565b01905060008167ffffffffffffffff811115610218576102176104ce565b5b6040519080825280601f01601f19166020018201604052801561024a5781602001600182028036833780820191505090505b509050600082602001820190505b6001156102ad578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816102a1576102a0610980565b5b04945060008503610258575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610316577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161030c5761030b610980565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310610353576d04ee2d6d415b85acef8100000000838161034957610348610980565b5b0492506020810190505b662386f26fc10000831061038257662386f26fc10000838161037857610377610980565b5b0492506010810190505b6305f5e10083106103ab576305f5e10083816103a1576103a0610980565b5b0492506008810190505b61271083106103d05761271083816103c6576103c5610980565b5b0492506004810190505b606483106103f357606483816103e9576103e8610980565b5b0492506002810190505b600a8310610402576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061044a8261041f565b9050919050565b61045a8161043f565b811461046557600080fd5b50565b60008135905061047781610451565b92915050565b6000819050919050565b6104908161047d565b811461049b57600080fd5b50565b6000813590506104ad81610487565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610506826104bd565b810181811067ffffffffffffffff82111715610525576105246104ce565b5b80604052505050565b600061053861040b565b905061054482826104fd565b919050565b600067ffffffffffffffff821115610564576105636104ce565b5b61056d826104bd565b9050602081019050919050565b82818337600083830152505050565b600061059c61059784610549565b61052e565b9050828152602081018484840111156105b8576105b76104b8565b5b6105c384828561057a565b509392505050565b600082601f8301126105e0576105df6104b3565b5b81356105f0848260208601610589565b91505092915050565b6000806000806080858703121561061357610612610415565b5b600061062187828801610468565b94505060206106328782880161049e565b935050604085013567ffffffffffffffff8111156106535761065261041a565b5b61065f878288016105cb565b92505060606106708782880161049e565b91505092959194509250565b600082825260208201905092915050565b7f4661696c656420746f2073656e64206e617469766520746f6b656e0000000000600082015250565b60006106c3601b8361067c565b91506106ce8261068d565b602082019050919050565b600060208201905081810360008301526106f2816106b6565b9050919050565b60006107048261041f565b9050919050565b610714816106f9565b82525050565b6107238161047d565b82525050565b600081519050919050565b60005b83811015610752578082015181840152602081019050610737565b60008484015250505050565b600061076982610729565b610773818561067c565b9350610783818560208601610734565b61078c816104bd565b840191505092915050565b60006060820190506107ac600083018661070b565b6107b9602083018561071a565b81810360408301526107cb818461075e565b9050949350505050565b6000815190506107e481610487565b92915050565b600060208284031215610800576107ff610415565b5b600061080e848285016107d5565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b600061087e603d83610817565b915061088982610822565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b60006108c582610729565b6108cf8185610817565b93506108df818560208601610734565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b600061091c82610871565b915061092782610894565b600b8201915061093782856108ba565b9150610942826108eb565b60098201915061095282846108ba565b91508190509392505050565b60006020820190508181036000830152610978818461075e565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220df7092cb424bd549df3b9d958db66a63c029a1e42d78f468fb93c7574ccea23864736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol b/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol index da9cb471b..45ec757b9 100644 --- a/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol +++ b/x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol @@ -20,15 +20,20 @@ contract TestNativeSendThenPrecompileSend { bool isSent = nativeRecipient.send(nativeAmount); require(isSent, "Failed to send native token"); - (bool success, ) = FUNTOKEN_PRECOMPILE_ADDRESS.call( - abi.encodeWithSignature( - "bankSend(address,uint256,string)", - erc20, - precompileAmount, - precompileRecipient + uint256 sentAmount = FUNTOKEN_PRECOMPILE.bankSend( + erc20, + precompileAmount, + precompileRecipient + ); + require( + sentAmount == precompileAmount, + string.concat( + "IFunToken.bankSend succeeded but transferred the wrong amount", + "sentAmount ", + Strings.toString(sentAmount), + "expected ", + Strings.toString(precompileAmount) ) ); - - require(success, string.concat("Failed to call precompile bankSend")); } } diff --git a/x/evm/evmmodule/genesis_test.go b/x/evm/evmmodule/genesis_test.go index 690745e84..72b884082 100644 --- a/x/evm/evmmodule/genesis_test.go +++ b/x/evm/evmmodule/genesis_test.go @@ -89,13 +89,13 @@ func (s *Suite) TestExportInitGenesis() { s.Require().NoError(err) // Export genesis - evmGenesisState := evmmodule.ExportGenesis(deps.Ctx, &deps.EvmKeeper, deps.App.AccountKeeper) + evmGenesisState := evmmodule.ExportGenesis(deps.Ctx, deps.EvmKeeper, deps.App.AccountKeeper) authGenesisState := deps.App.AccountKeeper.ExportGenesis(deps.Ctx) // Init genesis from the exported state deps = evmtest.NewTestDeps() deps.App.AccountKeeper.InitGenesis(deps.Ctx, *authGenesisState) - evmmodule.InitGenesis(deps.Ctx, &deps.EvmKeeper, deps.App.AccountKeeper, *evmGenesisState) + evmmodule.InitGenesis(deps.Ctx, deps.EvmKeeper, deps.App.AccountKeeper, *evmGenesisState) // Verify erc20 balances for users A, B and sender balance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, toUserA, deps.Ctx) diff --git a/x/evm/evmtest/erc20.go b/x/evm/evmtest/erc20.go index d8798f71d..3d7dd4d76 100644 --- a/x/evm/evmtest/erc20.go +++ b/x/evm/evmtest/erc20.go @@ -21,9 +21,7 @@ func AssertERC20BalanceEqual( erc20, account gethcommon.Address, expectedBalance *big.Int, ) { - actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx) - assert.NoError(t, err) - assert.Equal(t, expectedBalance.String(), actualBalance.String(), "expected %s, got %s", expectedBalance, actualBalance) + AssertERC20BalanceEqualWithDescription(t, deps, erc20, account, expectedBalance, "") } // CreateFunTokenForBankCoin: Uses the "TestDeps.Sender" account to create a @@ -95,9 +93,9 @@ func AssertBankBalanceEqual( account gethcommon.Address, expectedBalance *big.Int, ) { - bech32Addr := eth.EthAddrToNibiruAddr(account) - actualBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, bech32Addr, denom).Amount.BigInt() - assert.Zero(t, expectedBalance.Cmp(actualBalance), "expected %s, got %s", expectedBalance, actualBalance) + AssertBankBalanceEqualWithDescription( + t, deps, denom, account, expectedBalance, "", + ) } // BigPow multiplies "amount" by 10 to the "pow10Exp". @@ -105,3 +103,63 @@ func BigPow(amount *big.Int, pow10Exp uint8) (powAmount *big.Int) { pow10 := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(pow10Exp)), nil) return new(big.Int).Mul(amount, pow10) } + +type FunTokenBalanceAssert struct { + FunToken evm.FunToken + Account gethcommon.Address + BalanceBank *big.Int + BalanceERC20 *big.Int + Description string +} + +func (bals FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps) { + AssertERC20BalanceEqualWithDescription( + t, deps, bals.FunToken.Erc20Addr.Address, bals.Account, bals.BalanceERC20, + bals.Description, + ) + AssertBankBalanceEqualWithDescription( + t, deps, bals.FunToken.BankDenom, bals.Account, bals.BalanceBank, + bals.Description, + ) +} + +func AssertERC20BalanceEqualWithDescription( + t *testing.T, + deps TestDeps, + erc20, account gethcommon.Address, + expectedBalance *big.Int, + description string, +) { + actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx) + var errSuffix string + if description == "" { + errSuffix = description + } else { + errSuffix = ": " + description + } + assert.NoError(t, err, errSuffix) + assert.Equalf(t, expectedBalance.String(), actualBalance.String(), + "expected %s, got %s", expectedBalance, actualBalance, + errSuffix, + ) +} + +func AssertBankBalanceEqualWithDescription( + t *testing.T, + deps TestDeps, + denom string, + account gethcommon.Address, + expectedBalance *big.Int, + description string, +) { + bech32Addr := eth.EthAddrToNibiruAddr(account) + actualBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, bech32Addr, denom).Amount.BigInt() + var errSuffix string + if description == "" { + errSuffix = description + } else { + errSuffix = ": " + description + } + assert.Equalf(t, expectedBalance.String(), actualBalance.String(), + "expected %s, got %s", expectedBalance, actualBalance, errSuffix) +} diff --git a/x/evm/evmtest/eth_test.go b/x/evm/evmtest/eth_test.go index 612beb05d..1d5feee47 100644 --- a/x/evm/evmtest/eth_test.go +++ b/x/evm/evmtest/eth_test.go @@ -36,11 +36,10 @@ func (s *Suite) TestSampleFns() { func (s *Suite) TestERC20Helpers() { deps := evmtest.NewTestDeps() funtoken := evmtest.CreateFunTokenForBankCoin(&deps, "token", &s.Suite) - - evmtest.AssertERC20BalanceEqual( - s.T(), deps, - funtoken.Erc20Addr.Address, - deps.Sender.EthAddr, - big.NewInt(0), - ) + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: deps.Sender.EthAddr, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + }.Assert(s.T(), deps) } diff --git a/x/evm/evmtest/smart_contract_test.go b/x/evm/evmtest/smart_contract_test.go index d5ca3434a..a78dbcf8e 100644 --- a/x/evm/evmtest/smart_contract_test.go +++ b/x/evm/evmtest/smart_contract_test.go @@ -17,7 +17,7 @@ func (s *Suite) TestCreateContractTxMsg() { EthAcc: ethAcc, EthChainIDInt: deps.EvmKeeper.EthChainID(deps.Ctx), GasPrice: big.NewInt(1), - Nonce: deps.StateDB().GetNonce(ethAcc.EthAddr), + Nonce: deps.NewStateDB().GetNonce(ethAcc.EthAddr), } ethTxMsg, err := evmtest.CreateContractMsgEthereumTx(args) @@ -33,7 +33,7 @@ func (s *Suite) TestExecuteContractTxMsg() { EthAcc: ethAcc, EthChainIDInt: deps.EvmKeeper.EthChainID(deps.Ctx), GasPrice: big.NewInt(1), - Nonce: deps.StateDB().GetNonce(ethAcc.EthAddr), + Nonce: deps.NewStateDB().GetNonce(ethAcc.EthAddr), ContractAddress: &contractAddress, Data: nil, } diff --git a/x/evm/evmtest/test_deps.go b/x/evm/evmtest/test_deps.go index 44fb34c31..6d2e830af 100644 --- a/x/evm/evmtest/test_deps.go +++ b/x/evm/evmtest/test_deps.go @@ -22,7 +22,7 @@ type TestDeps struct { App *app.NibiruApp Ctx sdk.Context EncCfg codec.EncodingConfig - EvmKeeper keeper.Keeper + EvmKeeper *keeper.Keeper GenState *evm.GenesisState Sender EthPrivKeyAcc } @@ -45,7 +45,7 @@ func NewTestDeps() TestDeps { } } -func (deps TestDeps) StateDB() *statedb.StateDB { +func (deps TestDeps) NewStateDB() *statedb.StateDB { return deps.EvmKeeper.NewStateDB( deps.Ctx, statedb.NewEmptyTxConfig( diff --git a/x/evm/evmtest/tx.go b/x/evm/evmtest/tx.go index 6b876f16d..25bba83f6 100644 --- a/x/evm/evmtest/tx.go +++ b/x/evm/evmtest/tx.go @@ -7,9 +7,8 @@ import ( "math/big" "testing" - sdkmath "cosmossdk.io/math" - "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -28,7 +27,7 @@ import ( // ExecuteNibiTransfer executes nibi transfer func ExecuteNibiTransfer(deps *TestDeps, t *testing.T) *evm.MsgEthereumTx { - nonce := deps.StateDB().GetNonce(deps.Sender.EthAddr) + nonce := deps.NewStateDB().GetNonce(deps.Sender.EthAddr) recipient := NewEthPrivAcc().EthAddr txArgs := evm.JsonTxArgs{ @@ -67,7 +66,7 @@ func DeployContract( } bytecodeForCall := append(contract.Bytecode, packedArgs...) - nonce := deps.StateDB().GetNonce(deps.Sender.EthAddr) + nonce := deps.NewStateDB().GetNonce(deps.Sender.EthAddr) ethTxMsg, gethSigner, krSigner, err := GenerateEthTxMsgAndSigner( evm.JsonTxArgs{ Nonce: (*hexutil.Uint64)(&nonce), @@ -124,7 +123,7 @@ func DeployAndExecuteERC20Transfer( "transfer", NewEthPrivAcc().EthAddr, new(big.Int).SetUint64(1000), ) require.NoError(t, err) - nonce = deps.StateDB().GetNonce(deps.Sender.EthAddr) + nonce = deps.NewStateDB().GetNonce(deps.Sender.EthAddr) txArgs := evm.JsonTxArgs{ From: &deps.Sender.EthAddr, To: &contractAddr, @@ -149,7 +148,7 @@ func CallContractTx( input []byte, sender EthPrivKeyAcc, ) (ethTxMsg *evm.MsgEthereumTx, resp *evm.MsgEthereumTxResponse, err error) { - nonce := deps.StateDB().GetNonce(sender.EthAddr) + nonce := deps.NewStateDB().GetNonce(sender.EthAddr) ethTxMsg, gethSigner, krSigner, err := GenerateEthTxMsgAndSigner(evm.JsonTxArgs{ From: &sender.EthAddr, To: &contractAddr, @@ -171,6 +170,8 @@ func CallContractTx( return ethTxMsg, resp, err } +var DefaultEthCallGasLimit = srvconfig.DefaultEthCallGasLimit + // GenerateEthTxMsgAndSigner estimates gas, sets gas limit and returns signer for // the tx. // @@ -220,7 +221,7 @@ func TransferWei( deps, gethcore.LegacyTxType, innerTxData, - deps.StateDB().GetNonce(ethAcc.EthAddr), + deps.NewStateDB().GetNonce(ethAcc.EthAddr), &to, amountWei, gethparams.TxGas, diff --git a/x/evm/keeper/bank_extension.go b/x/evm/keeper/bank_extension.go new file mode 100644 index 000000000..da5221cbb --- /dev/null +++ b/x/evm/keeper/bank_extension.go @@ -0,0 +1,155 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + + "github.com/NibiruChain/nibiru/v2/eth" + "github.com/NibiruChain/nibiru/v2/x/evm" + "github.com/NibiruChain/nibiru/v2/x/evm/statedb" +) + +var ( + _ bankkeeper.Keeper = &NibiruBankKeeper{} + _ bankkeeper.SendKeeper = &NibiruBankKeeper{} +) + +type NibiruBankKeeper struct { + bankkeeper.BaseKeeper + StateDB *statedb.StateDB +} + +func (evmKeeper *Keeper) NewStateDB( + ctx sdk.Context, txConfig statedb.TxConfig, +) *statedb.StateDB { + stateDB := statedb.New(ctx, evmKeeper, txConfig) + evmKeeper.Bank.StateDB = stateDB + return stateDB +} + +func (bk NibiruBankKeeper) MintCoins( + ctx sdk.Context, + moduleName string, + coins sdk.Coins, +) error { + // Use the embedded function from [bankkeeper.Keeper] + if err := bk.BaseKeeper.MintCoins(ctx, moduleName, coins); err != nil { + return err + } + if findEtherBalanceChangeFromCoins(coins) { + moduleBech32Addr := auth.NewModuleAddress(moduleName) + bk.SyncStateDBWithAccount(ctx, moduleBech32Addr) + } + return nil +} + +func (bk NibiruBankKeeper) BurnCoins( + ctx sdk.Context, + moduleName string, + coins sdk.Coins, +) error { + // Use the embedded function from [bankkeeper.Keeper] + if err := bk.BaseKeeper.BurnCoins(ctx, moduleName, coins); err != nil { + return err + } + if findEtherBalanceChangeFromCoins(coins) { + moduleBech32Addr := auth.NewModuleAddress(moduleName) + bk.SyncStateDBWithAccount(ctx, moduleBech32Addr) + } + return nil +} + +func (bk NibiruBankKeeper) SendCoins( + ctx sdk.Context, + fromAddr sdk.AccAddress, + toAddr sdk.AccAddress, + coins sdk.Coins, +) error { + // Use the embedded function from [bankkeeper.Keeper] + if err := bk.BaseKeeper.SendCoins(ctx, fromAddr, toAddr, coins); err != nil { + return err + } + if findEtherBalanceChangeFromCoins(coins) { + bk.SyncStateDBWithAccount(ctx, fromAddr) + bk.SyncStateDBWithAccount(ctx, toAddr) + } + return nil +} + +func (bk *NibiruBankKeeper) SyncStateDBWithAccount( + ctx sdk.Context, acc sdk.AccAddress, +) { + // If there's no StateDB set, it means we're not in an EthereumTx. + if bk.StateDB == nil { + return + } + balanceWei := evm.NativeToWei( + bk.GetBalance(ctx, acc, evm.EVMBankDenom).Amount.BigInt(), + ) + bk.StateDB.SetBalanceWei(eth.NibiruAddrToEthAddr(acc), balanceWei) +} + +func findEtherBalanceChangeFromCoins(coins sdk.Coins) (found bool) { + for _, c := range coins { + if c.Denom == evm.EVMBankDenom { + return true + } + } + return false +} + +func (bk NibiruBankKeeper) SendCoinsFromAccountToModule( + ctx sdk.Context, + senderAddr sdk.AccAddress, + recipientModule string, + coins sdk.Coins, +) error { + // Use the embedded function from [bankkeeper.Keeper] + if err := bk.BaseKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, coins); err != nil { + return err + } + if findEtherBalanceChangeFromCoins(coins) { + bk.SyncStateDBWithAccount(ctx, senderAddr) + moduleBech32Addr := auth.NewModuleAddress(recipientModule) + bk.SyncStateDBWithAccount(ctx, moduleBech32Addr) + } + return nil +} + +func (bk NibiruBankKeeper) SendCoinsFromModuleToAccount( + ctx sdk.Context, + senderModule string, + recipientAddr sdk.AccAddress, + coins sdk.Coins, +) error { + // Use the embedded function from [bankkeeper.Keeper] + if err := bk.BaseKeeper.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, coins); err != nil { + return err + } + if findEtherBalanceChangeFromCoins(coins) { + moduleBech32Addr := auth.NewModuleAddress(senderModule) + bk.SyncStateDBWithAccount(ctx, moduleBech32Addr) + bk.SyncStateDBWithAccount(ctx, recipientAddr) + } + return nil +} + +func (bk NibiruBankKeeper) SendCoinsFromModuleToModule( + ctx sdk.Context, + senderModule string, + recipientModule string, + coins sdk.Coins, +) error { + // Use the embedded function from [bankkeeper.Keeper] + if err := bk.BaseKeeper.SendCoinsFromModuleToModule(ctx, senderModule, recipientModule, coins); err != nil { + return err + } + if findEtherBalanceChangeFromCoins(coins) { + senderBech32Addr := auth.NewModuleAddress(senderModule) + recipientBech32Addr := auth.NewModuleAddress(recipientModule) + bk.SyncStateDBWithAccount(ctx, senderBech32Addr) + bk.SyncStateDBWithAccount(ctx, recipientBech32Addr) + } + return nil +} diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go index 06d2e5ab3..79c189f1e 100644 --- a/x/evm/keeper/erc20.go +++ b/x/evm/keeper/erc20.go @@ -180,7 +180,9 @@ func (k Keeper) CallContract( if err != nil { return nil, fmt.Errorf("failed to pack ABI args: %w", err) } - evmResp, _, err = k.CallContractWithInput(ctx, fromAcc, contract, commit, contractInput) + evmResp, _, err = k.CallContractWithInput( + ctx, fromAcc, contract, commit, contractInput, + ) return evmResp, err } diff --git a/x/evm/keeper/funtoken_from_coin.go b/x/evm/keeper/funtoken_from_coin.go index 6f0f2efd0..8075107c6 100644 --- a/x/evm/keeper/funtoken_from_coin.go +++ b/x/evm/keeper/funtoken_from_coin.go @@ -23,7 +23,7 @@ func (k *Keeper) createFunTokenFromCoin( } // 2 | Check for denom metadata in bank state - bankMetadata, isFound := k.bankKeeper.GetDenomMetaData(ctx, bankDenom) + bankMetadata, isFound := k.Bank.GetDenomMetaData(ctx, bankDenom) if !isFound { return nil, fmt.Errorf("bank coin denom should have bank metadata for denom \"%s\"", bankDenom) } diff --git a/x/evm/keeper/funtoken_from_coin_test.go b/x/evm/keeper/funtoken_from_coin_test.go index 3b4b17f7a..f69143772 100644 --- a/x/evm/keeper/funtoken_from_coin_test.go +++ b/x/evm/keeper/funtoken_from_coin_test.go @@ -25,7 +25,7 @@ func (s *FunTokenFromCoinSuite) TestCreateFunTokenFromCoin() { deps := evmtest.NewTestDeps() // Compute contract address. FindERC20 should fail - nonce := deps.StateDB().GetNonce(deps.Sender.EthAddr) + nonce := deps.NewStateDB().GetNonce(deps.Sender.EthAddr) contractAddress := crypto.CreateAddress(deps.Sender.EthAddr, nonce) metadata, err := deps.EvmKeeper.FindERC20Metadata(deps.Ctx, contractAddress) s.Require().Error(err) @@ -172,7 +172,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { bankDenom := evm.EVMBankDenom // Initial setup - funTokenErc20Addr := s.fundAndCreateFunToken(deps, 100) + funToken := s.fundAndCreateFunToken(deps, 100) s.T().Log("Convert bank coin to erc-20") _, err := deps.EvmKeeper.ConvertCoinToEvm( @@ -193,7 +193,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { deps.Ctx, &evm.EventConvertCoinToEvm{ Sender: deps.Sender.NibiruAddr.String(), - Erc20ContractAddress: funTokenErc20Addr.String(), + Erc20ContractAddress: funToken.Erc20Addr.String(), ToEthAddr: alice.EthAddr.String(), BankCoin: sdk.NewCoin(bankDenom, sdk.NewInt(10)), }, @@ -208,7 +208,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { s.Require().Equal(sdk.NewInt(90), senderBalance.Amount) // Check 3: erc-20 balance - balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, alice.EthAddr, deps.Ctx) + balance, err := deps.EvmKeeper.ERC20().BalanceOf(funToken.Erc20Addr.Address, alice.EthAddr, deps.Ctx) s.Require().NoError(err) s.Require().Zero(balance.Cmp(big.NewInt(10))) @@ -233,7 +233,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { &precompile.PrecompileAddr_FunToken, true, "bankSend", - funTokenErc20Addr.Address, + funToken.Erc20Addr.Address, big.NewInt(10), deps.Sender.NibiruAddr.String(), ) @@ -248,7 +248,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { s.Require().Equal(sdk.NewInt(100), senderBalance.Amount) // Check 3: erc-20 balance - balance, err = deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, alice.EthAddr, deps.Ctx) + balance, err = deps.EvmKeeper.ERC20().BalanceOf(funToken.Erc20Addr.Address, alice.EthAddr, deps.Ctx) s.Require().NoError(err) s.Require().Equal("0", balance.String()) @@ -260,7 +260,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { &precompile.PrecompileAddr_FunToken, true, "bankSend", - funTokenErc20Addr.Address, + funToken.Erc20Addr.Address, big.NewInt(10), deps.Sender.NibiruAddr.String(), ) @@ -286,13 +286,14 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() { bankDenom := evm.EVMBankDenom // Initial setup - funTokenErc20Addr := s.fundAndCreateFunToken(deps, 10e6) + sendAmt := big.NewInt(10) + funtoken := s.fundAndCreateFunToken(deps, sendAmt.Int64()) s.T().Log("Deploy Test Contract") deployResp, err := evmtest.DeployContract( &deps, embeds.SmartContract_TestNativeSendThenPrecompileSendJson, - funTokenErc20Addr.Address, + funtoken.Erc20Addr.Address, ) s.Require().NoError(err) @@ -304,7 +305,13 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() { deps.App.BankKeeper, deps.Ctx, testContractNibiAddr, - sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(10e6)))), + sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewIntFromBigInt(sendAmt)))), + ) + evmtest.AssertBankBalanceEqual( + s.T(), deps, bankDenom, testContractAddr, sendAmt, + ) + evmtest.AssertBankBalanceEqual( + s.T(), deps, bankDenom, evm.EVM_MODULE_ADDRESS, big.NewInt(0), ) s.T().Log("Convert bank coin to erc-20: give test contract 10 WNIBI (erc20)") @@ -312,52 +319,72 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() { sdk.WrapSDKContext(deps.Ctx), &evm.MsgConvertCoinToEvm{ Sender: deps.Sender.NibiruAddr.String(), - BankCoin: sdk.NewCoin(bankDenom, sdk.NewInt(10e6)), + BankCoin: sdk.NewCoin(bankDenom, sdk.NewIntFromBigInt(sendAmt)), ToEthAddr: eth.EIP55Addr{Address: testContractAddr}, }, ) s.Require().NoError(err) + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: testContractAddr, + BalanceBank: sendAmt, + BalanceERC20: sendAmt, + }.Assert(s.T(), deps) + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: evm.EVM_MODULE_ADDRESS, + BalanceBank: sendAmt, + BalanceERC20: big.NewInt(0), + }.Assert(s.T(), deps) // Alice hex and Alice bech32 is the same address in different representation, // so funds are expected to be available in Alice's bank wallet alice := evmtest.NewEthPrivAcc() + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: alice.EthAddr, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + }.Assert(s.T(), deps) s.T().Log("call test contract") - _, err = deps.EvmKeeper.CallContract( + evmResp, err := deps.EvmKeeper.CallContract( deps.Ctx, embeds.SmartContract_TestNativeSendThenPrecompileSendJson.ABI, deps.Sender.EthAddr, &testContractAddr, true, "nativeSendThenPrecompileSend", - alice.EthAddr, - evm.NativeToWei(big.NewInt(10e6)), // for native evm send: 18 decimals - alice.NibiruAddr.String(), - big.NewInt(10e6), // for precompile bankSend: 6 decimals + []any{ + alice.EthAddr, + evm.NativeToWei(sendAmt), // native send uses wei units + alice.NibiruAddr.String(), + sendAmt, // amount for precompile bankSend + }..., ) s.Require().NoError(err) - - // Check 1: Alice has 20 NIBI in bank - aliceBankBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, alice.NibiruAddr, bankDenom) - s.Require().Equal(sdk.NewInt(20e6), aliceBankBalance.Amount) - - // Check 2: Alice has 0 WNIBI on ERC20 - aliceERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, alice.EthAddr, deps.Ctx) - s.Require().NoError(err) - s.Require().Zero(big.NewInt(0).Cmp(aliceERC20Balance)) - - // Check 3: test contract has 0 NIBI in bank - testContractBankBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, testContractNibiAddr, bankDenom) - s.Require().Equal(sdk.NewInt(0), testContractBankBalance.Amount) - - // Check 4: test contract has 0 WNIBI on ERC20 - testContractERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, testContractAddr, deps.Ctx) - s.Require().NoError(err) - s.Require().Zero(big.NewInt(0).Cmp(testContractERC20Balance)) - - // Check 5: module balance has 0 NIBI escrowed - moduleBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, authtypes.NewModuleAddress(evm.ModuleName), bankDenom) - s.Require().Equal(sdk.NewInt(0), moduleBalance.Amount) + s.Empty(evmResp.VmError) + + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: alice.EthAddr, + BalanceBank: new(big.Int).Mul(sendAmt, big.NewInt(2)), + BalanceERC20: big.NewInt(0), + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: testContractAddr, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funtoken, + Account: evm.EVM_MODULE_ADDRESS, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + }.Assert(s.T(), deps) } // TestERC20TransferThenPrecompileSend @@ -379,13 +406,13 @@ func (s *FunTokenFromCoinSuite) TestERC20TransferThenPrecompileSend() { bankDenom := evm.EVMBankDenom // Initial setup - funTokenErc20Addr := s.fundAndCreateFunToken(deps, 10e6) + funToken := s.fundAndCreateFunToken(deps, 10e6) s.T().Log("Deploy Test Contract") deployResp, err := evmtest.DeployContract( &deps, embeds.SmartContract_TestERC20TransferThenPrecompileSend, - funTokenErc20Addr.Address, + funToken.Erc20Addr.Address, ) s.Require().NoError(err) @@ -425,12 +452,12 @@ func (s *FunTokenFromCoinSuite) TestERC20TransferThenPrecompileSend() { s.Require().Equal(sdk.NewInt(9e6), aliceBankBalance.Amount) // Check 2: Alice has 1 WNIBI on ERC20 - aliceERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, alice.EthAddr, deps.Ctx) + aliceERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funToken.Erc20Addr.Address, alice.EthAddr, deps.Ctx) s.Require().NoError(err) s.Require().Zero(big.NewInt(1e6).Cmp(aliceERC20Balance)) // Check 3: test contract has 0 WNIBI on ERC20 - testContractERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funTokenErc20Addr.Address, testContractAddr, deps.Ctx) + testContractERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funToken.Erc20Addr.Address, testContractAddr, deps.Ctx) s.Require().NoError(err) s.Require().Zero(big.NewInt(0).Cmp(testContractERC20Balance)) @@ -440,7 +467,7 @@ func (s *FunTokenFromCoinSuite) TestERC20TransferThenPrecompileSend() { } // fundAndCreateFunToken creates initial setup for tests -func (s *FunTokenFromCoinSuite) fundAndCreateFunToken(deps evmtest.TestDeps, unibiAmount int64) eth.EIP55Addr { +func (s *FunTokenFromCoinSuite) fundAndCreateFunToken(deps evmtest.TestDeps, unibiAmount int64) evm.FunToken { bankDenom := evm.EVMBankDenom s.T().Log("Setup: Create a coin in the bank state") @@ -449,12 +476,15 @@ func (s *FunTokenFromCoinSuite) fundAndCreateFunToken(deps evmtest.TestDeps, uni { Denom: bankDenom, Exponent: 0, - Aliases: nil, + }, + { + Denom: "NIBI", + Exponent: 6, }, }, Base: bankDenom, - Display: bankDenom, - Name: bankDenom, + Display: "NIBI", + Name: "NIBI", Symbol: "NIBI", }) @@ -475,7 +505,16 @@ func (s *FunTokenFromCoinSuite) fundAndCreateFunToken(deps evmtest.TestDeps, uni }, ) s.Require().NoError(err) - return createFunTokenResp.FuntokenMapping.Erc20Addr + + erc20Decimals, err := deps.EvmKeeper.LoadERC20Decimals( + deps.Ctx, + embeds.SmartContract_ERC20Minter.ABI, + createFunTokenResp.FuntokenMapping.Erc20Addr.Address, + ) + s.Require().NoError(err) + s.Require().Equal(erc20Decimals, uint8(6)) + + return createFunTokenResp.FuntokenMapping } type FunTokenFromCoinSuite struct { diff --git a/x/evm/keeper/funtoken_from_erc20.go b/x/evm/keeper/funtoken_from_erc20.go index e10f0cca8..f1fa3b0b2 100644 --- a/x/evm/keeper/funtoken_from_erc20.go +++ b/x/evm/keeper/funtoken_from_erc20.go @@ -122,7 +122,7 @@ func (k *Keeper) createFunTokenFromERC20( bankDenom := fmt.Sprintf("erc20/%s", erc20.String()) // 3 | Coin already registered with FunToken? - _, isFound := k.bankKeeper.GetDenomMetaData(ctx, bankDenom) + _, isFound := k.Bank.GetDenomMetaData(ctx, bankDenom) if isFound { return funtoken, fmt.Errorf("bank coin denom already registered with denom \"%s\"", bankDenom) } @@ -137,7 +137,7 @@ func (k *Keeper) createFunTokenFromERC20( if err != nil { return funtoken, fmt.Errorf("failed to validate bank metadata: %w", err) } - k.bankKeeper.SetDenomMetaData(ctx, bankMetadata) + k.Bank.SetDenomMetaData(ctx, bankMetadata) // 5 | Officially create the funtoken mapping funtoken = &evm.FunToken{ diff --git a/x/evm/keeper/funtoken_from_erc20_test.go b/x/evm/keeper/funtoken_from_erc20_test.go index eb209f7ca..53db98b31 100644 --- a/x/evm/keeper/funtoken_from_erc20_test.go +++ b/x/evm/keeper/funtoken_from_erc20_test.go @@ -25,7 +25,7 @@ func (s *FunTokenFromErc20Suite) TestCreateFunTokenFromERC20() { deps := evmtest.NewTestDeps() // assert that the ERC20 contract is not deployed - expectedERC20Addr := crypto.CreateAddress(deps.Sender.EthAddr, deps.StateDB().GetNonce(deps.Sender.EthAddr)) + expectedERC20Addr := crypto.CreateAddress(deps.Sender.EthAddr, deps.NewStateDB().GetNonce(deps.Sender.EthAddr)) _, err := deps.EvmKeeper.FindERC20Metadata(deps.Ctx, expectedERC20Addr) s.Error(err) diff --git a/x/evm/keeper/gas_fees.go b/x/evm/keeper/gas_fees.go index 01c72034c..c373b06ac 100644 --- a/x/evm/keeper/gas_fees.go +++ b/x/evm/keeper/gas_fees.go @@ -60,7 +60,7 @@ func (k *Keeper) RefundGas( // Refund to sender from the fee collector module account. This account // manages the collection of gas fees. - err := k.bankKeeper.SendCoinsFromModuleToAccount( + err := k.Bank.SendCoinsFromModuleToAccount( ctx, authtypes.FeeCollectorName, // sender msgFrom.Bytes(), // recipient @@ -136,7 +136,7 @@ func (k *Keeper) DeductTxCostsFromUserBalance( } // deduct the full gas cost from the user balance - if err := authante.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil { + if err := authante.DeductFees(k.Bank, ctx, signerAcc, fees); err != nil { return errors.Wrapf(err, "failed to deduct full gas cost %s from the user %s balance", fees, from) } diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go index b16bea40c..b1d8e0515 100644 --- a/x/evm/keeper/grpc_query_test.go +++ b/x/evm/keeper/grpc_query_test.go @@ -330,7 +330,7 @@ func (s *Suite) TestQueryStorage() { Key: storageKey.String(), } - stateDB := deps.StateDB() + stateDB := deps.NewStateDB() storageValue := gethcommon.BytesToHash([]byte("value")) stateDB.SetState(addr, storageKey, storageValue) @@ -404,7 +404,7 @@ func (s *Suite) TestQueryCode() { Address: addr.Hex(), } - stateDB := deps.StateDB() + stateDB := deps.NewStateDB() contractBytecode := []byte("bytecode") stateDB.SetCode(addr, contractBytecode) s.Require().NoError(stateDB.Commit()) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index dd31229fd..dd757ced9 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/NibiruChain/nibiru/v2/app/appconst" @@ -41,7 +40,7 @@ type Keeper struct { // this should be the x/gov module account. authority sdk.AccAddress - bankKeeper bankkeeper.Keeper + Bank *NibiruBankKeeper accountKeeper evm.AccountKeeper stakingKeeper evm.StakingKeeper @@ -64,7 +63,7 @@ func NewKeeper( storeKey, transientKey storetypes.StoreKey, authority sdk.AccAddress, accKeeper evm.AccountKeeper, - bankKeeper bankkeeper.Keeper, + bankKeeper *NibiruBankKeeper, stakingKeeper evm.StakingKeeper, tracer string, ) Keeper { @@ -80,7 +79,7 @@ func NewKeeper( EvmState: NewEvmState(cdc, storeKey, transientKey), FunTokens: NewFunTokenState(cdc, storeKey), accountKeeper: accKeeper, - bankKeeper: bankKeeper, + Bank: bankKeeper, stakingKeeper: stakingKeeper, tracer: tracer, } @@ -91,7 +90,7 @@ func NewKeeper( // tokens for EVM execution in EVM denom units. func (k *Keeper) GetEvmGasBalance(ctx sdk.Context, addr gethcommon.Address) (balance *big.Int) { nibiruAddr := sdk.AccAddress(addr.Bytes()) - return k.bankKeeper.GetBalance(ctx, nibiruAddr, evm.EVMBankDenom).Amount.BigInt() + return k.Bank.GetBalance(ctx, nibiruAddr, evm.EVMBankDenom).Amount.BigInt() } func (k Keeper) EthChainID(ctx sdk.Context) *big.Int { diff --git a/x/evm/keeper/msg_ethereum_tx_test.go b/x/evm/keeper/msg_ethereum_tx_test.go index 0c2de7a39..4d9f16345 100644 --- a/x/evm/keeper/msg_ethereum_tx_test.go +++ b/x/evm/keeper/msg_ethereum_tx_test.go @@ -47,7 +47,7 @@ func (s *Suite) TestMsgEthereumTx_CreateContract() { EthAcc: ethAcc, EthChainIDInt: deps.EvmKeeper.EthChainID(deps.Ctx), GasPrice: big.NewInt(1), - Nonce: deps.StateDB().GetNonce(ethAcc.EthAddr), + Nonce: deps.NewStateDB().GetNonce(ethAcc.EthAddr), GasLimit: gasLimit, } ethTxMsg, err := evmtest.CreateContractMsgEthereumTx(args) @@ -87,7 +87,7 @@ func (s *Suite) TestMsgEthereumTx_CreateContract() { EthAcc: ethAcc, EthChainIDInt: deps.EvmKeeper.EthChainID(deps.Ctx), GasPrice: big.NewInt(1), - Nonce: deps.StateDB().GetNonce(ethAcc.EthAddr), + Nonce: deps.NewStateDB().GetNonce(ethAcc.EthAddr), } ethTxMsg, err := evmtest.CreateContractMsgEthereumTx(args) s.NoError(err) @@ -139,7 +139,7 @@ func (s *Suite) TestMsgEthereumTx_ExecuteContract() { EthAcc: ethAcc, EthChainIDInt: deps.EvmKeeper.EthChainID(deps.Ctx), GasPrice: big.NewInt(1), - Nonce: deps.StateDB().GetNonce(ethAcc.EthAddr), + Nonce: deps.NewStateDB().GetNonce(ethAcc.EthAddr), GasLimit: gasLimit, ContractAddress: &contractAddr, Data: input, @@ -205,7 +205,7 @@ func (s *Suite) TestMsgEthereumTx_SimpleTransfer() { &deps, tc.txType, innerTxData, - deps.StateDB().GetNonce(ethAcc.EthAddr), + deps.NewStateDB().GetNonce(ethAcc.EthAddr), &to, big.NewInt(fundedAmount), gethparams.TxGas, diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index ec13c0709..dbc1e8f74 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -202,9 +202,10 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { } } -// ApplyEvmMsg computes the new state by applying the given message against the existing state. -// If the message fails, the VM execution error with the reason will be returned to the client -// and the transaction won't be committed to the store. +// ApplyEvmMsg computes the new state by applying the given message against the +// existing state. If the message fails, the VM execution error with the reason +// will be returned to the client and the transaction won't be committed to the +// store. // // # Reverted state // @@ -455,11 +456,11 @@ func (k Keeper) deductCreateFunTokenFee(ctx sdk.Context, msg *evm.MsgCreateFunTo fee := k.FeeForCreateFunToken(ctx) from := sdk.MustAccAddressFromBech32(msg.Sender) // validation in msg.ValidateBasic - if err := k.bankKeeper.SendCoinsFromAccountToModule( + if err := k.Bank.SendCoinsFromAccountToModule( ctx, from, evm.ModuleName, fee); err != nil { return fmt.Errorf("unable to pay the \"create_fun_token_fee\": %w", err) } - if err := k.bankKeeper.BurnCoins(ctx, evm.ModuleName, fee); err != nil { + if err := k.Bank.BurnCoins(ctx, evm.ModuleName, fee); err != nil { return fmt.Errorf("failed to burn the \"create_fun_token_fee\" after payment: %w", err) } return nil @@ -511,15 +512,14 @@ func (k Keeper) convertCoinToEvmBornCoin( coin sdk.Coin, funTokenMapping evm.FunToken, ) (*evm.MsgConvertCoinToEvmResponse, error) { - // Step 1: Send Bank Coins to the EVM module - err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, evm.ModuleName, sdk.NewCoins(coin)) + // 1 | Send Bank Coins to the EVM module + err := k.Bank.SendCoinsFromAccountToModule(ctx, sender, evm.ModuleName, sdk.NewCoins(coin)) if err != nil { return nil, errors.Wrap(err, "failed to send coins to module account") } + // 2 | Mint ERC20 tokens to the recipient erc20Addr := funTokenMapping.Erc20Addr.Address - - // Step 2: Mint ERC20 tokens to the recipient evmResp, err := k.CallContract( ctx, embeds.SmartContract_ERC20Minter.ABI, @@ -560,7 +560,7 @@ func (k Keeper) convertCoinToEvmBornERC20( ) (*evm.MsgConvertCoinToEvmResponse, error) { erc20Addr := funTokenMapping.Erc20Addr.Address // 1 | Caller transfers Bank Coins to be converted to ERC20 tokens. - if err := k.bankKeeper.SendCoinsFromAccountToModule( + if err := k.Bank.SendCoinsFromAccountToModule( ctx, sender, evm.ModuleName, @@ -594,7 +594,7 @@ func (k Keeper) convertCoinToEvmBornERC20( // on the sum of the FunToken's bank and ERC20 supply, we burn the coins here // in the BC → ERC20 conversion. burnCoin := sdk.NewCoin(coin.Denom, sdk.NewIntFromBigInt(actualSentAmount)) - err = k.bankKeeper.BurnCoins(ctx, evm.ModuleName, sdk.NewCoins(burnCoin)) + err = k.Bank.BurnCoins(ctx, evm.ModuleName, sdk.NewCoins(burnCoin)) if err != nil { return nil, errors.Wrap(err, "failed to burn coins") } diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 7aff8c02d..b85a595a5 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -17,13 +17,6 @@ import ( var _ statedb.Keeper = &Keeper{} -func (k *Keeper) NewStateDB( - ctx sdk.Context, - txConfig statedb.TxConfig, -) *statedb.StateDB { - return statedb.New(ctx, k, txConfig) -} - // ---------------------------------------------------------------------------- // StateDB Keeper implementation // ---------------------------------------------------------------------------- @@ -79,27 +72,28 @@ func (k *Keeper) ForEachStorage( func (k *Keeper) SetAccBalance( ctx sdk.Context, addr gethcommon.Address, amountEvmDenom *big.Int, ) error { - nativeAddr := sdk.AccAddress(addr.Bytes()) - balance := k.bankKeeper.GetBalance(ctx, nativeAddr, evm.EVMBankDenom).Amount.BigInt() + addrBech32 := eth.EthAddrToNibiruAddr(addr) + balance := k.Bank.GetBalance(ctx, addrBech32, evm.EVMBankDenom).Amount.BigInt() delta := new(big.Int).Sub(amountEvmDenom, balance) + bk := k.Bank.BaseKeeper switch delta.Sign() { case 1: // mint coins := sdk.NewCoins(sdk.NewCoin(evm.EVMBankDenom, sdkmath.NewIntFromBigInt(delta))) - if err := k.bankKeeper.MintCoins(ctx, evm.ModuleName, coins); err != nil { + if err := bk.MintCoins(ctx, evm.ModuleName, coins); err != nil { return err } - if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, evm.ModuleName, nativeAddr, coins); err != nil { + if err := bk.SendCoinsFromModuleToAccount(ctx, evm.ModuleName, addrBech32, coins); err != nil { return err } case -1: // burn coins := sdk.NewCoins(sdk.NewCoin(evm.EVMBankDenom, sdkmath.NewIntFromBigInt(new(big.Int).Neg(delta)))) - if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, nativeAddr, evm.ModuleName, coins); err != nil { + if err := bk.SendCoinsFromAccountToModule(ctx, addrBech32, evm.ModuleName, coins); err != nil { return err } - if err := k.bankKeeper.BurnCoins(ctx, evm.ModuleName, coins); err != nil { + if err := bk.BurnCoins(ctx, evm.ModuleName, coins); err != nil { return err } default: diff --git a/x/evm/keeper/statedb_test.go b/x/evm/keeper/statedb_test.go index a918039a8..a9fd8cede 100644 --- a/x/evm/keeper/statedb_test.go +++ b/x/evm/keeper/statedb_test.go @@ -21,7 +21,7 @@ import ( func (s *Suite) TestStateDBBalance() { deps := evmtest.NewTestDeps() { - db := deps.StateDB() + db := deps.NewStateDB() s.Equal("0", db.GetBalance(deps.Sender.EthAddr).String()) s.T().Log("fund account in unibi. See expected wei amount.") @@ -47,7 +47,7 @@ func (s *Suite) TestStateDBBalance() { { err := evmtest.TransferWei(&deps, to, evm.NativeToWei(big.NewInt(12))) s.Require().NoError(err) - db := deps.StateDB() + db := deps.NewStateDB() s.Equal( "30"+strings.Repeat("0", 12), db.GetBalance(deps.Sender.EthAddr).String(), @@ -80,7 +80,7 @@ func (s *Suite) TestStateDBBalance() { ) s.NoError(err) - db := deps.StateDB() + db := deps.NewStateDB() s.Equal( "3"+strings.Repeat("0", 12), db.GetBalance(to).String(), diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index 1d50d99ab..b1fc0239d 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -6,18 +6,14 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - auth "github.com/cosmos/cosmos-sdk/x/auth/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" gethabi "github.com/ethereum/go-ethereum/accounts/abi" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" "github.com/NibiruChain/nibiru/v2/app/keepers" - "github.com/NibiruChain/nibiru/v2/eth" "github.com/NibiruChain/nibiru/v2/x/evm" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" evmkeeper "github.com/NibiruChain/nibiru/v2/x/evm/keeper" - "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) var _ vm.PrecompiledContract = (*precompileFunToken)(nil) @@ -55,6 +51,7 @@ func (p precompileFunToken) Run( if err != nil { return nil, err } + p.evmKeeper.Bank.StateDB = start.StateDB method := start.Method switch PrecompileMethod(method.Name) { @@ -74,14 +71,12 @@ func (p precompileFunToken) Run( func PrecompileFunToken(keepers keepers.PublicKeepers) vm.PrecompiledContract { return precompileFunToken{ - bankKeeper: keepers.BankKeeper, - evmKeeper: keepers.EvmKeeper, + evmKeeper: keepers.EvmKeeper, } } type precompileFunToken struct { - bankKeeper bankkeeper.Keeper - evmKeeper evmkeeper.Keeper + evmKeeper *evmkeeper.Keeper } // bankSend: Implements "IFunToken.bankSend" @@ -151,7 +146,12 @@ func (p precompileFunToken) bankSend( return } } else { - err = SafeMintCoins(ctx, evm.ModuleName, coinToSend, p.bankKeeper, start.StateDB) + // NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before + // any operation that has the potential to use Bank send methods. This will + // guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are + // recorded if wei (NIBI) is transferred. + p.evmKeeper.Bank.StateDB = start.StateDB + err = p.evmKeeper.Bank.MintCoins(ctx, evm.ModuleName, sdk.NewCoins(coinToSend)) if err != nil { return nil, fmt.Errorf("mint failed for module \"%s\" (%s): contract caller %s: %w", evm.ModuleName, evm.EVM_MODULE_ADDRESS.Hex(), caller.Hex(), err, @@ -160,13 +160,17 @@ func (p precompileFunToken) bankSend( } // Transfer the bank coin - err = SafeSendCoinFromModuleToAccount( + // + // NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before + // any operation that has the potential to use Bank send methods. This will + // guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are + // recorded if wei (NIBI) is transferred. + p.evmKeeper.Bank.StateDB = start.StateDB + err = p.evmKeeper.Bank.SendCoinsFromModuleToAccount( ctx, evm.ModuleName, toAddr, - coinToSend, - p.bankKeeper, - start.StateDB, + sdk.NewCoins(coinToSend), ) if err != nil { return nil, fmt.Errorf("send failed for module \"%s\" (%s): contract caller %s: %w", @@ -179,58 +183,6 @@ func (p precompileFunToken) bankSend( return method.Outputs.Pack(gotAmount) } -func SafeMintCoins( - ctx sdk.Context, - moduleName string, - amt sdk.Coin, - bk bankkeeper.Keeper, - db *statedb.StateDB, -) error { - err := bk.MintCoins(ctx, evm.ModuleName, sdk.NewCoins(amt)) - if err != nil { - return err - } - if amt.Denom == evm.EVMBankDenom { - evmBech32Addr := auth.NewModuleAddress(evm.ModuleName) - balAfter := bk.GetBalance(ctx, evmBech32Addr, amt.Denom).Amount.BigInt() - db.SetBalanceWei( - evm.EVM_MODULE_ADDRESS, - evm.NativeToWei(balAfter), - ) - } - - return nil -} - -func SafeSendCoinFromModuleToAccount( - ctx sdk.Context, - senderModule string, - recipientAddr sdk.AccAddress, - amt sdk.Coin, - bk bankkeeper.Keeper, - db *statedb.StateDB, -) error { - err := bk.SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, sdk.NewCoins(amt)) - if err != nil { - return err - } - if amt.Denom == evm.EVMBankDenom { - evmBech32Addr := auth.NewModuleAddress(evm.ModuleName) - balAfterFrom := bk.GetBalance(ctx, evmBech32Addr, amt.Denom).Amount.BigInt() - db.SetBalanceWei( - evm.EVM_MODULE_ADDRESS, - evm.NativeToWei(balAfterFrom), - ) - - balAfterTo := bk.GetBalance(ctx, recipientAddr, amt.Denom).Amount.BigInt() - db.SetBalanceWei( - eth.NibiruAddrToEthAddr(recipientAddr), - evm.NativeToWei(balAfterTo), - ) - } - return nil -} - func (p precompileFunToken) decomposeBankSendArgs(args []any) ( erc20 gethcommon.Address, amount *big.Int, diff --git a/x/evm/precompile/funtoken_test.go b/x/evm/precompile/funtoken_test.go index fc51a47f5..a17836582 100644 --- a/x/evm/precompile/funtoken_test.go +++ b/x/evm/precompile/funtoken_test.go @@ -120,7 +120,7 @@ func (s *FuntokenSuite) TestHappyPath() { randomAcc := testutil.AccAddress() - s.T().Log("Send using precompile") + s.T().Log("Send NIBI (FunToken) using precompile") amtToSend := int64(420) callArgs := []any{erc20, big.NewInt(amtToSend), randomAcc.String()} input, err := embeds.SmartContract_FunToken.ABI.Pack(string(precompile.FunTokenMethod_BankSend), callArgs...) @@ -134,6 +134,7 @@ func (s *FuntokenSuite) TestHappyPath() { ) s.Require().NoError(err) s.Require().Empty(ethTxResp.VmError) + s.True(deps.App.BankKeeper == deps.App.EvmKeeper.Bank) evmtest.AssertERC20BalanceEqual( s.T(), deps, erc20, deps.Sender.EthAddr, big.NewInt(69_000), @@ -144,6 +145,7 @@ func (s *FuntokenSuite) TestHappyPath() { s.Equal(sdk.NewInt(420).String(), deps.App.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.String(), ) + s.Require().NotNil(deps.EvmKeeper.Bank.StateDB) s.T().Log("Parse the response contract addr and response bytes") var sentAmt *big.Int diff --git a/x/evm/precompile/wasm.go b/x/evm/precompile/wasm.go index cddfc488e..0c7753564 100644 --- a/x/evm/precompile/wasm.go +++ b/x/evm/precompile/wasm.go @@ -8,6 +8,7 @@ import ( "github.com/NibiruChain/nibiru/v2/app/keepers" "github.com/NibiruChain/nibiru/v2/eth" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" + evmkeeper "github.com/NibiruChain/nibiru/v2/x/evm/keeper" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasm "github.com/CosmWasm/wasmd/x/wasm/types" @@ -42,6 +43,11 @@ func (p precompileWasm) Run( return nil, err } + // NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before + // any operation that has the potential to use Bank send methods. This will + // guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are + // recorded if wei (NIBI) is transferred. + p.Bank.StateDB = startResult.StateDB switch PrecompileMethod(startResult.Method.Name) { case WasmMethod_execute: bz, err = p.execute(startResult, contract.CallerAddress, readonly) @@ -66,6 +72,7 @@ func (p precompileWasm) Run( } type precompileWasm struct { + *evmkeeper.Keeper Wasm Wasm } @@ -91,6 +98,7 @@ type Wasm struct { func PrecompileWasm(keepers keepers.PublicKeepers) vm.PrecompiledContract { return precompileWasm{ + Keeper: keepers.EvmKeeper, Wasm: Wasm{ wasmkeeper.NewDefaultPermissionKeeper(keepers.WasmKeeper), keepers.WasmKeeper, diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index 4e93b127a..4c729ef34 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -78,6 +78,10 @@ type StateDB struct { accessList *accessList } +func FromVM(evmObj *vm.EVM) *StateDB { + return evmObj.StateDB.(*StateDB) +} + // New creates a new state from a given trie. func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB { return &StateDB{ diff --git a/x/evm/statedb/statedb_test.go b/x/evm/statedb/statedb_test.go index 7919d3da0..a89444042 100644 --- a/x/evm/statedb/statedb_test.go +++ b/x/evm/statedb/statedb_test.go @@ -82,7 +82,7 @@ func (s *Suite) TestAccount() { s.Require().EqualValues(statedb.NewEmptyAccount(), acct) s.Require().Empty(CollectContractStorage(db)) - db = deps.StateDB() + db = deps.NewStateDB() s.Require().Equal(true, db.Exist(address)) s.Require().Equal(true, db.Empty(address)) s.Require().Equal(big.NewInt(0), db.GetBalance(address)) @@ -104,7 +104,7 @@ func (s *Suite) TestAccount() { s.Require().NoError(db.Commit()) // suicide - db = deps.StateDB() + db = deps.NewStateDB() s.Require().False(db.HasSuicided(address)) s.Require().True(db.Suicide(address)) @@ -119,7 +119,7 @@ func (s *Suite) TestAccount() { s.Require().NoError(db.Commit()) // not accessible from StateDB anymore - db = deps.StateDB() + db = deps.NewStateDB() s.Require().False(db.Exist(address)) s.Require().Empty(CollectContractStorage(db)) }}, @@ -127,7 +127,7 @@ func (s *Suite) TestAccount() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() tc.malleate(&deps, db) }) } @@ -135,7 +135,7 @@ func (s *Suite) TestAccount() { func (s *Suite) TestAccountOverride() { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() // test balance carry over when overwritten amount := big.NewInt(1) @@ -168,7 +168,7 @@ func (s *Suite) TestDBError() { } for _, tc := range testCases { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() tc.malleate(db) s.Require().NoError(db.Commit()) } @@ -201,7 +201,7 @@ func (s *Suite) TestBalance() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() tc.malleate(db) // check dirty state @@ -254,7 +254,7 @@ func (s *Suite) TestState() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() tc.malleate(db) s.Require().NoError(db.Commit()) @@ -264,7 +264,7 @@ func (s *Suite) TestState() { } // check ForEachStorage - db = deps.StateDB() + db = deps.NewStateDB() collected := CollectContractStorage(db) if len(tc.expStates) > 0 { s.Require().Equal(tc.expStates, collected) @@ -297,7 +297,7 @@ func (s *Suite) TestCode() { for _, tc := range testCases { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() tc.malleate(db) // check dirty state @@ -308,7 +308,7 @@ func (s *Suite) TestCode() { s.Require().NoError(db.Commit()) // check again - db = deps.StateDB() + db = deps.NewStateDB() s.Require().Equal(tc.expCode, db.GetCode(address)) s.Require().Equal(len(tc.expCode), db.GetCodeSize(address)) s.Require().Equal(tc.expCodeHash, db.GetCodeHash(address)) @@ -364,7 +364,7 @@ func (s *Suite) TestRevertSnapshot() { deps := evmtest.NewTestDeps() // do some arbitrary changes to the storage - db := deps.StateDB() + db := deps.NewStateDB() db.SetNonce(address, 1) db.AddBalance(address, big.NewInt(100)) db.SetCode(address, []byte("hello world")) @@ -406,7 +406,7 @@ func (s *Suite) TestNestedSnapshot() { value2 := common.BigToHash(big.NewInt(2)) deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() rev1 := db.Snapshot() db.SetState(address, key, value1) @@ -424,7 +424,7 @@ func (s *Suite) TestNestedSnapshot() { func (s *Suite) TestInvalidSnapshotId() { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() s.Require().Panics(func() { db.RevertToSnapshot(1) @@ -499,7 +499,7 @@ func (s *Suite) TestAccessList() { for _, tc := range testCases { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() tc.malleate(db) } } @@ -521,7 +521,7 @@ func (s *Suite) TestLog() { } deps := evmtest.NewTestDeps() - db := statedb.New(deps.Ctx, &deps.App.EvmKeeper, txConfig) + db := statedb.New(deps.Ctx, deps.App.EvmKeeper, txConfig) logData := []byte("hello world") log := &gethcore.Log{ @@ -576,7 +576,7 @@ func (s *Suite) TestRefund() { } for _, tc := range testCases { deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() if !tc.expPanic { tc.malleate(db) s.Require().Equal(tc.expRefund, db.GetRefund()) @@ -595,7 +595,7 @@ func (s *Suite) TestIterateStorage() { value2 := common.BigToHash(big.NewInt(4)) deps := evmtest.NewTestDeps() - db := deps.StateDB() + db := deps.NewStateDB() db.SetState(address, key1, value1) db.SetState(address, key2, value2) From 7b26a2cf2a0c66ecd52b7445bbd3053c69918225 Mon Sep 17 00:00:00 2001 From: Matthias <97468149+matthiasmatt@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:26:44 +0100 Subject: [PATCH 09/12] feat: add new query for dated prices (#2097) * feat: add new query for dated prices * feat: use ctx to get timestamp for query * chore: changelog * lint: remove dead code * field rename to include block --------- Co-authored-by: Unique-Divine --- CHANGELOG.md | 14 +- app/wasmext/stargate_query.go | 1 + proto/nibiru/oracle/v1/query.proto | 26 +- .../contracts/IOracle.sol/IOracle.json | 16 +- x/evm/embeds/contracts/IOracle.sol | 20 +- x/evm/precompile/oracle.go | 4 +- x/evm/precompile/oracle_test.go | 8 +- x/oracle/keeper/keeper.go | 10 + x/oracle/keeper/querier.go | 18 + x/oracle/keeper/querier_test.go | 105 ++++ x/oracle/types/query.pb.go | 467 ++++++++++++++---- x/oracle/types/query.pb.gw.go | 83 ++++ 12 files changed, 663 insertions(+), 109 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 884cc7e67..9467ff398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,11 +50,12 @@ Zenith](https://code4rena.com/zenith) Audit, running from 2024-10-07 until period. This section describes code changes that occured after that audit in preparation for a second audit starting in November 2024. -- [#2074](https://github.com/NibiruChain/nibiru/pull/2074) - fix(evm-keeper): better utilize ERC20 metadata during FunToken creation. The bank metadata for a new FunToken mapping ties a connection between the Bank Coin's `DenomUnit` and the ERC20 contract metadata like the name, decimals, and symbol. This change brings parity between EVM wallets, such as MetaMask, and Interchain wallets like Keplr and Leap. +- [#2068](https://github.com/NibiruChain/nibiru/pull/2068) - feat: enable wasm light clients on IBC (08-wasm) +- [#2074](https://github.com/NibiruChain/nibiru/pull/2074) - fix(evm-keeper): better utilize ERC20 metadata during FunToken creation. The bank metadata for a new FunToken mapping ties a connection between the Bank Coin's `DenomUnit` and the ERC20 contract metadata like the name, decimals, and symbol. This change brings parity between EVM wallets, such as MetaMask, and Interchain wallets like Keplr and Leap. - [#2076](https://github.com/NibiruChain/nibiru/pull/2076) - fix(evm-gas-fees): -Use effective gas price in RefundGas and make sure that units are properly -reflected on all occurences of "base fee" in the codebase. This fixes [#2059](https://github.com/NibiruChain/nibiru/issues/2059) -and the [related comments from @Unique-Divine and @berndartmueller](https://github.com/NibiruChain/nibiru/issues/2059#issuecomment-2408625724). + Use effective gas price in RefundGas and make sure that units are properly + reflected on all occurences of "base fee" in the codebase. This fixes [#2059](https://github.com/NibiruChain/nibiru/issues/2059) + and the [related comments from @Unique-Divine and @berndartmueller](https://github.com/NibiruChain/nibiru/issues/2059#issuecomment-2408625724). - [#2084](https://github.com/NibiruChain/nibiru/pull/2084) - feat(evm-forge): foundry support and template for Nibiru EVM develoment - [#2086](https://github.com/NibiruChain/nibiru/pull/2086) - fix(evm-precomples): Fix state consistency in precompile execution by ensuring proper journaling of @@ -92,11 +93,13 @@ balance changes in wei as journal changes automatically. This guarantees that commits and reversions of the `StateDB` do not misalign with the state of the Bank module. This code change uses the `NibiruBankKeeper` on all modules that depend on x/bank, such as the EVM and Wasm modules. +- [#2097](https://github.com/NibiruChain/nibiru/pull/2097) - feat(evm): Add new query to get dated price from the oracle precompile - [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb tests for race conditions within funtoken precompile -- [#2068](https://github.com/NibiruChain/nibiru/pull/2068) - feat: enable wasm light clients on IBC (08-wasm) +- [#2100](https://github.com/NibiruChain/nibiru/pull/2100) - refactor: cleanup statedb and precompile sections - [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling + #### Nibiru EVM | Before Audit 1 - 2024-10-18 - [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): protos, eth types, and evm module types @@ -175,7 +178,6 @@ tests for race conditions within funtoken precompile - [#2060](https://github.com/NibiruChain/nibiru/pull/2060) - fix(evm-precompiles): add assertNumArgs validation - [#2056](https://github.com/NibiruChain/nibiru/pull/2056) - feat(evm): add oracle precompile - [#2065](https://github.com/NibiruChain/nibiru/pull/2065) - refactor(evm)!: Refactor out dead code from the evm.Params -- [#2100](https://github.com/NibiruChain/nibiru/pull/2100) - refactor: cleanup statedb and precompile sections ### State Machine Breaking (Other) diff --git a/app/wasmext/stargate_query.go b/app/wasmext/stargate_query.go index 2d90b6d58..bd1567175 100644 --- a/app/wasmext/stargate_query.go +++ b/app/wasmext/stargate_query.go @@ -120,6 +120,7 @@ func WasmAcceptedStargateQueries() wasmkeeper.AcceptedStargateQueries { // nibiru oracle "/nibiru.oracle.v1.Query/ExchangeRate": new(oracle.QueryExchangeRateResponse), + "/nibiru.oracle.v1.Query/DatedExchangeRate": new(oracle.QueryDatedExchangeRateResponse), "/nibiru.oracle.v1.Query/ExchangeRateTwap": new(oracle.QueryExchangeRateResponse), "/nibiru.oracle.v1.Query/ExchangeRates": new(oracle.QueryExchangeRatesResponse), "/nibiru.oracle.v1.Query/Actives": new(oracle.QueryActivesResponse), diff --git a/proto/nibiru/oracle/v1/query.proto b/proto/nibiru/oracle/v1/query.proto index 62e1f40be..3be464a1a 100644 --- a/proto/nibiru/oracle/v1/query.proto +++ b/proto/nibiru/oracle/v1/query.proto @@ -22,6 +22,12 @@ service Query { option (google.api.http).get = "/nibiru/oracle/v1beta1/exchange_rate_twap"; } + // DatedExchangeRate returns latest price of a pair + rpc DatedExchangeRate(QueryExchangeRateRequest) + returns (QueryDatedExchangeRateResponse) { + option (google.api.http).get = "/nibiru/oracle/v1beta1/dated_exchange_rate"; + } + // ExchangeRates returns exchange rates of all pairs rpc ExchangeRates(QueryExchangeRatesRequest) returns (QueryExchangeRatesResponse) { @@ -112,7 +118,25 @@ message QueryExchangeRateResponse { // QueryExchangeRatesRequest is the request type for the Query/ExchangeRates RPC // method. -message QueryExchangeRatesRequest {} +message QueryExchangeRatesRequest { +} + +// QueryDatedExchangeRateResponse is the request type for the +// Query/DatedExchangeRate RPC method. +message QueryDatedExchangeRateResponse { + string price = 1 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + + // Block timestamp for the block where the oracle came to consensus for this + // price. This timestamp is a conventional Unix millisecond time, i.e. the + // number of milliseconds elapsed since January 1, 1970 UTC. + int64 block_timestamp_ms = 2; + + // Block height when the oracle came to consensus for this price. + uint64 block_height = 3; +} // QueryExchangeRatesResponse is response type for the // Query/ExchangeRates RPC method. diff --git a/x/evm/embeds/artifacts/contracts/IOracle.sol/IOracle.json b/x/evm/embeds/artifacts/contracts/IOracle.sol/IOracle.json index 39638bdae..887d9433c 100644 --- a/x/evm/embeds/artifacts/contracts/IOracle.sol/IOracle.json +++ b/x/evm/embeds/artifacts/contracts/IOracle.sol/IOracle.json @@ -14,9 +14,19 @@ "name": "queryExchangeRate", "outputs": [ { - "internalType": "string", - "name": "", - "type": "string" + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "blockTimeMs", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockHeight", + "type": "uint64" } ], "stateMutability": "view", diff --git a/x/evm/embeds/contracts/IOracle.sol b/x/evm/embeds/contracts/IOracle.sol index 7cb0a820a..393584f6f 100644 --- a/x/evm/embeds/contracts/IOracle.sol +++ b/x/evm/embeds/contracts/IOracle.sol @@ -3,12 +3,20 @@ pragma solidity >=0.8.19; /// @notice Oracle interface for querying exchange rates interface IOracle { - /// @notice Queries the exchange rate for a given pair - /// @param pair The asset pair to query. For example, "ubtc:uusd" is the - /// USD price of BTC and "unibi:uusd" is the USD price of NIBI. - /// @return The exchange rate (a decimal value) as a string. - /// @dev This function is view-only and does not modify state. - function queryExchangeRate(string memory pair) external view returns (string memory); + /// @notice Queries the dated exchange rate for a given pair + /// @param pair The asset pair to query. For example, "ubtc:uusd" is the + /// USD price of BTC and "unibi:uusd" is the USD price of NIBI. + /// @return price The exchange rate for the given pair + /// @return blockTimeMs The block time in milliseconds when the price was + /// last updated + /// @return blockHeight The block height when the price was last updated + /// @dev This function is view-only and does not modify state. + function queryExchangeRate( + string memory pair + ) + external + view + returns (uint256 price, uint64 blockTimeMs, uint64 blockHeight); } address constant ORACLE_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000801; diff --git a/x/evm/precompile/oracle.go b/x/evm/precompile/oracle.go index f59b93822..cf461a3c4 100644 --- a/x/evm/precompile/oracle.go +++ b/x/evm/precompile/oracle.go @@ -81,12 +81,12 @@ func (p precompileOracle) queryExchangeRate( return nil, err } - price, err := p.oracleKeeper.GetExchangeRate(ctx, assetPair) + price, blockTime, blockHeight, err := p.oracleKeeper.GetDatedExchangeRate(ctx, assetPair) if err != nil { return nil, err } - return method.Outputs.Pack(price.String()) + return method.Outputs.Pack(price.BigInt(), uint64(blockTime), blockHeight) } func (p precompileOracle) parseQueryExchangeRateArgs(args []any) ( diff --git a/x/evm/precompile/oracle_test.go b/x/evm/precompile/oracle_test.go index efab80118..fa07d72d6 100644 --- a/x/evm/precompile/oracle_test.go +++ b/x/evm/precompile/oracle_test.go @@ -1,7 +1,9 @@ package precompile_test import ( + "math/big" "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" @@ -55,7 +57,9 @@ func (s *OracleSuite) TestOracle_HappyPath() { s.T().Log("Query exchange rate") { + deps.Ctx = deps.Ctx.WithBlockTime(time.Unix(69, 420)).WithBlockHeight(69) deps.App.OracleKeeper.SetPrice(deps.Ctx, "unibi:uusd", sdk.MustNewDecFromStr("0.067")) + input, err := embeds.SmartContract_Oracle.ABI.Pack("queryExchangeRate", "unibi:uusd") s.NoError(err) resp, _, err := deps.EvmKeeper.CallContractWithInput( @@ -68,7 +72,9 @@ func (s *OracleSuite) TestOracle_HappyPath() { s.NoError(err) // Check the response - s.Equal("0.067000000000000000", out[0].(string)) + s.Equal(out[0].(*big.Int), big.NewInt(67000000000000000)) + s.Equal(out[1].(uint64), uint64(69000)) + s.Equal(out[2].(uint64), uint64(69)) } } diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index 32d2b8b63..bbbf31ce9 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -187,6 +187,16 @@ func (k Keeper) GetExchangeRate(ctx sdk.Context, pair asset.Pair) (price sdk.Dec return } +func (k Keeper) GetDatedExchangeRate(ctx sdk.Context, pair asset.Pair) (price sdk.Dec, blockTimeMs int64, BlockHeight uint64, err error) { + exchangeRate, err := k.ExchangeRates.Get(ctx, pair) + if err != nil { + return + } + time := ctx.WithBlockHeight(int64(exchangeRate.CreatedBlock)).BlockTime() + + return exchangeRate.ExchangeRate, time.UnixMilli(), exchangeRate.CreatedBlock, nil +} + // SetPrice sets the price for a pair as well as the price snapshot. func (k Keeper) SetPrice(ctx sdk.Context, pair asset.Pair, price sdk.Dec) { k.ExchangeRates.Insert(ctx, pair, types.DatedPrice{ExchangeRate: price, CreatedBlock: uint64(ctx.BlockHeight())}) diff --git a/x/oracle/keeper/querier.go b/x/oracle/keeper/querier.go index 576c5c72b..6cc7fbd2b 100644 --- a/x/oracle/keeper/querier.go +++ b/x/oracle/keeper/querier.go @@ -79,6 +79,24 @@ func (q querier) ExchangeRateTwap(c context.Context, req *types.QueryExchangeRat return &types.QueryExchangeRateResponse{ExchangeRate: twap}, nil } +// get the latest price snapshot from the oracle for a pair +func (q querier) DatedExchangeRate(c context.Context, req *types.QueryExchangeRateRequest) (response *types.QueryDatedExchangeRateResponse, err error) { + if _, err = q.ExchangeRate(c, req); err != nil { + return + } + + ctx := sdk.UnwrapSDKContext(c) + price, blockTime, blockHeight, err := q.Keeper.GetDatedExchangeRate(ctx, req.Pair) + if err != nil { + return &types.QueryDatedExchangeRateResponse{}, err + } + return &types.QueryDatedExchangeRateResponse{ + Price: price, + BlockTimestampMs: blockTime, + BlockHeight: blockHeight, + }, nil +} + // ExchangeRates queries exchange rates of all pairs func (q querier) ExchangeRates(c context.Context, _ *types.QueryExchangeRatesRequest) (*types.QueryExchangeRatesResponse, error) { ctx := sdk.UnwrapSDKContext(c) diff --git a/x/oracle/keeper/querier_test.go b/x/oracle/keeper/querier_test.go index 8db8f2749..45e39ccdc 100644 --- a/x/oracle/keeper/querier_test.go +++ b/x/oracle/keeper/querier_test.go @@ -118,6 +118,111 @@ func TestQueryExchangeRateTwap(t *testing.T) { require.Equal(t, math.LegacyMustNewDecFromStr("1700"), res.ExchangeRate) } +func TestQueryDatedExchangeRate(t *testing.T) { + input := CreateTestFixture(t) + querier := NewQuerier(input.OracleKeeper) + + // Set initial block time and height + initialTime := input.Ctx.BlockTime() + initialHeight := input.Ctx.BlockHeight() + + // Pair 1: BTC/NUSD + pairBTC := asset.Registry.Pair(denoms.BTC, denoms.NUSD) + rateBTC1 := math.LegacyNewDec(1700) + rateBTC2 := math.LegacyNewDec(1800) + + // Pair 2: ETH/NUSD + pairETH := asset.Registry.Pair(denoms.ETH, denoms.NUSD) + rateETH1 := math.LegacyNewDec(100) + rateETH2 := math.LegacyNewDec(110) + + // --- Set first price for BTC/NUSD --- + input.OracleKeeper.SetPrice(input.Ctx, pairBTC, rateBTC1) + testutilevents.RequireContainsTypedEvent( + t, + input.Ctx, + &types.EventPriceUpdate{ + Pair: pairBTC.String(), + Price: rateBTC1, + TimestampMs: input.Ctx.BlockTime().UnixMilli(), + }, + ) + + // Advance time and block height + input.Ctx = input.Ctx.WithBlockTime(initialTime.Add(1 * time.Second)). + WithBlockHeight(initialHeight + 1) + + // --- Set first price for ETH/NUSD --- + input.OracleKeeper.SetPrice(input.Ctx, pairETH, rateETH1) + testutilevents.RequireContainsTypedEvent( + t, + input.Ctx, + &types.EventPriceUpdate{ + Pair: pairETH.String(), + Price: rateETH1, + TimestampMs: input.Ctx.BlockTime().UnixMilli(), + }, + ) + + // Advance time and block height + input.Ctx = input.Ctx.WithBlockTime(initialTime.Add(2 * time.Second)). + WithBlockHeight(initialHeight + 2) + + // --- Set second price for BTC/NUSD --- + input.OracleKeeper.SetPrice(input.Ctx, pairBTC, rateBTC2) + testutilevents.RequireContainsTypedEvent( + t, + input.Ctx, + &types.EventPriceUpdate{ + Pair: pairBTC.String(), + Price: rateBTC2, + TimestampMs: input.Ctx.BlockTime().UnixMilli(), + }, + ) + + // Advance time and block height + input.Ctx = input.Ctx.WithBlockTime(initialTime.Add(3 * time.Second)). + WithBlockHeight(initialHeight + 3) + + // --- Set second price for ETH/NUSD --- + input.OracleKeeper.SetPrice(input.Ctx, pairETH, rateETH2) + testutilevents.RequireContainsTypedEvent( + t, + input.Ctx, + &types.EventPriceUpdate{ + Pair: pairETH.String(), + Price: rateETH2, + TimestampMs: input.Ctx.BlockTime().UnixMilli(), + }, + ) + + // Wrap context for querying + ctx := sdk.WrapSDKContext(input.Ctx) + + // --- Query latest snapshot for BTC/NUSD --- + resBTC, err := querier.DatedExchangeRate( + ctx, + &types.QueryExchangeRateRequest{Pair: pairBTC}, + ) + require.NoError(t, err) + require.Equal(t, rateBTC2, resBTC.Price) + require.Equal(t, input.Ctx.BlockTime().UnixMilli(), resBTC.BlockTimestampMs) + + // --- Query latest snapshot for ETH/NUSD --- + resETH, err := querier.DatedExchangeRate( + ctx, + &types.QueryExchangeRateRequest{Pair: pairETH}, + ) + require.NoError(t, err) + require.Equal(t, rateETH2, resETH.Price) + require.Equal(t, input.Ctx.BlockTime().UnixMilli(), resETH.BlockTimestampMs) + + // --- Query a pair with no snapshots (should return an error) --- + pairATOM := asset.Registry.Pair(denoms.ATOM, denoms.NUSD) + _, err = querier.DatedExchangeRate(ctx, &types.QueryExchangeRateRequest{Pair: pairATOM}) + require.Error(t, err) +} + func TestCalcTwap(t *testing.T) { tests := []struct { name string diff --git a/x/oracle/types/query.pb.go b/x/oracle/types/query.pb.go index d1462c82e..4149e28c4 100644 --- a/x/oracle/types/query.pb.go +++ b/x/oracle/types/query.pb.go @@ -150,6 +150,65 @@ func (m *QueryExchangeRatesRequest) XXX_DiscardUnknown() { var xxx_messageInfo_QueryExchangeRatesRequest proto.InternalMessageInfo +// QueryDatedExchangeRateResponse is the request type for the +// Query/DatedExchangeRate RPC method. +type QueryDatedExchangeRateResponse struct { + Price github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=price,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"price"` + // Block timestamp for the block where the oracle came to consensus for this + // price. This timestamp is a conventional Unix millisecond time, i.e. the + // number of milliseconds elapsed since January 1, 1970 UTC. + BlockTimestampMs int64 `protobuf:"varint,2,opt,name=block_timestamp_ms,json=blockTimestampMs,proto3" json:"block_timestamp_ms,omitempty"` + // Block height when the oracle came to consensus for this price. + BlockHeight uint64 `protobuf:"varint,3,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` +} + +func (m *QueryDatedExchangeRateResponse) Reset() { *m = QueryDatedExchangeRateResponse{} } +func (m *QueryDatedExchangeRateResponse) String() string { return proto.CompactTextString(m) } +func (*QueryDatedExchangeRateResponse) ProtoMessage() {} +func (*QueryDatedExchangeRateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_16aef2382d1249a8, []int{3} +} +func (m *QueryDatedExchangeRateResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryDatedExchangeRateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryDatedExchangeRateResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryDatedExchangeRateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryDatedExchangeRateResponse.Merge(m, src) +} +func (m *QueryDatedExchangeRateResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryDatedExchangeRateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryDatedExchangeRateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryDatedExchangeRateResponse proto.InternalMessageInfo + +func (m *QueryDatedExchangeRateResponse) GetBlockTimestampMs() int64 { + if m != nil { + return m.BlockTimestampMs + } + return 0 +} + +func (m *QueryDatedExchangeRateResponse) GetBlockHeight() uint64 { + if m != nil { + return m.BlockHeight + } + return 0 +} + // QueryExchangeRatesResponse is response type for the // Query/ExchangeRates RPC method. type QueryExchangeRatesResponse struct { @@ -162,7 +221,7 @@ func (m *QueryExchangeRatesResponse) Reset() { *m = QueryExchangeRatesRe func (m *QueryExchangeRatesResponse) String() string { return proto.CompactTextString(m) } func (*QueryExchangeRatesResponse) ProtoMessage() {} func (*QueryExchangeRatesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{3} + return fileDescriptor_16aef2382d1249a8, []int{4} } func (m *QueryExchangeRatesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -206,7 +265,7 @@ func (m *QueryActivesRequest) Reset() { *m = QueryActivesRequest{} } func (m *QueryActivesRequest) String() string { return proto.CompactTextString(m) } func (*QueryActivesRequest) ProtoMessage() {} func (*QueryActivesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{4} + return fileDescriptor_16aef2382d1249a8, []int{5} } func (m *QueryActivesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -246,7 +305,7 @@ func (m *QueryActivesResponse) Reset() { *m = QueryActivesResponse{} } func (m *QueryActivesResponse) String() string { return proto.CompactTextString(m) } func (*QueryActivesResponse) ProtoMessage() {} func (*QueryActivesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{5} + return fileDescriptor_16aef2382d1249a8, []int{6} } func (m *QueryActivesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -284,7 +343,7 @@ func (m *QueryVoteTargetsRequest) Reset() { *m = QueryVoteTargetsRequest func (m *QueryVoteTargetsRequest) String() string { return proto.CompactTextString(m) } func (*QueryVoteTargetsRequest) ProtoMessage() {} func (*QueryVoteTargetsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{6} + return fileDescriptor_16aef2382d1249a8, []int{7} } func (m *QueryVoteTargetsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -325,7 +384,7 @@ func (m *QueryVoteTargetsResponse) Reset() { *m = QueryVoteTargetsRespon func (m *QueryVoteTargetsResponse) String() string { return proto.CompactTextString(m) } func (*QueryVoteTargetsResponse) ProtoMessage() {} func (*QueryVoteTargetsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{7} + return fileDescriptor_16aef2382d1249a8, []int{8} } func (m *QueryVoteTargetsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -365,7 +424,7 @@ func (m *QueryFeederDelegationRequest) Reset() { *m = QueryFeederDelegat func (m *QueryFeederDelegationRequest) String() string { return proto.CompactTextString(m) } func (*QueryFeederDelegationRequest) ProtoMessage() {} func (*QueryFeederDelegationRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{8} + return fileDescriptor_16aef2382d1249a8, []int{9} } func (m *QueryFeederDelegationRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -405,7 +464,7 @@ func (m *QueryFeederDelegationResponse) Reset() { *m = QueryFeederDelega func (m *QueryFeederDelegationResponse) String() string { return proto.CompactTextString(m) } func (*QueryFeederDelegationResponse) ProtoMessage() {} func (*QueryFeederDelegationResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{9} + return fileDescriptor_16aef2382d1249a8, []int{10} } func (m *QueryFeederDelegationResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -452,7 +511,7 @@ func (m *QueryMissCounterRequest) Reset() { *m = QueryMissCounterRequest func (m *QueryMissCounterRequest) String() string { return proto.CompactTextString(m) } func (*QueryMissCounterRequest) ProtoMessage() {} func (*QueryMissCounterRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{10} + return fileDescriptor_16aef2382d1249a8, []int{11} } func (m *QueryMissCounterRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -492,7 +551,7 @@ func (m *QueryMissCounterResponse) Reset() { *m = QueryMissCounterRespon func (m *QueryMissCounterResponse) String() string { return proto.CompactTextString(m) } func (*QueryMissCounterResponse) ProtoMessage() {} func (*QueryMissCounterResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{11} + return fileDescriptor_16aef2382d1249a8, []int{12} } func (m *QueryMissCounterResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -539,7 +598,7 @@ func (m *QueryAggregatePrevoteRequest) Reset() { *m = QueryAggregatePrev func (m *QueryAggregatePrevoteRequest) String() string { return proto.CompactTextString(m) } func (*QueryAggregatePrevoteRequest) ProtoMessage() {} func (*QueryAggregatePrevoteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{12} + return fileDescriptor_16aef2382d1249a8, []int{13} } func (m *QueryAggregatePrevoteRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -580,7 +639,7 @@ func (m *QueryAggregatePrevoteResponse) Reset() { *m = QueryAggregatePre func (m *QueryAggregatePrevoteResponse) String() string { return proto.CompactTextString(m) } func (*QueryAggregatePrevoteResponse) ProtoMessage() {} func (*QueryAggregatePrevoteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{13} + return fileDescriptor_16aef2382d1249a8, []int{14} } func (m *QueryAggregatePrevoteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -625,7 +684,7 @@ func (m *QueryAggregatePrevotesRequest) Reset() { *m = QueryAggregatePre func (m *QueryAggregatePrevotesRequest) String() string { return proto.CompactTextString(m) } func (*QueryAggregatePrevotesRequest) ProtoMessage() {} func (*QueryAggregatePrevotesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{14} + return fileDescriptor_16aef2382d1249a8, []int{15} } func (m *QueryAggregatePrevotesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -666,7 +725,7 @@ func (m *QueryAggregatePrevotesResponse) Reset() { *m = QueryAggregatePr func (m *QueryAggregatePrevotesResponse) String() string { return proto.CompactTextString(m) } func (*QueryAggregatePrevotesResponse) ProtoMessage() {} func (*QueryAggregatePrevotesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{15} + return fileDescriptor_16aef2382d1249a8, []int{16} } func (m *QueryAggregatePrevotesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -713,7 +772,7 @@ func (m *QueryAggregateVoteRequest) Reset() { *m = QueryAggregateVoteReq func (m *QueryAggregateVoteRequest) String() string { return proto.CompactTextString(m) } func (*QueryAggregateVoteRequest) ProtoMessage() {} func (*QueryAggregateVoteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{16} + return fileDescriptor_16aef2382d1249a8, []int{17} } func (m *QueryAggregateVoteRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -754,7 +813,7 @@ func (m *QueryAggregateVoteResponse) Reset() { *m = QueryAggregateVoteRe func (m *QueryAggregateVoteResponse) String() string { return proto.CompactTextString(m) } func (*QueryAggregateVoteResponse) ProtoMessage() {} func (*QueryAggregateVoteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{17} + return fileDescriptor_16aef2382d1249a8, []int{18} } func (m *QueryAggregateVoteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -799,7 +858,7 @@ func (m *QueryAggregateVotesRequest) Reset() { *m = QueryAggregateVotesR func (m *QueryAggregateVotesRequest) String() string { return proto.CompactTextString(m) } func (*QueryAggregateVotesRequest) ProtoMessage() {} func (*QueryAggregateVotesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{18} + return fileDescriptor_16aef2382d1249a8, []int{19} } func (m *QueryAggregateVotesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -840,7 +899,7 @@ func (m *QueryAggregateVotesResponse) Reset() { *m = QueryAggregateVotes func (m *QueryAggregateVotesResponse) String() string { return proto.CompactTextString(m) } func (*QueryAggregateVotesResponse) ProtoMessage() {} func (*QueryAggregateVotesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{19} + return fileDescriptor_16aef2382d1249a8, []int{20} } func (m *QueryAggregateVotesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -884,7 +943,7 @@ func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryParamsRequest) ProtoMessage() {} func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{20} + return fileDescriptor_16aef2382d1249a8, []int{21} } func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -923,7 +982,7 @@ func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryParamsResponse) ProtoMessage() {} func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16aef2382d1249a8, []int{21} + return fileDescriptor_16aef2382d1249a8, []int{22} } func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -963,6 +1022,7 @@ func init() { proto.RegisterType((*QueryExchangeRateRequest)(nil), "nibiru.oracle.v1.QueryExchangeRateRequest") proto.RegisterType((*QueryExchangeRateResponse)(nil), "nibiru.oracle.v1.QueryExchangeRateResponse") proto.RegisterType((*QueryExchangeRatesRequest)(nil), "nibiru.oracle.v1.QueryExchangeRatesRequest") + proto.RegisterType((*QueryDatedExchangeRateResponse)(nil), "nibiru.oracle.v1.QueryDatedExchangeRateResponse") proto.RegisterType((*QueryExchangeRatesResponse)(nil), "nibiru.oracle.v1.QueryExchangeRatesResponse") proto.RegisterType((*QueryActivesRequest)(nil), "nibiru.oracle.v1.QueryActivesRequest") proto.RegisterType((*QueryActivesResponse)(nil), "nibiru.oracle.v1.QueryActivesResponse") @@ -987,77 +1047,84 @@ func init() { func init() { proto.RegisterFile("nibiru/oracle/v1/query.proto", fileDescriptor_16aef2382d1249a8) } var fileDescriptor_16aef2382d1249a8 = []byte{ - // 1108 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x97, 0xc1, 0x6f, 0x1b, 0x45, - 0x14, 0xc6, 0x3d, 0x10, 0x52, 0x78, 0x8e, 0xd3, 0x64, 0x08, 0x22, 0xdd, 0x26, 0x76, 0x59, 0x9a, - 0xa8, 0x6d, 0x9a, 0x5d, 0x9c, 0x54, 0x45, 0x81, 0x22, 0x70, 0x12, 0x2a, 0x15, 0xb5, 0x10, 0x4c, - 0x15, 0xa1, 0x5e, 0xac, 0xf1, 0x7a, 0xba, 0x59, 0x61, 0xef, 0x6c, 0x77, 0xd6, 0xa6, 0x51, 0xe1, - 0x52, 0x01, 0xe2, 0x88, 0x84, 0x10, 0x37, 0xe8, 0x05, 0x09, 0x71, 0x06, 0xee, 0x70, 0xea, 0xb1, - 0x12, 0x17, 0xc4, 0xa1, 0xa0, 0x84, 0x03, 0x7f, 0x06, 0xda, 0xd9, 0xf1, 0x7a, 0xd7, 0xeb, 0x51, - 0x16, 0x97, 0x9e, 0x12, 0xcd, 0x7b, 0xfb, 0xde, 0xef, 0x7d, 0x33, 0x3b, 0x9f, 0x17, 0x16, 0x5c, - 0xa7, 0xe9, 0xf8, 0x5d, 0x93, 0xf9, 0xc4, 0x6a, 0x53, 0xb3, 0x57, 0x35, 0x6f, 0x75, 0xa9, 0xbf, - 0x6f, 0x78, 0x3e, 0x0b, 0x18, 0x9e, 0x89, 0xa2, 0x46, 0x14, 0x35, 0x7a, 0x55, 0x6d, 0xce, 0x66, - 0x36, 0x13, 0x41, 0x33, 0xfc, 0x2f, 0xca, 0xd3, 0x16, 0x6c, 0xc6, 0xec, 0x36, 0x35, 0x89, 0xe7, - 0x98, 0xc4, 0x75, 0x59, 0x40, 0x02, 0x87, 0xb9, 0x5c, 0x46, 0x17, 0x33, 0x3d, 0x64, 0xbd, 0x28, - 0x5c, 0xb6, 0x18, 0xef, 0x30, 0x6e, 0x36, 0x09, 0x0f, 0x83, 0x4d, 0x1a, 0x90, 0xaa, 0x69, 0x31, - 0xc7, 0x8d, 0xe2, 0x7a, 0x0f, 0xe6, 0xdf, 0x0d, 0x99, 0xde, 0xbc, 0x6d, 0xed, 0x11, 0xd7, 0xa6, - 0x75, 0x12, 0xd0, 0x3a, 0xbd, 0xd5, 0xa5, 0x3c, 0xc0, 0x3b, 0x30, 0xe1, 0x11, 0xc7, 0x9f, 0x47, - 0xa7, 0xd0, 0x99, 0x67, 0x36, 0x2f, 0xdd, 0x7f, 0x58, 0x29, 0xfc, 0xf1, 0xb0, 0x72, 0xc1, 0x76, - 0x82, 0xbd, 0x6e, 0xd3, 0xb0, 0x58, 0xc7, 0x7c, 0x5b, 0xf4, 0xde, 0xda, 0x23, 0x8e, 0x6b, 0x4a, - 0x8e, 0xde, 0x9a, 0x79, 0xdb, 0xb4, 0x58, 0xa7, 0xc3, 0x5c, 0x93, 0x70, 0x4e, 0x03, 0x63, 0x87, - 0x38, 0x7e, 0x5d, 0x54, 0x7a, 0xe5, 0xe9, 0xcf, 0xef, 0x55, 0x0a, 0xff, 0xdc, 0xab, 0x14, 0x74, - 0x0f, 0x4e, 0x8c, 0xe8, 0xcb, 0x3d, 0xe6, 0x72, 0x8a, 0xdf, 0x83, 0x12, 0x95, 0xeb, 0x0d, 0x9f, - 0x04, 0x54, 0x12, 0x18, 0x92, 0x60, 0x39, 0x41, 0x20, 0xc7, 0x8b, 0xfe, 0xac, 0xf2, 0xd6, 0x07, - 0x66, 0xb0, 0xef, 0x51, 0x6e, 0x6c, 0x53, 0xab, 0x3e, 0x45, 0x13, 0xc5, 0xf5, 0x93, 0x23, 0x3a, - 0x72, 0x39, 0xaa, 0xfe, 0x09, 0x02, 0x6d, 0x54, 0x54, 0x02, 0xdd, 0x84, 0xe9, 0x14, 0x10, 0x9f, - 0x47, 0xa7, 0x9e, 0x3c, 0x53, 0x5c, 0x7b, 0xd1, 0x18, 0xde, 0x43, 0x23, 0x59, 0xe0, 0x7a, 0xd7, - 0x6b, 0xd3, 0x4d, 0x2d, 0xc4, 0xfe, 0xe1, 0xcf, 0x0a, 0xce, 0x84, 0x78, 0xbd, 0x94, 0x44, 0xe4, - 0xfa, 0x73, 0xf0, 0xac, 0xa0, 0xa8, 0x59, 0x81, 0xd3, 0x1b, 0xd0, 0xb9, 0x30, 0x97, 0x5e, 0x96, - 0x58, 0xbb, 0x70, 0x8c, 0x44, 0x4b, 0x82, 0xe7, 0x51, 0xf7, 0xa8, 0x5f, 0x4c, 0x3f, 0x01, 0xcf, - 0x8b, 0x7e, 0xbb, 0x2c, 0xa0, 0xd7, 0x89, 0x6f, 0xd3, 0x20, 0x46, 0xb9, 0x23, 0xcf, 0x4b, 0x2a, - 0x24, 0x71, 0x1a, 0x30, 0xd5, 0x63, 0x01, 0x6d, 0x04, 0xd1, 0xfa, 0xff, 0xc2, 0x54, 0xec, 0x0d, - 0x1a, 0xe9, 0xef, 0xc0, 0x82, 0x68, 0x7e, 0x99, 0xd2, 0x16, 0xf5, 0xb7, 0x69, 0x9b, 0xda, 0xe2, - 0x5d, 0xe8, 0x1f, 0xd8, 0x25, 0x98, 0xee, 0x91, 0xb6, 0xd3, 0x22, 0x01, 0xf3, 0x1b, 0xa4, 0xd5, - 0x92, 0x47, 0xb7, 0x5e, 0x8a, 0x57, 0x6b, 0xad, 0x56, 0xf2, 0x14, 0xbe, 0x01, 0x8b, 0x8a, 0x82, - 0x72, 0xa4, 0x0a, 0x14, 0x6f, 0x8a, 0x58, 0xb2, 0x1c, 0x44, 0x4b, 0x61, 0x2d, 0xfd, 0x2d, 0x29, - 0xd5, 0x35, 0x87, 0xf3, 0x2d, 0xd6, 0x75, 0x03, 0xea, 0x8f, 0x4d, 0xf3, 0x9a, 0xd4, 0x36, 0x55, - 0x4b, 0x82, 0xbc, 0x00, 0x53, 0x1d, 0x87, 0xf3, 0x86, 0x15, 0xad, 0x8b, 0x52, 0x13, 0xf5, 0x62, - 0x67, 0x90, 0x1a, 0xab, 0x53, 0xb3, 0x6d, 0x3f, 0x9c, 0x83, 0xee, 0xf8, 0x34, 0x54, 0x6f, 0x6c, - 0x9e, 0xbb, 0x48, 0xca, 0x93, 0xad, 0x28, 0xa9, 0x08, 0xcc, 0x92, 0x7e, 0xac, 0xe1, 0x45, 0x41, - 0x51, 0xb5, 0xb8, 0x66, 0x64, 0x5f, 0x8d, 0xb8, 0x4c, 0xf2, 0x45, 0x90, 0x25, 0x37, 0x27, 0xc2, - 0x63, 0x52, 0x9f, 0x21, 0x43, 0xad, 0xf4, 0x8a, 0x82, 0x21, 0x3e, 0x91, 0x9f, 0x22, 0x28, 0xab, - 0x32, 0x24, 0xa6, 0x05, 0x38, 0x83, 0xd9, 0x7f, 0x85, 0xc7, 0xe3, 0x9c, 0x1d, 0xe6, 0xe4, 0xfa, - 0x55, 0x79, 0xbf, 0xc4, 0x4f, 0xef, 0x3e, 0x8a, 0xf6, 0x3d, 0x79, 0x1f, 0x0d, 0x55, 0x93, 0x03, - 0xbd, 0x0f, 0xd3, 0x83, 0x81, 0x12, 0xa2, 0xaf, 0xe4, 0x1c, 0x66, 0x77, 0x30, 0x49, 0x89, 0x24, - 0x3b, 0xe8, 0x0b, 0xa3, 0xfa, 0xc6, 0x5a, 0xef, 0xc3, 0xc9, 0x91, 0x51, 0x89, 0x75, 0x03, 0x8e, - 0xa7, 0xb1, 0xfa, 0x22, 0x8f, 0xc1, 0x35, 0x9d, 0xe2, 0xe2, 0xfa, 0x1c, 0x60, 0xd1, 0x7a, 0x87, - 0xf8, 0xa4, 0x13, 0x03, 0x5d, 0x93, 0x17, 0x66, 0x7f, 0x55, 0x82, 0x5c, 0x84, 0x49, 0x4f, 0xac, - 0x48, 0x5d, 0xe6, 0xb3, 0xfd, 0xa3, 0x27, 0x64, 0x33, 0x99, 0xbd, 0xf6, 0xeb, 0x71, 0x78, 0x4a, - 0xd4, 0xc3, 0x5f, 0x21, 0x98, 0x4a, 0x92, 0xe1, 0x73, 0xd9, 0x12, 0x2a, 0xe3, 0xd4, 0x56, 0x72, - 0xe5, 0x46, 0xac, 0xfa, 0xf9, 0xbb, 0xbf, 0xfd, 0xfd, 0xe5, 0x13, 0xcb, 0xf8, 0xb4, 0x39, 0xec, - 0xe4, 0x91, 0x59, 0xa7, 0x8c, 0x07, 0x7f, 0x83, 0x60, 0x26, 0xe5, 0x23, 0x1f, 0x12, 0xef, 0xf1, - 0xb1, 0x55, 0x05, 0xdb, 0x0a, 0x3e, 0x9b, 0x87, 0xad, 0x11, 0x84, 0x2c, 0xdf, 0x22, 0x28, 0xa5, - 0x4c, 0x14, 0xe7, 0xe9, 0xd8, 0xdf, 0x50, 0xed, 0x7c, 0xbe, 0x64, 0xc9, 0xb7, 0x2e, 0xf8, 0x56, - 0xf1, 0x8a, 0x82, 0x2f, 0xfc, 0xd1, 0xc1, 0xd3, 0x94, 0x1c, 0x7f, 0x86, 0xe0, 0x98, 0x74, 0x52, - 0xbc, 0xa4, 0x68, 0x97, 0x36, 0x60, 0x6d, 0xf9, 0xa8, 0xb4, 0x9c, 0x7b, 0x19, 0xf1, 0x48, 0x9b, - 0xc5, 0x5f, 0x23, 0x28, 0x26, 0x7c, 0x14, 0x9f, 0x55, 0x74, 0xc9, 0xda, 0xb0, 0x76, 0x2e, 0x4f, - 0x6a, 0xce, 0x4d, 0x8c, 0xa0, 0x92, 0xce, 0x8d, 0x7f, 0x46, 0x30, 0x33, 0xec, 0x89, 0xd8, 0x50, - 0xf4, 0x54, 0xb8, 0xb1, 0x66, 0xe6, 0xce, 0x97, 0xa0, 0x35, 0x01, 0xfa, 0x2a, 0xde, 0x50, 0x80, - 0xc6, 0x77, 0x25, 0x37, 0xef, 0xa4, 0x6f, 0xd3, 0x8f, 0xcd, 0xc8, 0x92, 0xf1, 0x77, 0x08, 0x8a, - 0x09, 0xfb, 0x54, 0x4a, 0x9a, 0xb5, 0x6b, 0xa5, 0xa4, 0x23, 0xdc, 0x58, 0x7f, 0x5d, 0x90, 0x6e, - 0xe0, 0x97, 0xc7, 0x20, 0x0d, 0x2d, 0x1b, 0xff, 0x82, 0x60, 0x66, 0xd8, 0xaf, 0x94, 0x02, 0x2b, - 0x0c, 0x5d, 0x29, 0xb0, 0xca, 0xae, 0xf5, 0xab, 0x02, 0xfb, 0x32, 0xde, 0x1e, 0x03, 0x3b, 0x63, - 0xa0, 0xf8, 0x47, 0x04, 0xb3, 0x19, 0xcf, 0xc5, 0x79, 0xa1, 0xe2, 0xa3, 0xfc, 0x52, 0xfe, 0x07, - 0xe4, 0x18, 0x97, 0xc4, 0x18, 0x17, 0xf1, 0x85, 0xa3, 0xc7, 0xc8, 0xda, 0x3e, 0xfe, 0x09, 0x41, - 0x29, 0xe5, 0x5f, 0xca, 0x0b, 0x6a, 0x94, 0x93, 0x2b, 0x2f, 0xa8, 0x91, 0x46, 0xad, 0x5f, 0x11, - 0xa8, 0x5b, 0xb8, 0xa6, 0x46, 0x6d, 0x39, 0x47, 0x2a, 0x2e, 0xe4, 0xfe, 0x1e, 0xc1, 0x74, 0xda, - 0x77, 0x71, 0x2e, 0x96, 0x58, 0xe8, 0xd5, 0x9c, 0xd9, 0x12, 0x7d, 0x43, 0xa0, 0xaf, 0xe3, 0xea, - 0x7f, 0x51, 0x39, 0x92, 0xf8, 0x23, 0x98, 0x8c, 0xec, 0x15, 0x9f, 0x56, 0xf4, 0x4c, 0xb9, 0xb8, - 0xb6, 0x74, 0x44, 0x96, 0x24, 0x5a, 0x12, 0x44, 0x15, 0xbc, 0xa8, 0xbc, 0xc8, 0x84, 0xa5, 0x5f, - 0xb9, 0x7f, 0x50, 0x46, 0x0f, 0x0e, 0xca, 0xe8, 0xaf, 0x83, 0x32, 0xfa, 0xe2, 0xb0, 0x5c, 0x78, - 0x70, 0x58, 0x2e, 0xfc, 0x7e, 0x58, 0x2e, 0xdc, 0x30, 0x73, 0x7c, 0x82, 0xc8, 0x9a, 0xe2, 0x2b, - 0xb2, 0x39, 0x29, 0x3e, 0x92, 0xd7, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xa4, 0xa3, 0x89, 0xf1, - 0xc9, 0x0f, 0x00, 0x00, + // 1218 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x98, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xc7, 0x3d, 0x4d, 0x9a, 0xc2, 0x73, 0x1c, 0x9c, 0x21, 0x08, 0xd7, 0x4d, 0xec, 0x74, 0x69, + 0xa2, 0x34, 0x3f, 0x76, 0x49, 0x52, 0x15, 0x05, 0x8a, 0x20, 0x3f, 0xa8, 0x28, 0x6a, 0x20, 0x98, + 0x28, 0x42, 0xbd, 0x58, 0xe3, 0xf5, 0x74, 0xb3, 0xaa, 0xbd, 0xbb, 0xdd, 0x19, 0x9b, 0x46, 0x85, + 0x4b, 0x05, 0x88, 0x23, 0x12, 0x42, 0xdc, 0xa0, 0x17, 0x24, 0xc4, 0x99, 0x1f, 0x67, 0x6e, 0x3d, + 0x56, 0xe2, 0x82, 0x38, 0x14, 0x94, 0x70, 0x40, 0xfc, 0x15, 0x68, 0x67, 0xc7, 0xce, 0xae, 0xd7, + 0xa3, 0x6c, 0x5d, 0x38, 0xb5, 0x9a, 0xf7, 0xf6, 0xbd, 0xcf, 0x7c, 0x35, 0x33, 0xef, 0xeb, 0xc0, + 0xa4, 0x63, 0xd7, 0x6c, 0xbf, 0x65, 0xb8, 0x3e, 0x31, 0x1b, 0xd4, 0x68, 0x2f, 0x1b, 0xb7, 0x5b, + 0xd4, 0x3f, 0xd0, 0x3d, 0xdf, 0xe5, 0x2e, 0xce, 0x87, 0x51, 0x3d, 0x8c, 0xea, 0xed, 0xe5, 0xe2, + 0x84, 0xe5, 0x5a, 0xae, 0x08, 0x1a, 0xc1, 0xff, 0xc2, 0xbc, 0xe2, 0xa4, 0xe5, 0xba, 0x56, 0x83, + 0x1a, 0xc4, 0xb3, 0x0d, 0xe2, 0x38, 0x2e, 0x27, 0xdc, 0x76, 0x1d, 0x26, 0xa3, 0x53, 0x89, 0x1e, + 0xb2, 0x5e, 0x18, 0x2e, 0x99, 0x2e, 0x6b, 0xba, 0xcc, 0xa8, 0x11, 0x16, 0x04, 0x6b, 0x94, 0x93, + 0x65, 0xc3, 0x74, 0x6d, 0x27, 0x8c, 0x6b, 0x6d, 0x28, 0xbc, 0x1b, 0x30, 0xbd, 0x71, 0xc7, 0xdc, + 0x27, 0x8e, 0x45, 0x2b, 0x84, 0xd3, 0x0a, 0xbd, 0xdd, 0xa2, 0x8c, 0xe3, 0x1d, 0x18, 0xf6, 0x88, + 0xed, 0x17, 0xd0, 0x34, 0x9a, 0x7b, 0x7a, 0xe3, 0xca, 0x83, 0x47, 0xe5, 0xcc, 0xef, 0x8f, 0xca, + 0x97, 0x2c, 0x9b, 0xef, 0xb7, 0x6a, 0xba, 0xe9, 0x36, 0x8d, 0xb7, 0x45, 0xef, 0xcd, 0x7d, 0x62, + 0x3b, 0x86, 0xe4, 0x68, 0xaf, 0x18, 0x77, 0x0c, 0xd3, 0x6d, 0x36, 0x5d, 0xc7, 0x20, 0x8c, 0x51, + 0xae, 0xef, 0x10, 0xdb, 0xaf, 0x88, 0x4a, 0x2f, 0x3f, 0xf5, 0xd9, 0xfd, 0x72, 0xe6, 0xef, 0xfb, + 0xe5, 0x8c, 0xe6, 0xc1, 0xd9, 0x3e, 0x7d, 0x99, 0xe7, 0x3a, 0x8c, 0xe2, 0xf7, 0x20, 0x47, 0xe5, + 0x7a, 0xd5, 0x27, 0x9c, 0x4a, 0x02, 0x5d, 0x12, 0xcc, 0x46, 0x08, 0xe4, 0xf6, 0xc2, 0x7f, 0x96, + 0x58, 0xfd, 0x96, 0xc1, 0x0f, 0x3c, 0xca, 0xf4, 0x2d, 0x6a, 0x56, 0x46, 0x69, 0xa4, 0xb8, 0x76, + 0xae, 0x4f, 0x47, 0x26, 0xb7, 0xaa, 0xfd, 0x8c, 0xa0, 0x24, 0xa2, 0x5b, 0x84, 0xd3, 0x7a, 0x5f, + 0xa8, 0x2d, 0x38, 0xed, 0xf9, 0xb6, 0x39, 0x28, 0x4c, 0xf8, 0x31, 0x5e, 0x04, 0x5c, 0x6b, 0xb8, + 0xe6, 0xad, 0x2a, 0xb7, 0x9b, 0x94, 0x71, 0xd2, 0xf4, 0xaa, 0x4d, 0x56, 0x38, 0x35, 0x8d, 0xe6, + 0x86, 0x2a, 0x79, 0x11, 0xd9, 0xed, 0x04, 0xb6, 0x19, 0x3e, 0x0f, 0xa3, 0x61, 0xf6, 0x3e, 0xb5, + 0xad, 0x7d, 0x5e, 0x18, 0x9a, 0x46, 0x73, 0xc3, 0x95, 0xac, 0x58, 0x7b, 0x53, 0x2c, 0x69, 0x1f, + 0x23, 0x28, 0xf6, 0xdb, 0x97, 0xa4, 0xbe, 0x09, 0x63, 0x31, 0x29, 0x59, 0x01, 0x4d, 0x0f, 0xcd, + 0x65, 0x57, 0x5e, 0xd0, 0x7b, 0x4f, 0x9f, 0x1e, 0x2d, 0xb0, 0xdb, 0xf2, 0x1a, 0x74, 0xa3, 0x18, + 0xec, 0xf1, 0xfb, 0x3f, 0xca, 0x38, 0x11, 0x62, 0x95, 0x5c, 0x54, 0x5c, 0xa6, 0x3d, 0x07, 0xcf, + 0x0a, 0x8a, 0x75, 0x93, 0xdb, 0xed, 0x63, 0x5d, 0x1d, 0x98, 0x88, 0x2f, 0x4b, 0xac, 0x3d, 0x38, + 0x43, 0xc2, 0x25, 0xc1, 0xf3, 0xa4, 0xa7, 0xab, 0x53, 0x4c, 0x3b, 0x0b, 0xcf, 0x8b, 0x7e, 0x7b, + 0x2e, 0xa7, 0xbb, 0xc4, 0xb7, 0x28, 0xef, 0xa2, 0xdc, 0x95, 0x27, 0x3d, 0x16, 0x92, 0x38, 0x55, + 0x18, 0x6d, 0xbb, 0x9c, 0x56, 0x79, 0xb8, 0xfe, 0x9f, 0x30, 0x65, 0xdb, 0xc7, 0x8d, 0xb4, 0x77, + 0x60, 0x52, 0x34, 0xbf, 0x4a, 0x69, 0x9d, 0xfa, 0x5b, 0xb4, 0x41, 0x2d, 0x71, 0x8b, 0x3b, 0x57, + 0x6d, 0x06, 0xc6, 0xda, 0xa4, 0x61, 0xd7, 0x09, 0x77, 0xfd, 0x2a, 0xa9, 0xd7, 0xe5, 0xa5, 0xab, + 0xe4, 0xba, 0xab, 0xeb, 0xf5, 0x7a, 0xf4, 0xfe, 0xbc, 0x0e, 0x53, 0x8a, 0x82, 0x72, 0x4b, 0x65, + 0xc8, 0xde, 0x14, 0xb1, 0x68, 0x39, 0x08, 0x97, 0x82, 0x5a, 0xda, 0x5b, 0x52, 0xaa, 0x6d, 0x9b, + 0xb1, 0x4d, 0xb7, 0xe5, 0x70, 0xea, 0x0f, 0x4c, 0xf3, 0xaa, 0xd4, 0x36, 0x56, 0x4b, 0x82, 0x9c, + 0x87, 0xd1, 0xa6, 0xcd, 0x58, 0xd5, 0x0c, 0xd7, 0x45, 0xa9, 0xe1, 0x4a, 0xb6, 0x79, 0x9c, 0xda, + 0x55, 0x67, 0xdd, 0xb2, 0xfc, 0x60, 0x1f, 0x74, 0xc7, 0xa7, 0x81, 0x7a, 0x03, 0xf3, 0xdc, 0x43, + 0x52, 0x9e, 0x64, 0x45, 0x49, 0x45, 0x60, 0x9c, 0x74, 0x62, 0x55, 0x2f, 0x0c, 0x8a, 0xaa, 0xd9, + 0x15, 0x3d, 0x79, 0x35, 0xba, 0x65, 0xa2, 0x17, 0x41, 0x96, 0xdc, 0x18, 0x0e, 0x8e, 0x49, 0x25, + 0x4f, 0x7a, 0x5a, 0x69, 0x65, 0x05, 0x43, 0xf7, 0x44, 0x7e, 0xd2, 0x79, 0x74, 0xfa, 0x64, 0x48, + 0x4c, 0x13, 0x70, 0x02, 0xb3, 0x73, 0x85, 0x07, 0xe3, 0x1c, 0xef, 0xe5, 0x64, 0xda, 0x75, 0xf9, + 0x32, 0x76, 0xbf, 0xde, 0x7b, 0x12, 0xed, 0xdb, 0xf2, 0x3d, 0xea, 0xa9, 0x26, 0x37, 0xf4, 0x3e, + 0x8c, 0x1d, 0x6f, 0x28, 0x22, 0xfa, 0x42, 0xca, 0xcd, 0xec, 0x1d, 0xef, 0x24, 0x47, 0xa2, 0x1d, + 0xb4, 0xc9, 0x7e, 0x7d, 0xbb, 0x5a, 0x1f, 0xc0, 0xb9, 0xbe, 0x51, 0x89, 0x75, 0x03, 0x9e, 0x89, + 0x63, 0x75, 0x44, 0x1e, 0x80, 0x6b, 0x2c, 0xc6, 0xc5, 0xb4, 0x09, 0xc0, 0xa2, 0xf5, 0x0e, 0xf1, + 0x49, 0xb3, 0x0b, 0xb4, 0x2d, 0x1f, 0xcc, 0xce, 0xaa, 0x04, 0xb9, 0x0c, 0x23, 0x9e, 0x58, 0x91, + 0xba, 0x14, 0x92, 0xfd, 0xc3, 0x2f, 0x64, 0x33, 0x99, 0xbd, 0xf2, 0x4f, 0x1e, 0x4e, 0x8b, 0x7a, + 0xf8, 0x4b, 0x04, 0xa3, 0x51, 0x32, 0x3c, 0x9f, 0x2c, 0xa1, 0x1a, 0xf9, 0xc5, 0x85, 0x54, 0xb9, + 0x21, 0xab, 0xb6, 0x78, 0xef, 0xd7, 0xbf, 0xbe, 0x38, 0x35, 0x8b, 0x2f, 0x18, 0xbd, 0x1e, 0x24, + 0xb4, 0x19, 0xb1, 0xc1, 0x83, 0xbf, 0x46, 0x90, 0x8f, 0xcd, 0x91, 0x0f, 0x88, 0xf7, 0xff, 0xb1, + 0x2d, 0x0b, 0xb6, 0x05, 0x7c, 0x31, 0x0d, 0x5b, 0x95, 0x07, 0x2c, 0xdf, 0x22, 0x18, 0x4f, 0x8c, + 0xff, 0xc7, 0x22, 0x7c, 0x51, 0x91, 0xab, 0x34, 0x15, 0xda, 0x8a, 0xc0, 0x5c, 0xc4, 0xf3, 0x0a, + 0xcc, 0x7a, 0xf0, 0x65, 0x35, 0x2e, 0xe4, 0x37, 0x08, 0x72, 0xb1, 0x61, 0x8f, 0xd3, 0x28, 0xd3, + 0x39, 0x78, 0xc5, 0xc5, 0x74, 0xc9, 0x12, 0x70, 0x55, 0x00, 0x2e, 0xe1, 0x05, 0x05, 0x60, 0x60, + 0xeb, 0x58, 0x5c, 0x4d, 0x86, 0x3f, 0x45, 0x70, 0x46, 0x4e, 0x7c, 0x3c, 0xa3, 0x68, 0x17, 0x37, + 0x0a, 0xc5, 0xd9, 0x93, 0xd2, 0x52, 0x9e, 0xb9, 0x90, 0x47, 0xda, 0x01, 0xfc, 0x15, 0x82, 0x6c, + 0x64, 0xde, 0xe3, 0x8b, 0x8a, 0x2e, 0x49, 0xbb, 0x50, 0x9c, 0x4f, 0x93, 0x9a, 0xf2, 0xb0, 0x85, + 0x50, 0x51, 0x87, 0x81, 0x7f, 0x42, 0x90, 0xef, 0x9d, 0xdd, 0x58, 0x57, 0xf4, 0x54, 0xb8, 0x86, + 0xa2, 0x91, 0x3a, 0x5f, 0x82, 0xae, 0x0b, 0xd0, 0x57, 0xf0, 0x9a, 0x02, 0xb4, 0xfb, 0xa6, 0x33, + 0xe3, 0x6e, 0xfc, 0xd5, 0xff, 0xc8, 0x08, 0xad, 0x43, 0x70, 0x4b, 0xb2, 0x91, 0x31, 0xaf, 0x94, + 0x34, 0x69, 0x2b, 0x94, 0x92, 0xf6, 0x71, 0x0d, 0xda, 0x6b, 0x82, 0x74, 0x0d, 0xbf, 0x34, 0x00, + 0x69, 0x60, 0x2d, 0xf0, 0x2f, 0x08, 0xf2, 0xbd, 0x73, 0x55, 0x29, 0xb0, 0xc2, 0x78, 0x28, 0x05, + 0x56, 0xd9, 0x0a, 0xed, 0xba, 0xc0, 0xbe, 0x8a, 0xb7, 0x06, 0xc0, 0x4e, 0x0c, 0x7a, 0xfc, 0x03, + 0x82, 0xf1, 0x84, 0x37, 0xc0, 0x69, 0xa1, 0xd8, 0x49, 0xcf, 0x92, 0xd2, 0x76, 0x68, 0x57, 0xc4, + 0x36, 0x2e, 0xe3, 0x4b, 0x27, 0x6f, 0x23, 0x69, 0x4f, 0xf0, 0x8f, 0x08, 0x72, 0xb1, 0x39, 0xab, + 0x7c, 0xa0, 0xfa, 0x39, 0x0e, 0xe5, 0x03, 0xd5, 0xd7, 0x50, 0x68, 0xd7, 0x04, 0xea, 0x26, 0x5e, + 0x57, 0xa3, 0xd6, 0xed, 0x13, 0x15, 0x17, 0x72, 0x7f, 0x87, 0x60, 0x2c, 0xee, 0x0f, 0x70, 0x2a, + 0x96, 0xae, 0xd0, 0x4b, 0x29, 0xb3, 0x25, 0xfa, 0x9a, 0x40, 0x5f, 0xc5, 0xcb, 0x8f, 0xa3, 0x72, + 0x28, 0xf1, 0x87, 0x30, 0x12, 0xda, 0x00, 0x7c, 0x41, 0xd1, 0x33, 0xe6, 0x36, 0x8a, 0x33, 0x27, + 0x64, 0x49, 0xa2, 0x19, 0x41, 0x54, 0xc6, 0x53, 0xca, 0x87, 0x4c, 0x58, 0x8f, 0x6b, 0x0f, 0x0e, + 0x4b, 0xe8, 0xe1, 0x61, 0x09, 0xfd, 0x79, 0x58, 0x42, 0x9f, 0x1f, 0x95, 0x32, 0x0f, 0x8f, 0x4a, + 0x99, 0xdf, 0x8e, 0x4a, 0x99, 0x1b, 0x46, 0x8a, 0x9f, 0x4a, 0xb2, 0xa6, 0xf8, 0x69, 0x5c, 0x1b, + 0x11, 0x7f, 0x86, 0x58, 0xfd, 0x37, 0x00, 0x00, 0xff, 0xff, 0xb7, 0xc9, 0xcd, 0x87, 0x2b, 0x11, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1076,6 +1143,8 @@ type QueryClient interface { ExchangeRate(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryExchangeRateResponse, error) // ExchangeRateTwap returns twap exchange rate of a pair ExchangeRateTwap(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryExchangeRateResponse, error) + // DatedExchangeRate returns latest price of a pair + DatedExchangeRate(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryDatedExchangeRateResponse, error) // ExchangeRates returns exchange rates of all pairs ExchangeRates(ctx context.Context, in *QueryExchangeRatesRequest, opts ...grpc.CallOption) (*QueryExchangeRatesResponse, error) // Actives returns all active pairs @@ -1124,6 +1193,15 @@ func (c *queryClient) ExchangeRateTwap(ctx context.Context, in *QueryExchangeRat return out, nil } +func (c *queryClient) DatedExchangeRate(ctx context.Context, in *QueryExchangeRateRequest, opts ...grpc.CallOption) (*QueryDatedExchangeRateResponse, error) { + out := new(QueryDatedExchangeRateResponse) + err := c.cc.Invoke(ctx, "/nibiru.oracle.v1.Query/DatedExchangeRate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) ExchangeRates(ctx context.Context, in *QueryExchangeRatesRequest, opts ...grpc.CallOption) (*QueryExchangeRatesResponse, error) { out := new(QueryExchangeRatesResponse) err := c.cc.Invoke(ctx, "/nibiru.oracle.v1.Query/ExchangeRates", in, out, opts...) @@ -1220,6 +1298,8 @@ type QueryServer interface { ExchangeRate(context.Context, *QueryExchangeRateRequest) (*QueryExchangeRateResponse, error) // ExchangeRateTwap returns twap exchange rate of a pair ExchangeRateTwap(context.Context, *QueryExchangeRateRequest) (*QueryExchangeRateResponse, error) + // DatedExchangeRate returns latest price of a pair + DatedExchangeRate(context.Context, *QueryExchangeRateRequest) (*QueryDatedExchangeRateResponse, error) // ExchangeRates returns exchange rates of all pairs ExchangeRates(context.Context, *QueryExchangeRatesRequest) (*QueryExchangeRatesResponse, error) // Actives returns all active pairs @@ -1252,6 +1332,9 @@ func (*UnimplementedQueryServer) ExchangeRate(ctx context.Context, req *QueryExc func (*UnimplementedQueryServer) ExchangeRateTwap(ctx context.Context, req *QueryExchangeRateRequest) (*QueryExchangeRateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ExchangeRateTwap not implemented") } +func (*UnimplementedQueryServer) DatedExchangeRate(ctx context.Context, req *QueryExchangeRateRequest) (*QueryDatedExchangeRateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DatedExchangeRate not implemented") +} func (*UnimplementedQueryServer) ExchangeRates(ctx context.Context, req *QueryExchangeRatesRequest) (*QueryExchangeRatesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ExchangeRates not implemented") } @@ -1323,6 +1406,24 @@ func _Query_ExchangeRateTwap_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Query_DatedExchangeRate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryExchangeRateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).DatedExchangeRate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/nibiru.oracle.v1.Query/DatedExchangeRate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).DatedExchangeRate(ctx, req.(*QueryExchangeRateRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_ExchangeRates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryExchangeRatesRequest) if err := dec(in); err != nil { @@ -1515,6 +1616,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "ExchangeRateTwap", Handler: _Query_ExchangeRateTwap_Handler, }, + { + MethodName: "DatedExchangeRate", + Handler: _Query_DatedExchangeRate_Handler, + }, { MethodName: "ExchangeRates", Handler: _Query_ExchangeRates_Handler, @@ -1649,6 +1754,49 @@ func (m *QueryExchangeRatesRequest) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *QueryDatedExchangeRateResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryDatedExchangeRateResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryDatedExchangeRateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlockHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.BlockHeight)) + i-- + dAtA[i] = 0x18 + } + if m.BlockTimestampMs != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.BlockTimestampMs)) + i-- + dAtA[i] = 0x10 + } + { + size := m.Price.Size() + i -= size + if _, err := m.Price.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *QueryExchangeRatesResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2268,6 +2416,23 @@ func (m *QueryExchangeRatesRequest) Size() (n int) { return n } +func (m *QueryDatedExchangeRateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Price.Size() + n += 1 + l + sovQuery(uint64(l)) + if m.BlockTimestampMs != 0 { + n += 1 + sovQuery(uint64(m.BlockTimestampMs)) + } + if m.BlockHeight != 0 { + n += 1 + sovQuery(uint64(m.BlockHeight)) + } + return n +} + func (m *QueryExchangeRatesResponse) Size() (n int) { if m == nil { return 0 @@ -2722,6 +2887,128 @@ func (m *QueryExchangeRatesRequest) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryDatedExchangeRateResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryDatedExchangeRateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryDatedExchangeRateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Price.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockTimestampMs", wireType) + } + m.BlockTimestampMs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockTimestampMs |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockHeight", wireType) + } + m.BlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryExchangeRatesResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/oracle/types/query.pb.gw.go b/x/oracle/types/query.pb.gw.go index f8af1a4f8..c9436368d 100644 --- a/x/oracle/types/query.pb.gw.go +++ b/x/oracle/types/query.pb.gw.go @@ -105,6 +105,42 @@ func local_request_Query_ExchangeRateTwap_0(ctx context.Context, marshaler runti } +var ( + filter_Query_DatedExchangeRate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_DatedExchangeRate_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryExchangeRateRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DatedExchangeRate_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.DatedExchangeRate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_DatedExchangeRate_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryExchangeRateRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_DatedExchangeRate_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DatedExchangeRate(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_ExchangeRates_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryExchangeRatesRequest var metadata runtime.ServerMetadata @@ -481,6 +517,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_DatedExchangeRate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_DatedExchangeRate_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DatedExchangeRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_ExchangeRates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -792,6 +851,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_DatedExchangeRate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_DatedExchangeRate_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_DatedExchangeRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_ExchangeRates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1000,6 +1079,8 @@ var ( pattern_Query_ExchangeRateTwap_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"nibiru", "oracle", "v1beta1", "exchange_rate_twap"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_DatedExchangeRate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"nibiru", "oracle", "v1beta1", "dated_exchange_rate"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_ExchangeRates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "pairs", "exchange_rates"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_Actives_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"nibiru", "oracle", "v1beta1", "pairs", "actives"}, "", runtime.AssumeColonVerbOpt(false))) @@ -1026,6 +1107,8 @@ var ( forward_Query_ExchangeRateTwap_0 = runtime.ForwardResponseMessage + forward_Query_DatedExchangeRate_0 = runtime.ForwardResponseMessage + forward_Query_ExchangeRates_0 = runtime.ForwardResponseMessage forward_Query_Actives_0 = runtime.ForwardResponseMessage From 528f51a07a828d3593ae87b8cf74ba66b0d5883a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 04:44:34 +0000 Subject: [PATCH 10/12] chore(deps): bump bufbuild/buf-setup-action from 1.45.0 to 1.46.0 (#2102) * chore(deps): bump bufbuild/buf-setup-action from 1.45.0 to 1.46.0 Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.45.0 to 1.46.0. - [Release notes](https://github.com/bufbuild/buf-setup-action/releases) - [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.45.0...v1.46.0) --- updated-dependencies: - dependency-name: bufbuild/buf-setup-action dependency-type: direct:production update-type: version-update:semver-minor ... * Updated changelog - dependabot --------- Signed-off-by: Unique-Divine Co-authored-by: Unique Divine <51418232+Unique-Divine@users.noreply.github.com> Co-authored-by: Unique-Divine --- .github/workflows/proto-lint.yml | 4 ++-- CHANGELOG.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/proto-lint.yml b/.github/workflows/proto-lint.yml index 08b3ddb65..318fcc185 100644 --- a/.github/workflows/proto-lint.yml +++ b/.github/workflows/proto-lint.yml @@ -22,7 +22,7 @@ jobs: # timeout-minutes: 5 # steps: # - uses: actions/checkout@v4 - # - uses: bufbuild/buf-setup-action@v1.45.0 + # - uses: bufbuild/buf-setup-action@v1.46.0 # - uses: bufbuild/buf-lint-action@v1 # with: # input: "proto" @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.45.0 + - uses: bufbuild/buf-setup-action@v1.46.0 with: github_token: ${{ github.token }} - uses: bufbuild/buf-breaking-action@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9467ff398..0c017d74e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -240,7 +240,7 @@ tests for race conditions within funtoken precompile - Bump `github.com/hashicorp/go-getter` from 1.7.1 to 1.7.5 ([#1858](https://github.com/NibiruChain/nibiru/pull/1858), [#1938](https://github.com/NibiruChain/nibiru/pull/1938)) - Bump `github.com/btcsuite/btcd` from 0.23.3 to 0.24.2 ([#1862](https://github.com/NibiruChain/nibiru/pull/1862), [#2070](https://github.com/NibiruChain/nibiru/pull/2070)) - Bump `pozetroninc/github-action-get-latest-release` from 0.7.0 to 0.8.0 ([#1863](https://github.com/NibiruChain/nibiru/pull/1863)) -- Bump `bufbuild/buf-setup-action` from 1.30.1 to 1.45.0 ([#1891](https://github.com/NibiruChain/nibiru/pull/1891), [#1900](https://github.com/NibiruChain/nibiru/pull/1900), [#1923](https://github.com/NibiruChain/nibiru/pull/1923), [#1972](https://github.com/NibiruChain/nibiru/pull/1972), [#1974](https://github.com/NibiruChain/nibiru/pull/1974), [#1988](https://github.com/NibiruChain/nibiru/pull/1988), [#2043](https://github.com/NibiruChain/nibiru/pull/2043), [#2057](https://github.com/NibiruChain/nibiru/pull/2057), [#2062](https://github.com/NibiruChain/nibiru/pull/2062), [#2069](https://github.com/NibiruChain/nibiru/pull/2069)) +- Bump `bufbuild/buf-setup-action` from 1.30.1 to 1.46.0 ([#1891](https://github.com/NibiruChain/nibiru/pull/1891), [#1900](https://github.com/NibiruChain/nibiru/pull/1900), [#1923](https://github.com/NibiruChain/nibiru/pull/1923), [#1972](https://github.com/NibiruChain/nibiru/pull/1972), [#1974](https://github.com/NibiruChain/nibiru/pull/1974), [#1988](https://github.com/NibiruChain/nibiru/pull/1988), [#2043](https://github.com/NibiruChain/nibiru/pull/2043), [#2057](https://github.com/NibiruChain/nibiru/pull/2057), [#2062](https://github.com/NibiruChain/nibiru/pull/2062), [#2069](https://github.com/NibiruChain/nibiru/pull/2069), [#2102](https://github.com/NibiruChain/nibiru/pull/2102)) - Bump `axios` from 1.7.3 to 1.7.4 ([#2016](https://github.com/NibiruChain/nibiru/pull/2016)) - Bump `github.com/CosmWasm/wasmvm` from 1.5.0 to 1.5.5 ([#2047](https://github.com/NibiruChain/nibiru/pull/2047)) - Bump `docker/build-push-action` from 5 to 6 ([#1924](https://github.com/NibiruChain/nibiru/pull/1924)) From 1c8df54e0021f295d7cb9c18a6499b2a19f1a071 Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Mon, 4 Nov 2024 21:53:59 +0400 Subject: [PATCH 11/12] test(evm): precompile call with revert (#2105) * test(evm): precompile call with revert * chore: changelog update --- CHANGELOG.md | 1 + .../TestPrecompileSelfCallRevert.json | 78 ++++++++++ .../TestPrecompileSelfCallRevert.sol | 62 ++++++++ x/evm/embeds/embeds.go | 13 ++ x/evm/keeper/funtoken_from_coin_test.go | 143 ++++++++++++++++-- 5 files changed, 285 insertions(+), 12 deletions(-) create mode 100644 x/evm/embeds/artifacts/contracts/TestPrecompileSelfCallRevert.sol/TestPrecompileSelfCallRevert.json create mode 100644 x/evm/embeds/contracts/TestPrecompileSelfCallRevert.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c017d74e..ca1037d84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ depend on x/bank, such as the EVM and Wasm modules. tests for race conditions within funtoken precompile - [#2100](https://github.com/NibiruChain/nibiru/pull/2100) - refactor: cleanup statedb and precompile sections - [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling +- [#2105](https://github.com/NibiruChain/nibiru/pull/2105) - test(evm): precompile call with revert #### Nibiru EVM | Before Audit 1 - 2024-10-18 diff --git a/x/evm/embeds/artifacts/contracts/TestPrecompileSelfCallRevert.sol/TestPrecompileSelfCallRevert.json b/x/evm/embeds/artifacts/contracts/TestPrecompileSelfCallRevert.sol/TestPrecompileSelfCallRevert.json new file mode 100644 index 000000000..c56dfefac --- /dev/null +++ b/x/evm/embeds/artifacts/contracts/TestPrecompileSelfCallRevert.sol/TestPrecompileSelfCallRevert.json @@ -0,0 +1,78 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestPrecompileSelfCallRevert", + "sourceName": "contracts/TestPrecompileSelfCallRevert.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "erc20_", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "nativeRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nativeAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "precompileRecipient", + "type": "string" + }, + { + "internalType": "uint256", + "name": "precompileAmount", + "type": "uint256" + } + ], + "name": "selfCallTransferFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "nativeRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nativeAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "precompileRecipient", + "type": "string" + }, + { + "internalType": "uint256", + "name": "precompileAmount", + "type": "uint256" + } + ], + "name": "transferFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60806040526000600155604051610c8e380380610c8e833981810160405281019061002a91906100d3565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610100565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a082610075565b9050919050565b6100b081610095565b81146100bb57600080fd5b50565b6000815190506100cd816100a7565b92915050565b6000602082840312156100e9576100e8610070565b5b60006100f7848285016100be565b91505092915050565b610b7f8061010f6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636ad4fe961461003b578063705964db14610057575b600080fd5b610055600480360381019061005091906106c1565b610073565b005b610071600480360381019061006c91906106c1565b610208565b005b8373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050506100e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100de906107a1565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684866040518463ffffffff1660e01b81526004016101489392919061085f565b6020604051808303816000875af1158015610167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061018b91906108b2565b9050818114610199856102b2565b6101a2846102b2565b6040516020016101b39291906109d9565b60405160208183030381529060405290610203576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fa9190610a26565b60405180910390fd5b600080fd5b6001600081548092919061021b90610a77565b91905055503073ffffffffffffffffffffffffffffffffffffffff16636ad4fe96858585856040518563ffffffff1660e01b815260040161025f9493929190610ace565b600060405180830381600087803b15801561027957600080fd5b505af192505050801561028a575060015b6102ab57600160008154809291906102a190610a77565b91905055506102ac565b5b50505050565b6060600060016102c184610380565b01905060008167ffffffffffffffff8111156102e0576102df610596565b5b6040519080825280601f01601f1916602001820160405280156103125781602001600182028036833780820191505090505b509050600082602001820190505b600115610375578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161036957610368610b1a565b5b04945060008503610320575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106103de577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816103d4576103d3610b1a565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061041b576d04ee2d6d415b85acef8100000000838161041157610410610b1a565b5b0492506020810190505b662386f26fc10000831061044a57662386f26fc1000083816104405761043f610b1a565b5b0492506010810190505b6305f5e1008310610473576305f5e100838161046957610468610b1a565b5b0492506008810190505b612710831061049857612710838161048e5761048d610b1a565b5b0492506004810190505b606483106104bb57606483816104b1576104b0610b1a565b5b0492506002810190505b600a83106104ca576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610512826104e7565b9050919050565b61052281610507565b811461052d57600080fd5b50565b60008135905061053f81610519565b92915050565b6000819050919050565b61055881610545565b811461056357600080fd5b50565b6000813590506105758161054f565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6105ce82610585565b810181811067ffffffffffffffff821117156105ed576105ec610596565b5b80604052505050565b60006106006104d3565b905061060c82826105c5565b919050565b600067ffffffffffffffff82111561062c5761062b610596565b5b61063582610585565b9050602081019050919050565b82818337600083830152505050565b600061066461065f84610611565b6105f6565b9050828152602081018484840111156106805761067f610580565b5b61068b848285610642565b509392505050565b600082601f8301126106a8576106a761057b565b5b81356106b8848260208601610651565b91505092915050565b600080600080608085870312156106db576106da6104dd565b5b60006106e987828801610530565b94505060206106fa87828801610566565b935050604085013567ffffffffffffffff81111561071b5761071a6104e2565b5b61072787828801610693565b925050606061073887828801610566565b91505092959194509250565b600082825260208201905092915050565b7f455448207472616e73666572206661696c656400000000000000000000000000600082015250565b600061078b601383610744565b915061079682610755565b602082019050919050565b600060208201905081810360008301526107ba8161077e565b9050919050565b60006107cc826104e7565b9050919050565b6107dc816107c1565b82525050565b6107eb81610545565b82525050565b600081519050919050565b60005b8381101561081a5780820151818401526020810190506107ff565b60008484015250505050565b6000610831826107f1565b61083b8185610744565b935061084b8185602086016107fc565b61085481610585565b840191505092915050565b600060608201905061087460008301866107d3565b61088160208301856107e2565b81810360408301526108938184610826565b9050949350505050565b6000815190506108ac8161054f565b92915050565b6000602082840312156108c8576108c76104dd565b5b60006108d68482850161089d565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b6000610946603d836108df565b9150610951826108ea565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b600061098d826107f1565b61099781856108df565b93506109a78185602086016107fc565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b60006109e482610939565b91506109ef8261095c565b600b820191506109ff8285610982565b9150610a0a826109b3565b600982019150610a1a8284610982565b91508190509392505050565b60006020820190508181036000830152610a408184610826565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610a8282610545565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610ab457610ab3610a48565b5b600182019050919050565b610ac881610507565b82525050565b6000608082019050610ae36000830187610abf565b610af060208301866107e2565b8181036040830152610b028185610826565b9050610b1160608301846107e2565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212209f94c0998ce7cd55cbc2c6e9d67d15c37043043fd2ad0f792c2c2c8b09b8284764736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80636ad4fe961461003b578063705964db14610057575b600080fd5b610055600480360381019061005091906106c1565b610073565b005b610071600480360381019061006c91906106c1565b610208565b005b8373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050506100e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100de906107a1565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684866040518463ffffffff1660e01b81526004016101489392919061085f565b6020604051808303816000875af1158015610167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061018b91906108b2565b9050818114610199856102b2565b6101a2846102b2565b6040516020016101b39291906109d9565b60405160208183030381529060405290610203576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fa9190610a26565b60405180910390fd5b600080fd5b6001600081548092919061021b90610a77565b91905055503073ffffffffffffffffffffffffffffffffffffffff16636ad4fe96858585856040518563ffffffff1660e01b815260040161025f9493929190610ace565b600060405180830381600087803b15801561027957600080fd5b505af192505050801561028a575060015b6102ab57600160008154809291906102a190610a77565b91905055506102ac565b5b50505050565b6060600060016102c184610380565b01905060008167ffffffffffffffff8111156102e0576102df610596565b5b6040519080825280601f01601f1916602001820160405280156103125781602001600182028036833780820191505090505b509050600082602001820190505b600115610375578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161036957610368610b1a565b5b04945060008503610320575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106103de577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816103d4576103d3610b1a565b5b0492506040810190505b6d04ee2d6d415b85acef8100000000831061041b576d04ee2d6d415b85acef8100000000838161041157610410610b1a565b5b0492506020810190505b662386f26fc10000831061044a57662386f26fc1000083816104405761043f610b1a565b5b0492506010810190505b6305f5e1008310610473576305f5e100838161046957610468610b1a565b5b0492506008810190505b612710831061049857612710838161048e5761048d610b1a565b5b0492506004810190505b606483106104bb57606483816104b1576104b0610b1a565b5b0492506002810190505b600a83106104ca576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610512826104e7565b9050919050565b61052281610507565b811461052d57600080fd5b50565b60008135905061053f81610519565b92915050565b6000819050919050565b61055881610545565b811461056357600080fd5b50565b6000813590506105758161054f565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6105ce82610585565b810181811067ffffffffffffffff821117156105ed576105ec610596565b5b80604052505050565b60006106006104d3565b905061060c82826105c5565b919050565b600067ffffffffffffffff82111561062c5761062b610596565b5b61063582610585565b9050602081019050919050565b82818337600083830152505050565b600061066461065f84610611565b6105f6565b9050828152602081018484840111156106805761067f610580565b5b61068b848285610642565b509392505050565b600082601f8301126106a8576106a761057b565b5b81356106b8848260208601610651565b91505092915050565b600080600080608085870312156106db576106da6104dd565b5b60006106e987828801610530565b94505060206106fa87828801610566565b935050604085013567ffffffffffffffff81111561071b5761071a6104e2565b5b61072787828801610693565b925050606061073887828801610566565b91505092959194509250565b600082825260208201905092915050565b7f455448207472616e73666572206661696c656400000000000000000000000000600082015250565b600061078b601383610744565b915061079682610755565b602082019050919050565b600060208201905081810360008301526107ba8161077e565b9050919050565b60006107cc826104e7565b9050919050565b6107dc816107c1565b82525050565b6107eb81610545565b82525050565b600081519050919050565b60005b8381101561081a5780820151818401526020810190506107ff565b60008484015250505050565b6000610831826107f1565b61083b8185610744565b935061084b8185602086016107fc565b61085481610585565b840191505092915050565b600060608201905061087460008301866107d3565b61088160208301856107e2565b81810360408301526108938184610826565b9050949350505050565b6000815190506108ac8161054f565b92915050565b6000602082840312156108c8576108c76104dd565b5b60006108d68482850161089d565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b6000610946603d836108df565b9150610951826108ea565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b600061098d826107f1565b61099781856108df565b93506109a78185602086016107fc565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b60006109e482610939565b91506109ef8261095c565b600b820191506109ff8285610982565b9150610a0a826109b3565b600982019150610a1a8284610982565b91508190509392505050565b60006020820190508181036000830152610a408184610826565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610a8282610545565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610ab457610ab3610a48565b5b600182019050919050565b610ac881610507565b82525050565b6000608082019050610ae36000830187610abf565b610af060208301866107e2565b8181036040830152610b028185610826565b9050610b1160608301846107e2565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212209f94c0998ce7cd55cbc2c6e9d67d15c37043043fd2ad0f792c2c2c8b09b8284764736f6c63430008180033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/x/evm/embeds/contracts/TestPrecompileSelfCallRevert.sol b/x/evm/embeds/contracts/TestPrecompileSelfCallRevert.sol new file mode 100644 index 000000000..972691a71 --- /dev/null +++ b/x/evm/embeds/contracts/TestPrecompileSelfCallRevert.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import "./IFunToken.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +contract TestPrecompileSelfCallRevert { + address erc20; + uint counter = 0; + + constructor(address erc20_) payable { + erc20 = erc20_; + } + + function selfCallTransferFunds( + address payable nativeRecipient, + uint256 nativeAmount, + string memory precompileRecipient, + uint256 precompileAmount + ) external { + counter++; + try + TestPrecompileSelfCallRevert(payable(address(this))).transferFunds( + nativeRecipient, + nativeAmount, + precompileRecipient, + precompileAmount + ) + {} catch // [1] + { + counter++; + } + } + + function transferFunds( + address payable nativeRecipient, + uint256 nativeAmount, + string memory precompileRecipient, + uint256 precompileAmount + ) external { + require(nativeRecipient.send(nativeAmount), "ETH transfer failed"); // wei + + uint256 sentAmount = FUNTOKEN_PRECOMPILE.bankSend( + erc20, + precompileAmount, // micro-WNIBI + precompileRecipient + ); + + require( + sentAmount == precompileAmount, + string.concat( + "IFunToken.bankSend succeeded but transferred the wrong amount", + "sentAmount ", + Strings.toString(nativeAmount), + "expected ", + Strings.toString(precompileAmount) + ) + ); + + revert(); // [4] + } +} diff --git a/x/evm/embeds/embeds.go b/x/evm/embeds/embeds.go index 12b0d981c..202b26525 100644 --- a/x/evm/embeds/embeds.go +++ b/x/evm/embeds/embeds.go @@ -33,6 +33,8 @@ var ( testERC20TransferThenPrecompileSendJson []byte //go:embed artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json testNativeSendThenPrecompileSendJson []byte + //go:embed artifacts/contracts/TestPrecompileSelfCallRevert.sol/TestPrecompileSelfCallRevert.json + testPrecompileSelfCallRevertJson []byte ) var ( @@ -96,6 +98,16 @@ var ( Name: "TestERC20TransferThenPrecompileSend.sol", EmbedJSON: testERC20TransferThenPrecompileSendJson, } + + // SmartContract_TestPrecompileSelfCallRevert is a test contract + // that creates another instance of itself, calls the precompile method and then force reverts. + // It tests a race condition where the state DB commit + // may save the wrong state before the precompile execution, not revert it entirely, + // potentially causing an infinite mint of funds. + SmartContract_TestPrecompileSelfCallRevert = CompiledEvmContract{ + Name: "TestPrecompileSelfCallRevert.sol", + EmbedJSON: testPrecompileSelfCallRevertJson, + } ) func init() { @@ -108,6 +120,7 @@ func init() { SmartContract_TestERC20MaliciousTransfer.MustLoad() SmartContract_TestNativeSendThenPrecompileSendJson.MustLoad() SmartContract_TestERC20TransferThenPrecompileSend.MustLoad() + SmartContract_TestPrecompileSelfCallRevert.MustLoad() } type CompiledEvmContract struct { diff --git a/x/evm/keeper/funtoken_from_coin_test.go b/x/evm/keeper/funtoken_from_coin_test.go index f69143772..646391eea 100644 --- a/x/evm/keeper/funtoken_from_coin_test.go +++ b/x/evm/keeper/funtoken_from_coin_test.go @@ -447,23 +447,142 @@ func (s *FunTokenFromCoinSuite) TestERC20TransferThenPrecompileSend() { ) s.Require().NoError(err) - // Check 1: Alice has 9 NIBI in bank - aliceBankBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, alice.NibiruAddr, bankDenom) - s.Require().Equal(sdk.NewInt(9e6), aliceBankBalance.Amount) + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: alice.EthAddr, + BalanceBank: big.NewInt(9e6), + BalanceERC20: big.NewInt(1e6), + Description: "Alice has 9 NIBI / 1 WNIBI", + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: testContractAddr, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + Description: "Test contract 0 NIBI / 0 WNIBI", + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: evm.EVM_MODULE_ADDRESS, + BalanceBank: big.NewInt(1e6), + BalanceERC20: big.NewInt(0e6), + Description: "Module account has 1 NIBI escrowed", + }.Assert(s.T(), deps) +} - // Check 2: Alice has 1 WNIBI on ERC20 - aliceERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funToken.Erc20Addr.Address, alice.EthAddr, deps.Ctx) +// TestPrecompileSelfCallRevert +// 1. Creates a funtoken from coin. +// 2. Using the test contract, creates another instance of itself, calls the precompile method and then force reverts. +// It tests a race condition where the state DB commit +// may save the wrong state before the precompile execution, not revert it entirely, +// potentially causing an infinite mint of funds. +// +// INITIAL STATE: +// - Test contract funds: 10 NIBI, 10 WNIBI +// CONTRACT CALL: +// - Sends 1 NIBI to Alice using native send and 1 WNIBI -> NIBI to Charles using precompile +// EXPECTED: +// - all changes reverted +// - Test contract funds: 10 NIBI, 10 WNIBI +// - Alice: 0 NIBI +// - Charles: 0 NIBI +// - Module account: 10 NIBI escrowed (which Test contract holds as 10 WNIBI) +func (s *FunTokenFromCoinSuite) TestPrecompileSelfCallRevert() { + deps := evmtest.NewTestDeps() + bankDenom := evm.EVMBankDenom + + // Initial setup + funToken := s.fundAndCreateFunToken(deps, 10e6) + + s.T().Log("Deploy Test Contract") + deployResp, err := evmtest.DeployContract( + &deps, + embeds.SmartContract_TestPrecompileSelfCallRevert, + funToken.Erc20Addr.Address, + ) s.Require().NoError(err) - s.Require().Zero(big.NewInt(1e6).Cmp(aliceERC20Balance)) - // Check 3: test contract has 0 WNIBI on ERC20 - testContractERC20Balance, err := deps.EvmKeeper.ERC20().BalanceOf(funToken.Erc20Addr.Address, testContractAddr, deps.Ctx) + testContractAddr := deployResp.ContractAddr + + s.T().Log("Convert bank coin to erc-20: give test contract 10 WNIBI (erc20)") + _, err = deps.EvmKeeper.ConvertCoinToEvm( + sdk.WrapSDKContext(deps.Ctx), + &evm.MsgConvertCoinToEvm{ + Sender: deps.Sender.NibiruAddr.String(), + BankCoin: sdk.NewCoin(bankDenom, sdk.NewInt(10e6)), + ToEthAddr: eth.EIP55Addr{Address: testContractAddr}, + }, + ) s.Require().NoError(err) - s.Require().Zero(big.NewInt(0).Cmp(testContractERC20Balance)) - // Check 4: module balance has 1 NIBI escrowed (which Alice holds as 1 WNIBI) - moduleBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, authtypes.NewModuleAddress(evm.ModuleName), bankDenom) - s.Require().Equal(sdk.NewInt(1e6), moduleBalance.Amount) + s.T().Log("Give the test contract 10 NIBI (native)") + s.Require().NoError(testapp.FundAccount( + deps.App.BankKeeper, + deps.Ctx, + eth.EthAddrToNibiruAddr(testContractAddr), + sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(10e6))), + )) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: testContractAddr, + BalanceBank: big.NewInt(10e6), + BalanceERC20: big.NewInt(10e6), + Description: "Initial contract state sanity check: 10 NIBI / 10 WNIBI", + }.Assert(s.T(), deps) + + // Create Alice and Charles. Contract will try to send Alice native coins and send Charles tokens via bankSend + alice := evmtest.NewEthPrivAcc() + charles := evmtest.NewEthPrivAcc() + + s.T().Log("call test contract") + _, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_TestPrecompileSelfCallRevert.ABI, + deps.Sender.EthAddr, + &testContractAddr, + true, + "selfCallTransferFunds", + alice.EthAddr, + evm.NativeToWei(big.NewInt(1e6)), // native send uses wei units, + charles.NibiruAddr.String(), + big.NewInt(9e6), // for precompile bankSend: 6 decimals + ) + s.Require().NoError(err) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: alice.EthAddr, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + Description: "Alice has 0 NIBI / 0 WNIBI", + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: charles.EthAddr, + BalanceBank: big.NewInt(0), + BalanceERC20: big.NewInt(0), + Description: "Charles has 0 NIBI / 0 WNIBI", + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: testContractAddr, + BalanceBank: big.NewInt(10e6), + BalanceERC20: big.NewInt(10e6), + Description: "Test contract has 10 NIBI / 10 WNIBI", + }.Assert(s.T(), deps) + + evmtest.FunTokenBalanceAssert{ + FunToken: funToken, + Account: evm.EVM_MODULE_ADDRESS, + BalanceBank: big.NewInt(10e6), + BalanceERC20: big.NewInt(0), + Description: "Module account has 10 NIBI escrowed", + }.Assert(s.T(), deps) } // fundAndCreateFunToken creates initial setup for tests From 94db838eb391a0cef6b418af96e27220b3d73bf4 Mon Sep 17 00:00:00 2001 From: Oleg Nikonychev Date: Tue, 5 Nov 2024 18:11:00 +0400 Subject: [PATCH 12/12] feat(evm): gas usage in precompiles: limits, local gas meters (#2093) * feat(evm): gas usage in precompiles: limits, local gas meters * fix: local precompile gas meters * test(precompile): tests for precompile local gas meters * fix: increased funtoken precompile gas limit in favor to heavy user contracts * chore: moved evm grpc calls back to msg_server.go * cleanup * test: added sad test for precompile local gas * fix: duplicate import * chore: cleanup * refactor: clean up imports * fix: bad merge * fix: force switched precompile ctx gas configs * cleanup * fix: gas used discrepancy in estimate gas vs actual execution gas * chore: cleaned up solidity contracts calling bankSend precompile * refactor(gas): simplify estimate gas error handling * refactor(gas): simplify EstimateGasForEvmCallType * fix: comment on HandleOutOfGasPanic * fix: missing gas limit call * test: add WasmGasLimitQuery * refactor: update CallContractWIthInput * refactor(evm): prefer CallContract over CallContractWithInput * refactor: add clarifying context to error messages * fix: eth api test --------- Co-authored-by: Kevin Yang <5478483+k-yang@users.noreply.github.com> --- CHANGELOG.md | 4 +- eth/rpc/backend/call_tx.go | 6 +- eth/rpc/rpcapi/eth_api_test.go | 2 +- evm-e2e/.gitignore | 4 + .../TestERC20TransferThenPrecompileSend.json | 4 +- .../TestFunTokenPrecompileLocalGas.json | 63 ++++++ .../TestERC20TransferThenPrecompileSend.sol | 22 +- .../TestFunTokenPrecompileLocalGas.sol | 60 +++++ x/evm/embeds/embeds.go | 9 + x/evm/embeds/embeds_test.go | 1 + x/evm/errors.go | 57 +---- x/evm/evmmodule/genesis_test.go | 4 +- x/evm/evmtest/test_deps.go | 5 + x/evm/keeper/call_contract.go | 150 +++++++++++++ x/evm/keeper/erc20.go | 206 +++--------------- x/evm/keeper/erc20_test.go | 6 +- x/evm/keeper/funtoken_from_coin.go | 2 +- x/evm/keeper/funtoken_from_coin_test.go | 7 + x/evm/keeper/funtoken_from_erc20_test.go | 12 + x/evm/keeper/gas_fees.go | 11 +- x/evm/keeper/grpc_query.go | 48 ++-- x/evm/keeper/keeper.go | 46 +++- x/evm/keeper/msg_server.go | 131 ++++++----- x/evm/msg.go | 10 +- x/evm/precompile/funtoken.go | 51 ++++- x/evm/precompile/funtoken_test.go | 108 ++++++++- x/evm/precompile/oracle.go | 2 +- x/evm/precompile/oracle_test.go | 15 +- x/evm/precompile/precompile.go | 23 +- x/evm/precompile/test/export.go | 71 +++--- x/evm/precompile/wasm.go | 9 +- x/evm/precompile/wasm_test.go | 129 ++++++----- x/evm/statedb/journal_test.go | 9 +- 33 files changed, 824 insertions(+), 463 deletions(-) create mode 100644 evm-e2e/.gitignore create mode 100644 x/evm/embeds/artifacts/contracts/TestFunTokenPrecompileLocalGas.sol/TestFunTokenPrecompileLocalGas.json create mode 100644 x/evm/embeds/contracts/TestFunTokenPrecompileLocalGas.sol create mode 100644 x/evm/keeper/call_contract.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ca1037d84..f4e5fa640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ for (1) ERC20 transfers with tokens that return false success values instead of throwing an error and (2) ERC20 transfers with other operations that don't bring about the expected resulting balance for the transfer recipient. - [#2091](https://github.com/NibiruChain/nibiru/pull/2091) - feat(evm): add fun token creation fee validation +- [#2093](https://github.com/NibiruChain/nibiru/pull/2093) - feat(evm): gas usage in precompiles: limits, local gas meters - [#2092](https://github.com/NibiruChain/nibiru/pull/2092) - feat(evm): add validation for wasm multi message execution - [#2094](https://github.com/NibiruChain/nibiru/pull/2094) - fix(evm): Following from the changs in #2086, this pull request implements a new `JournalChange` @@ -92,7 +93,7 @@ The `NibiruBankKeeper` holds a reference to the current EVM `StateDB` and record balance changes in wei as journal changes automatically. This guarantees that commits and reversions of the `StateDB` do not misalign with the state of the Bank module. This code change uses the `NibiruBankKeeper` on all modules that -depend on x/bank, such as the EVM and Wasm modules. +depend on x/bank, such as the EVM and Wasm modules. - [#2097](https://github.com/NibiruChain/nibiru/pull/2097) - feat(evm): Add new query to get dated price from the oracle precompile - [#2098](https://github.com/NibiruChain/nibiru/pull/2098) - test(evm): statedb tests for race conditions within funtoken precompile @@ -100,7 +101,6 @@ tests for race conditions within funtoken precompile - [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling - [#2105](https://github.com/NibiruChain/nibiru/pull/2105) - test(evm): precompile call with revert - #### Nibiru EVM | Before Audit 1 - 2024-10-18 - [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): protos, eth types, and evm module types diff --git a/eth/rpc/backend/call_tx.go b/eth/rpc/backend/call_tx.go index 3e4de8037..66deeb8fb 100644 --- a/eth/rpc/backend/call_tx.go +++ b/eth/rpc/backend/call_tx.go @@ -295,10 +295,10 @@ func (b *Backend) DoCall( } if res.Failed() { - if res.VmError != vm.ErrExecutionReverted.Error() { - return nil, status.Error(codes.Internal, res.VmError) + if res.VmError == vm.ErrExecutionReverted.Error() { + return nil, evm.NewRevertError(res.Ret) } - return nil, evm.NewExecErrorWithReason(res.Ret) + return nil, status.Error(codes.Internal, res.VmError) } return res, nil diff --git a/eth/rpc/rpcapi/eth_api_test.go b/eth/rpc/rpcapi/eth_api_test.go index e20513f5e..1a599d2f1 100644 --- a/eth/rpc/rpcapi/eth_api_test.go +++ b/eth/rpc/rpcapi/eth_api_test.go @@ -193,7 +193,7 @@ func (s *NodeSuite) Test_EstimateGas() { } { msg.Value = msgValue _, err = s.ethClient.EstimateGas(context.Background(), msg) - s.ErrorContains(err, "StateDB: wei amount is too small") + s.ErrorContains(err, "wei amount is too small") } } diff --git a/evm-e2e/.gitignore b/evm-e2e/.gitignore new file mode 100644 index 000000000..3419dc450 --- /dev/null +++ b/evm-e2e/.gitignore @@ -0,0 +1,4 @@ +types +artifacts +cache +.env diff --git a/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json b/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json index 2d58f750e..3a1411d37 100644 --- a/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json +++ b/x/evm/embeds/artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json @@ -43,8 +43,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b50604051610974380380610974833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b61085d806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212203da3b9141c515078ba917a5b792ee843396b82d45e2ef60e0d6307c236e8c30664736f6c63430008180033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061049f565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a7929190610590565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906105f1565b610129576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101209061067b565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683856040516024016101799392919061072a565b6040516020818303038152906040527f03003bc5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020391906107af565b6000604051808303816000865af19150503d8060008114610240576040519150601f19603f3d011682016040523d82523d6000602084013e610245565b606091505b5050905080604051602001610259906107ec565b604051602081830303815290604052906102a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a09190610805565b60405180910390fd5b505050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102f0826102c5565b9050919050565b610300816102e5565b811461030b57600080fd5b50565b60008135905061031d816102f7565b92915050565b6000819050919050565b61033681610323565b811461034157600080fd5b50565b6000813590506103538161032d565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103ac82610363565b810181811067ffffffffffffffff821117156103cb576103ca610374565b5b80604052505050565b60006103de6102b1565b90506103ea82826103a3565b919050565b600067ffffffffffffffff82111561040a57610409610374565b5b61041382610363565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6103d4565b90508281526020810184848401111561045e5761045d61035e565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610359565b5b813561049684826020860161042f565b91505092915050565b600080600080608085870312156104b9576104b86102bb565b5b60006104c78782880161030e565b94505060206104d887828801610344565b935050604085013567ffffffffffffffff8111156104f9576104f86102c0565b5b61050587828801610471565b925050606061051687828801610344565b91505092959194509250565b6000819050919050565b600061054761054261053d846102c5565b610522565b6102c5565b9050919050565b60006105598261052c565b9050919050565b600061056b8261054e565b9050919050565b61057b81610560565b82525050565b61058a81610323565b82525050565b60006040820190506105a56000830185610572565b6105b26020830184610581565b9392505050565b60008115159050919050565b6105ce816105b9565b81146105d957600080fd5b50565b6000815190506105eb816105c5565b92915050565b600060208284031215610607576106066102bb565b5b6000610615848285016105dc565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b600061066560168361061e565b91506106708261062f565b602082019050919050565b6000602082019050818103600083015261069481610658565b9050919050565b60006106a6826102c5565b9050919050565b6106b68161069b565b82525050565b600081519050919050565b60005b838110156106e55780820151818401526020810190506106ca565b60008484015250505050565b60006106fc826106bc565b610706818561061e565b93506107168185602086016106c7565b61071f81610363565b840191505092915050565b600060608201905061073f60008301866106ad565b61074c6020830185610581565b818103604083015261075e81846106f1565b9050949350505050565b600081519050919050565b600081905092915050565b600061078982610768565b6107938185610773565b93506107a38185602086016106c7565b80840191505092915050565b60006107bb828461077e565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b60006107f7826107c6565b601782019150819050919050565b6000602082019050818103600083015261081f81846106f1565b90509291505056fea26469706673582212203da3b9141c515078ba917a5b792ee843396b82d45e2ef60e0d6307c236e8c30664736f6c63430008180033", + "bytecode": "0x608060405234801561001057600080fd5b50604051610c4c380380610c4c833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b610b35806101176000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061065c565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a792919061074d565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906107ae565b610129576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012090610838565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684866040518463ffffffff1660e01b815260040161018a939291906108e7565b6020604051808303816000875af11580156101a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101cd919061093a565b90508181146101db8261024d565b6101e48461024d565b6040516020016101f5929190610a61565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610aae565b60405180910390fd5b505050505050565b60606000600161025c8461031b565b01905060008167ffffffffffffffff81111561027b5761027a610531565b5b6040519080825280601f01601f1916602001820160405280156102ad5781602001600182028036833780820191505090505b509050600082602001820190505b600115610310578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161030457610303610ad0565b5b049450600085036102bb575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610379577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161036f5761036e610ad0565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106103b6576d04ee2d6d415b85acef810000000083816103ac576103ab610ad0565b5b0492506020810190505b662386f26fc1000083106103e557662386f26fc1000083816103db576103da610ad0565b5b0492506010810190505b6305f5e100831061040e576305f5e100838161040457610403610ad0565b5b0492506008810190505b612710831061043357612710838161042957610428610ad0565b5b0492506004810190505b60648310610456576064838161044c5761044b610ad0565b5b0492506002810190505b600a8310610465576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006104ad82610482565b9050919050565b6104bd816104a2565b81146104c857600080fd5b50565b6000813590506104da816104b4565b92915050565b6000819050919050565b6104f3816104e0565b81146104fe57600080fd5b50565b600081359050610510816104ea565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61056982610520565b810181811067ffffffffffffffff8211171561058857610587610531565b5b80604052505050565b600061059b61046e565b90506105a78282610560565b919050565b600067ffffffffffffffff8211156105c7576105c6610531565b5b6105d082610520565b9050602081019050919050565b82818337600083830152505050565b60006105ff6105fa846105ac565b610591565b90508281526020810184848401111561061b5761061a61051b565b5b6106268482856105dd565b509392505050565b600082601f83011261064357610642610516565b5b81356106538482602086016105ec565b91505092915050565b6000806000806080858703121561067657610675610478565b5b6000610684878288016104cb565b945050602061069587828801610501565b935050604085013567ffffffffffffffff8111156106b6576106b561047d565b5b6106c28782880161062e565b92505060606106d387828801610501565b91505092959194509250565b6000819050919050565b60006107046106ff6106fa84610482565b6106df565b610482565b9050919050565b6000610716826106e9565b9050919050565b60006107288261070b565b9050919050565b6107388161071d565b82525050565b610747816104e0565b82525050565b6000604082019050610762600083018561072f565b61076f602083018461073e565b9392505050565b60008115159050919050565b61078b81610776565b811461079657600080fd5b50565b6000815190506107a881610782565b92915050565b6000602082840312156107c4576107c3610478565b5b60006107d284828501610799565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b60006108226016836107db565b915061082d826107ec565b602082019050919050565b6000602082019050818103600083015261085181610815565b9050919050565b600061086382610482565b9050919050565b61087381610858565b82525050565b600081519050919050565b60005b838110156108a2578082015181840152602081019050610887565b60008484015250505050565b60006108b982610879565b6108c381856107db565b93506108d3818560208601610884565b6108dc81610520565b840191505092915050565b60006060820190506108fc600083018661086a565b610909602083018561073e565b818103604083015261091b81846108ae565b9050949350505050565b600081519050610934816104ea565b92915050565b6000602082840312156109505761094f610478565b5b600061095e84828501610925565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b60006109ce603d83610967565b91506109d982610972565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b6000610a1582610879565b610a1f8185610967565b9350610a2f818560208601610884565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b6000610a6c826109c1565b9150610a77826109e4565b600b82019150610a878285610a0a565b9150610a9282610a3b565b600982019150610aa28284610a0a565b91508190509392505050565b60006020820190508181036000830152610ac881846108ae565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220f0624f3122eb5227189289362e14705abd19c84ea5ee45bc30dbf8eedcb157b064736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063264c325814610030575b600080fd5b61004a6004803603810190610045919061065c565b61004c565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b81526004016100a792919061074d565b6020604051808303816000875af11580156100c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ea91906107ae565b610129576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012090610838565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684866040518463ffffffff1660e01b815260040161018a939291906108e7565b6020604051808303816000875af11580156101a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101cd919061093a565b90508181146101db8261024d565b6101e48461024d565b6040516020016101f5929190610a61565b60405160208183030381529060405290610245576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023c9190610aae565b60405180910390fd5b505050505050565b60606000600161025c8461031b565b01905060008167ffffffffffffffff81111561027b5761027a610531565b5b6040519080825280601f01601f1916602001820160405280156102ad5781602001600182028036833780820191505090505b509050600082602001820190505b600115610310578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161030457610303610ad0565b5b049450600085036102bb575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610379577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161036f5761036e610ad0565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106103b6576d04ee2d6d415b85acef810000000083816103ac576103ab610ad0565b5b0492506020810190505b662386f26fc1000083106103e557662386f26fc1000083816103db576103da610ad0565b5b0492506010810190505b6305f5e100831061040e576305f5e100838161040457610403610ad0565b5b0492506008810190505b612710831061043357612710838161042957610428610ad0565b5b0492506004810190505b60648310610456576064838161044c5761044b610ad0565b5b0492506002810190505b600a8310610465576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006104ad82610482565b9050919050565b6104bd816104a2565b81146104c857600080fd5b50565b6000813590506104da816104b4565b92915050565b6000819050919050565b6104f3816104e0565b81146104fe57600080fd5b50565b600081359050610510816104ea565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61056982610520565b810181811067ffffffffffffffff8211171561058857610587610531565b5b80604052505050565b600061059b61046e565b90506105a78282610560565b919050565b600067ffffffffffffffff8211156105c7576105c6610531565b5b6105d082610520565b9050602081019050919050565b82818337600083830152505050565b60006105ff6105fa846105ac565b610591565b90508281526020810184848401111561061b5761061a61051b565b5b6106268482856105dd565b509392505050565b600082601f83011261064357610642610516565b5b81356106538482602086016105ec565b91505092915050565b6000806000806080858703121561067657610675610478565b5b6000610684878288016104cb565b945050602061069587828801610501565b935050604085013567ffffffffffffffff8111156106b6576106b561047d565b5b6106c28782880161062e565b92505060606106d387828801610501565b91505092959194509250565b6000819050919050565b60006107046106ff6106fa84610482565b6106df565b610482565b9050919050565b6000610716826106e9565b9050919050565b60006107288261070b565b9050919050565b6107388161071d565b82525050565b610747816104e0565b82525050565b6000604082019050610762600083018561072f565b61076f602083018461073e565b9392505050565b60008115159050919050565b61078b81610776565b811461079657600080fd5b50565b6000815190506107a881610782565b92915050565b6000602082840312156107c4576107c3610478565b5b60006107d284828501610799565b91505092915050565b600082825260208201905092915050565b7f4552432d3230207472616e73666572206661696c656400000000000000000000600082015250565b60006108226016836107db565b915061082d826107ec565b602082019050919050565b6000602082019050818103600083015261085181610815565b9050919050565b600061086382610482565b9050919050565b61087381610858565b82525050565b600081519050919050565b60005b838110156108a2578082015181840152602081019050610887565b60008484015250505050565b60006108b982610879565b6108c381856107db565b93506108d3818560208601610884565b6108dc81610520565b840191505092915050565b60006060820190506108fc600083018661086a565b610909602083018561073e565b818103604083015261091b81846108ae565b9050949350505050565b600081519050610934816104ea565b92915050565b6000602082840312156109505761094f610478565b5b600061095e84828501610925565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b60006109ce603d83610967565b91506109d982610972565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b6000610a1582610879565b610a1f8185610967565b9350610a2f818560208601610884565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b6000610a6c826109c1565b9150610a77826109e4565b600b82019150610a878285610a0a565b9150610a9282610a3b565b600982019150610aa28284610a0a565b91508190509392505050565b60006020820190508181036000830152610ac881846108ae565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220f0624f3122eb5227189289362e14705abd19c84ea5ee45bc30dbf8eedcb157b064736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/x/evm/embeds/artifacts/contracts/TestFunTokenPrecompileLocalGas.sol/TestFunTokenPrecompileLocalGas.json b/x/evm/embeds/artifacts/contracts/TestFunTokenPrecompileLocalGas.sol/TestFunTokenPrecompileLocalGas.json new file mode 100644 index 000000000..723b779b5 --- /dev/null +++ b/x/evm/embeds/artifacts/contracts/TestFunTokenPrecompileLocalGas.sol/TestFunTokenPrecompileLocalGas.json @@ -0,0 +1,63 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestFunTokenPrecompileLocalGas", + "sourceName": "contracts/TestFunTokenPrecompileLocalGas.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "erc20_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "bech32Recipient", + "type": "string" + } + ], + "name": "callBankSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "bech32Recipient", + "type": "string" + }, + { + "internalType": "uint256", + "name": "customGas", + "type": "uint256" + } + ], + "name": "callBankSendLocalGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50604051610b6a380380610b6a833981810160405281019061003291906100db565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610108565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b6100b88161009d565b81146100c357600080fd5b50565b6000815190506100d5816100af565b92915050565b6000602082840312156100f1576100f0610078565b5b60006100ff848285016100c6565b91505092915050565b610a53806101176000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806359b6ed891461003b57806390d2b5e714610057575b600080fd5b6100556004803603810190610050919061066b565b610073565b005b610071600480360381019061006c91906106da565b610198565b005b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc58360008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687876040518563ffffffff1660e01b81526004016100d593929190610805565b60206040518083038160008887f11580156100f4573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906101199190610858565b9050838114610127826102ba565b610130866102ba565b60405160200161014192919061097f565b60405160208183030381529060405290610191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161018891906109cc565b60405180910390fd5b5050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685856040518463ffffffff1660e01b81526004016101f993929190610805565b6020604051808303816000875af1158015610218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023c9190610858565b905082811461024a826102ba565b610253856102ba565b60405160200161026492919061097f565b604051602081830303815290604052906102b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ab91906109cc565b60405180910390fd5b50505050565b6060600060016102c984610388565b01905060008167ffffffffffffffff8111156102e8576102e7610540565b5b6040519080825280601f01601f19166020018201604052801561031a5781602001600182028036833780820191505090505b509050600082602001820190505b60011561037d578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581610371576103706109ee565b5b04945060008503610328575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106103e6577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816103dc576103db6109ee565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310610423576d04ee2d6d415b85acef81000000008381610419576104186109ee565b5b0492506020810190505b662386f26fc10000831061045257662386f26fc100008381610448576104476109ee565b5b0492506010810190505b6305f5e100831061047b576305f5e1008381610471576104706109ee565b5b0492506008810190505b61271083106104a0576127108381610496576104956109ee565b5b0492506004810190505b606483106104c357606483816104b9576104b86109ee565b5b0492506002810190505b600a83106104d2576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b610502816104ef565b811461050d57600080fd5b50565b60008135905061051f816104f9565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6105788261052f565b810181811067ffffffffffffffff8211171561059757610596610540565b5b80604052505050565b60006105aa6104db565b90506105b6828261056f565b919050565b600067ffffffffffffffff8211156105d6576105d5610540565b5b6105df8261052f565b9050602081019050919050565b82818337600083830152505050565b600061060e610609846105bb565b6105a0565b90508281526020810184848401111561062a5761062961052a565b5b6106358482856105ec565b509392505050565b600082601f83011261065257610651610525565b5b81356106628482602086016105fb565b91505092915050565b600080600060608486031215610684576106836104e5565b5b600061069286828701610510565b935050602084013567ffffffffffffffff8111156106b3576106b26104ea565b5b6106bf8682870161063d565b92505060406106d086828701610510565b9150509250925092565b600080604083850312156106f1576106f06104e5565b5b60006106ff85828601610510565b925050602083013567ffffffffffffffff8111156107205761071f6104ea565b5b61072c8582860161063d565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061076182610736565b9050919050565b61077181610756565b82525050565b610780816104ef565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156107c05780820151818401526020810190506107a5565b60008484015250505050565b60006107d782610786565b6107e18185610791565b93506107f18185602086016107a2565b6107fa8161052f565b840191505092915050565b600060608201905061081a6000830186610768565b6108276020830185610777565b818103604083015261083981846107cc565b9050949350505050565b600081519050610852816104f9565b92915050565b60006020828403121561086e5761086d6104e5565b5b600061087c84828501610843565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b60006108ec603d83610885565b91506108f782610890565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b600061093382610786565b61093d8185610885565b935061094d8185602086016107a2565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b600061098a826108df565b915061099582610902565b600b820191506109a58285610928565b91506109b082610959565b6009820191506109c08284610928565b91508190509392505050565b600060208201905081810360008301526109e681846107cc565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212203b80aa046928bf6b13cd29898611f9a4f048688dc21bfd44094fd59d8080e66064736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806359b6ed891461003b57806390d2b5e714610057575b600080fd5b6100556004803603810190610050919061066b565b610073565b005b610071600480360381019061006c91906106da565b610198565b005b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc58360008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687876040518563ffffffff1660e01b81526004016100d593929190610805565b60206040518083038160008887f11580156100f4573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906101199190610858565b9050838114610127826102ba565b610130866102ba565b60405160200161014192919061097f565b60405160208183030381529060405290610191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161018891906109cc565b60405180910390fd5b5050505050565b600061080073ffffffffffffffffffffffffffffffffffffffff166303003bc560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685856040518463ffffffff1660e01b81526004016101f993929190610805565b6020604051808303816000875af1158015610218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023c9190610858565b905082811461024a826102ba565b610253856102ba565b60405160200161026492919061097f565b604051602081830303815290604052906102b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ab91906109cc565b60405180910390fd5b50505050565b6060600060016102c984610388565b01905060008167ffffffffffffffff8111156102e8576102e7610540565b5b6040519080825280601f01601f19166020018201604052801561031a5781602001600182028036833780820191505090505b509050600082602001820190505b60011561037d578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581610371576103706109ee565b5b04945060008503610328575b819350505050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106103e6577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816103dc576103db6109ee565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310610423576d04ee2d6d415b85acef81000000008381610419576104186109ee565b5b0492506020810190505b662386f26fc10000831061045257662386f26fc100008381610448576104476109ee565b5b0492506010810190505b6305f5e100831061047b576305f5e1008381610471576104706109ee565b5b0492506008810190505b61271083106104a0576127108381610496576104956109ee565b5b0492506004810190505b606483106104c357606483816104b9576104b86109ee565b5b0492506002810190505b600a83106104d2576001810190505b80915050919050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b610502816104ef565b811461050d57600080fd5b50565b60008135905061051f816104f9565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6105788261052f565b810181811067ffffffffffffffff8211171561059757610596610540565b5b80604052505050565b60006105aa6104db565b90506105b6828261056f565b919050565b600067ffffffffffffffff8211156105d6576105d5610540565b5b6105df8261052f565b9050602081019050919050565b82818337600083830152505050565b600061060e610609846105bb565b6105a0565b90508281526020810184848401111561062a5761062961052a565b5b6106358482856105ec565b509392505050565b600082601f83011261065257610651610525565b5b81356106628482602086016105fb565b91505092915050565b600080600060608486031215610684576106836104e5565b5b600061069286828701610510565b935050602084013567ffffffffffffffff8111156106b3576106b26104ea565b5b6106bf8682870161063d565b92505060406106d086828701610510565b9150509250925092565b600080604083850312156106f1576106f06104e5565b5b60006106ff85828601610510565b925050602083013567ffffffffffffffff8111156107205761071f6104ea565b5b61072c8582860161063d565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061076182610736565b9050919050565b61077181610756565b82525050565b610780816104ef565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156107c05780820151818401526020810190506107a5565b60008484015250505050565b60006107d782610786565b6107e18185610791565b93506107f18185602086016107a2565b6107fa8161052f565b840191505092915050565b600060608201905061081a6000830186610768565b6108276020830185610777565b818103604083015261083981846107cc565b9050949350505050565b600081519050610852816104f9565b92915050565b60006020828403121561086e5761086d6104e5565b5b600061087c84828501610843565b91505092915050565b600081905092915050565b7f4946756e546f6b656e2e62616e6b53656e64207375636365656465642062757460008201527f207472616e73666572726564207468652077726f6e6720616d6f756e74000000602082015250565b60006108ec603d83610885565b91506108f782610890565b603d82019050919050565b7f73656e74416d6f756e7420000000000000000000000000000000000000000000815250565b600061093382610786565b61093d8185610885565b935061094d8185602086016107a2565b80840191505092915050565b7f6578706563746564200000000000000000000000000000000000000000000000815250565b600061098a826108df565b915061099582610902565b600b820191506109a58285610928565b91506109b082610959565b6009820191506109c08284610928565b91508190509392505050565b600060208201905081810360008301526109e681846107cc565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea26469706673582212203b80aa046928bf6b13cd29898611f9a4f048688dc21bfd44094fd59d8080e66064736f6c63430008180033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol b/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol index b51d0367e..984c00698 100644 --- a/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol +++ b/x/evm/embeds/contracts/TestERC20TransferThenPrecompileSend.sol @@ -25,15 +25,21 @@ contract TestERC20TransferThenPrecompileSend { "ERC-20 transfer failed" ); - (bool success, ) = FUNTOKEN_PRECOMPILE_ADDRESS.call( - abi.encodeWithSignature( - "bankSend(address,uint256,string)", - erc20, - uint256(precompileAmount), - precompileRecipient - ) + uint256 sentAmount = FUNTOKEN_PRECOMPILE.bankSend( + erc20, + precompileAmount, + precompileRecipient ); - require(success, string.concat("Failed to call bankSend")); + require( + sentAmount == precompileAmount, + string.concat( + "IFunToken.bankSend succeeded but transferred the wrong amount", + "sentAmount ", + Strings.toString(sentAmount), + "expected ", + Strings.toString(precompileAmount) + ) + ); } } diff --git a/x/evm/embeds/contracts/TestFunTokenPrecompileLocalGas.sol b/x/evm/embeds/contracts/TestFunTokenPrecompileLocalGas.sol new file mode 100644 index 000000000..abb239381 --- /dev/null +++ b/x/evm/embeds/contracts/TestFunTokenPrecompileLocalGas.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./IFunToken.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +contract TestFunTokenPrecompileLocalGas { + address erc20; + + constructor(address erc20_) { + erc20 = erc20_; + } + + // Calls bankSend of the FunToken Precompile with the default gas. + // Internal call could use all the gas for the parent call. + function callBankSend( + uint256 amount, + string memory bech32Recipient + ) public { + uint256 sentAmount = FUNTOKEN_PRECOMPILE.bankSend( + erc20, + amount, + bech32Recipient + ); + require( + sentAmount == amount, + string.concat( + "IFunToken.bankSend succeeded but transferred the wrong amount", + "sentAmount ", + Strings.toString(sentAmount), + "expected ", + Strings.toString(amount) + ) + ); + } + + // Calls bankSend of the FunToken Precompile with the gas amount set in parameter. + // Internal call should fail if the gas provided is insufficient. + function callBankSendLocalGas( + uint256 amount, + string memory bech32Recipient, + uint256 customGas + ) public { + uint256 sentAmount = FUNTOKEN_PRECOMPILE.bankSend{gas: customGas}( + erc20, + amount, + bech32Recipient + ); + require( + sentAmount == amount, + string.concat( + "IFunToken.bankSend succeeded but transferred the wrong amount", + "sentAmount ", + Strings.toString(sentAmount), + "expected ", + Strings.toString(amount) + ) + ); + } +} diff --git a/x/evm/embeds/embeds.go b/x/evm/embeds/embeds.go index 202b26525..b81a4b276 100644 --- a/x/evm/embeds/embeds.go +++ b/x/evm/embeds/embeds.go @@ -29,6 +29,8 @@ var ( testErc20MaliciousNameJson []byte //go:embed artifacts/contracts/TestERC20MaliciousTransfer.sol/TestERC20MaliciousTransfer.json testErc20MaliciousTransferJson []byte + //go:embed artifacts/contracts/TestFunTokenPrecompileLocalGas.sol/TestFunTokenPrecompileLocalGas.json + testFunTokenPrecompileLocalGasJson []byte //go:embed artifacts/contracts/TestERC20TransferThenPrecompileSend.sol/TestERC20TransferThenPrecompileSend.json testERC20TransferThenPrecompileSendJson []byte //go:embed artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json @@ -82,6 +84,12 @@ var ( Name: "TestERC20MaliciousTransfer.sol", EmbedJSON: testErc20MaliciousTransferJson, } + // SmartContract_TestFunTokenPrecompileLocalGas is a test contract + // which allows precompile execution with custom local gas set (calling precompile within contract) + SmartContract_TestFunTokenPrecompileLocalGas = CompiledEvmContract{ + Name: "TestFunTokenPrecompileLocalGas.sol", + EmbedJSON: testFunTokenPrecompileLocalGasJson, + } // SmartContract_TestNativeSendThenPrecompileSendJson is a test contract // that performs two sends in a single call: a native nibi send and a precompile bankSend. // It tests a race condition where the state DB commit @@ -118,6 +126,7 @@ func init() { SmartContract_TestERC20.MustLoad() SmartContract_TestERC20MaliciousName.MustLoad() SmartContract_TestERC20MaliciousTransfer.MustLoad() + SmartContract_TestFunTokenPrecompileLocalGas.MustLoad() SmartContract_TestNativeSendThenPrecompileSendJson.MustLoad() SmartContract_TestERC20TransferThenPrecompileSend.MustLoad() SmartContract_TestPrecompileSelfCallRevert.MustLoad() diff --git a/x/evm/embeds/embeds_test.go b/x/evm/embeds/embeds_test.go index 94f208dbb..91a5bf830 100644 --- a/x/evm/embeds/embeds_test.go +++ b/x/evm/embeds/embeds_test.go @@ -16,6 +16,7 @@ func TestLoadContracts(t *testing.T) { embeds.SmartContract_TestERC20.MustLoad() embeds.SmartContract_TestERC20MaliciousName.MustLoad() embeds.SmartContract_TestERC20MaliciousTransfer.MustLoad() + embeds.SmartContract_TestFunTokenPrecompileLocalGas.MustLoad() embeds.SmartContract_TestNativeSendThenPrecompileSendJson.MustLoad() embeds.SmartContract_TestERC20TransferThenPrecompileSend.MustLoad() }) diff --git a/x/evm/errors.go b/x/evm/errors.go index 87d5c747b..94ce6d3d8 100644 --- a/x/evm/errors.go +++ b/x/evm/errors.go @@ -2,19 +2,11 @@ package evm import ( - "errors" "fmt" errorsmod "cosmossdk.io/errors" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// Errors related to ERC20 calls and FunToken mappings. -const ( - ErrOwnable = "Ownable: caller is not the owner" ) const ( @@ -26,14 +18,10 @@ const ( codeErrInvalidRefund codeErrInvalidGasCap codeErrInvalidBaseFee - codeErrGasOverflow codeErrInvalidAccount - codeErrInvalidGasLimit codeErrInactivePrecompile ) -var ErrPostTxProcessing = errors.New("failed to execute post processing") - var ( // ErrInvalidState returns an error resulting from an invalid Storage State. ErrInvalidState = errorsmod.Register(ModuleName, codeErrInvalidState, "invalid storage state") @@ -59,53 +47,24 @@ var ( // ErrInvalidBaseFee returns an error if the base fee cap value is invalid ErrInvalidBaseFee = errorsmod.Register(ModuleName, codeErrInvalidBaseFee, "invalid base fee") - // ErrGasOverflow returns an error if gas computation overlow/underflow - ErrGasOverflow = errorsmod.Register(ModuleName, codeErrGasOverflow, "gas computation overflow/underflow") - // ErrInvalidAccount returns an error if the account is not an EVM compatible account ErrInvalidAccount = errorsmod.Register(ModuleName, codeErrInvalidAccount, "account type is not a valid ethereum account") - - // ErrInvalidGasLimit returns an error if gas limit value is invalid - ErrInvalidGasLimit = errorsmod.Register(ModuleName, codeErrInvalidGasLimit, "invalid gas limit") ) -// NewExecErrorWithReason unpacks the revert return bytes and returns a wrapped error +// NewRevertError unpacks the revert return bytes and returns a wrapped error // with the return reason. -func NewExecErrorWithReason(revertReason []byte) *RevertError { - result := common.CopyBytes(revertReason) - reason, errUnpack := abi.UnpackRevert(result) - - var err error - errPrefix := "execution reverted" - if errUnpack == nil { - reasonStr := reason - err = fmt.Errorf("%s with reason \"%v\"", errPrefix, reasonStr) - } else if string(result) != "" { - reasonStr := string(result) - err = fmt.Errorf("%s with reason \"%v\"", errPrefix, reasonStr) - } else { - err = errors.New(errPrefix) - } - return &RevertError{ - error: err, - reason: hexutil.Encode(result), +func NewRevertError(revertReason []byte) error { + reason, unpackingError := abi.UnpackRevert(revertReason) + + if unpackingError != nil { + return fmt.Errorf("execution reverted, but unable to parse reason \"%v\"", string(revertReason)) } + + return fmt.Errorf("execution reverted with reason \"%v\"", reason) } // RevertError is an API error that encompass an EVM revert with JSON error // code and a binary data blob. type RevertError struct { error - reason string // revert reason hex encoded -} - -// ErrorCode returns the JSON error code for a revert. -// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal -func (e *RevertError) ErrorCode() int { - return 3 -} - -// ErrorData returns the hex encoded revert reason. -func (e *RevertError) ErrorData() any { - return e.reason } diff --git a/x/evm/evmmodule/genesis_test.go b/x/evm/evmmodule/genesis_test.go index 72b884082..cc9d8c247 100644 --- a/x/evm/evmmodule/genesis_test.go +++ b/x/evm/evmmodule/genesis_test.go @@ -54,11 +54,11 @@ func (s *Suite) TestExportInitGenesis() { s.Require().NoError(err) // Transfer ERC-20 tokens to user A - _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserA, amountToSendA, deps.Ctx) + _, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserA, amountToSendA, deps.Ctx) s.Require().NoError(err) // Transfer ERC-20 tokens to user B - _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserB, amountToSendB, deps.Ctx) + _, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserB, amountToSendB, deps.Ctx) s.Require().NoError(err) // Create fungible token from bank coin diff --git a/x/evm/evmtest/test_deps.go b/x/evm/evmtest/test_deps.go index 6d2e830af..2d1948972 100644 --- a/x/evm/evmtest/test_deps.go +++ b/x/evm/evmtest/test_deps.go @@ -61,3 +61,8 @@ func (deps *TestDeps) GethSigner() gethcore.Signer { func (deps TestDeps) GoCtx() context.Context { return sdk.WrapSDKContext(deps.Ctx) } + +func (deps TestDeps) ResetGasMeter() { + deps.EvmKeeper.ResetTransientGasUsed(deps.Ctx) + deps.EvmKeeper.ResetGasMeterAndConsumeGas(deps.Ctx, 0) +} diff --git a/x/evm/keeper/call_contract.go b/x/evm/keeper/call_contract.go new file mode 100644 index 000000000..ad4ac90c7 --- /dev/null +++ b/x/evm/keeper/call_contract.go @@ -0,0 +1,150 @@ +package keeper + +import ( + "fmt" + "math/big" + "strings" + + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + gethabi "github.com/ethereum/go-ethereum/accounts/abi" + gethcommon "github.com/ethereum/go-ethereum/common" + gethcore "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + + "github.com/NibiruChain/nibiru/v2/x/evm" +) + +// CallContract invokes a smart contract on the method specified by [methodName] +// using the given [args]. +// +// Parameters: +// - ctx: The SDK context for the transaction. +// - abi: The ABI (Application Binary Interface) of the smart contract. +// - fromAcc: The Ethereum address of the account initiating the contract call. +// - contract: Pointer to the Ethereum address of the contract to be called. +// - commit: Boolean flag indicating whether to commit the transaction (true) or simulate it (false). +// - methodName: The name of the contract method to be called. +// - args: Variadic parameter for the arguments to be passed to the contract method. +// +// Note: This function handles both contract method calls and simulations, +// depending on the 'commit' parameter. +func (k Keeper) CallContract( + ctx sdk.Context, + abi *gethabi.ABI, + fromAcc gethcommon.Address, + contract *gethcommon.Address, + commit bool, + gasLimit uint64, + methodName string, + args ...any, +) (evmResp *evm.MsgEthereumTxResponse, err error) { + contractInput, err := abi.Pack(methodName, args...) + if err != nil { + return nil, fmt.Errorf("failed to pack ABI args: %w", err) + } + evmResp, _, err = k.CallContractWithInput(ctx, fromAcc, contract, commit, contractInput, gasLimit) + return evmResp, err +} + +// CallContractWithInput invokes a smart contract with the given [contractInput] +// or deploys a new contract. +// +// Parameters: +// - ctx: The SDK context for the transaction. +// - fromAcc: The Ethereum address of the account initiating the contract call. +// - contract: Pointer to the Ethereum address of the contract. Nil if new +// contract is deployed. +// - commit: Boolean flag indicating whether to commit the transaction (true) +// or simulate it (false). +// - contractInput: Hexadecimal-encoded bytes use as input data to the call. +// +// Note: This function handles both contract method calls and simulations, +// depending on the 'commit' parameter. It uses a default gas limit. +func (k Keeper) CallContractWithInput( + ctx sdk.Context, + fromAcc gethcommon.Address, + contract *gethcommon.Address, + commit bool, + contractInput []byte, + gasLimit uint64, +) (evmResp *evm.MsgEthereumTxResponse, evmObj *vm.EVM, err error) { + // This is a `defer` pattern to add behavior that runs in the case that the + // error is non-nil, creating a concise way to add extra information. + defer HandleOutOfGasPanic(&err, "CallContractError") + nonce := k.GetAccNonce(ctx, fromAcc) + + unusedBigInt := big.NewInt(0) + evmMsg := gethcore.NewMessage( + fromAcc, + contract, + nonce, + unusedBigInt, // amount + gasLimit, + unusedBigInt, // gasFeeCap + unusedBigInt, // gasTipCap + unusedBigInt, // gasPrice + contractInput, + gethcore.AccessList{}, + !commit, // isFake + ) + + // Apply EVM message + evmCfg, err := k.GetEVMConfig( + ctx, + sdk.ConsAddress(ctx.BlockHeader().ProposerAddress), + k.EthChainID(ctx), + ) + if err != nil { + err = errors.Wrapf(err, "failed to load EVM config") + return + } + + // Generating TxConfig with an empty tx hash as there is no actual eth tx + // sent by a user + txConfig := k.TxConfig(ctx, gethcommon.BigToHash(big.NewInt(0))) + + evmResp, evmObj, err = k.ApplyEvmMsg( + ctx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, true, + ) + if err != nil { + // We don't know the actual gas used, so consuming the gas limit + k.ResetGasMeterAndConsumeGas(ctx, gasLimit) + err = errors.Wrap(err, "failed to apply ethereum core message") + return + } + + if evmResp.Failed() { + k.ResetGasMeterAndConsumeGas(ctx, evmResp.GasUsed) + if strings.Contains(evmResp.VmError, vm.ErrOutOfGas.Error()) { + err = fmt.Errorf("gas required exceeds allowance (%d)", gasLimit) + return + } + if evmResp.VmError == vm.ErrExecutionReverted.Error() { + err = fmt.Errorf("VMError: %w", evm.NewRevertError(evmResp.Ret)) + return + } + err = fmt.Errorf("VMError: %s", evmResp.VmError) + return + } + + // Success, update block gas used and bloom filter + if commit { + blockGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) + if err != nil { + k.ResetGasMeterAndConsumeGas(ctx, ctx.GasMeter().Limit()) + return nil, nil, errors.Wrap(err, "error adding transient gas used to block") + } + k.ResetGasMeterAndConsumeGas(ctx, blockGasUsed) + k.updateBlockBloom(ctx, evmResp, uint64(txConfig.LogIndex)) + // TODO: remove after migrating logs + //err = k.EmitLogEvents(ctx, evmResp) + //if err != nil { + // return nil, nil, errors.Wrap(err, "error emitting tx logs") + //} + + // blockTxIdx := uint64(txConfig.TxIndex) + 1 + // k.EvmState.BlockTxIndex.Set(ctx, blockTxIdx) + } + return evmResp, evmObj, nil +} diff --git a/x/evm/keeper/erc20.go b/x/evm/keeper/erc20.go index 79c189f1e..ed32a5788 100644 --- a/x/evm/keeper/erc20.go +++ b/x/evm/keeper/erc20.go @@ -9,15 +9,23 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" gethabi "github.com/ethereum/go-ethereum/accounts/abi" gethcommon "github.com/ethereum/go-ethereum/common" - gethcore "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - - serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" "github.com/NibiruChain/nibiru/v2/x/evm" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" ) +const ( + // Erc20GasLimitDeploy only used internally when deploying ERC20Minter. + // Deployment requires ~1_600_000 gas + Erc20GasLimitDeploy uint64 = 2_000_000 + // Erc20GasLimitQuery used only for querying name, symbol and decimals + // Cannot be heavy. Only if the contract is malicious. + Erc20GasLimitQuery uint64 = 100_000 + // Erc20GasLimitExecute used for transfer, mint and burn. + // All must not exceed 200_000 + Erc20GasLimitExecute uint64 = 200_000 +) + // ERC20 returns a mutable reference to the keeper with an ERC20 contract ABI and // Go functions corresponding to contract calls in the ERC20 standard like "mint" // and "transfer" in the ERC20 standard. @@ -52,12 +60,7 @@ func (e erc20Calls) Mint( contract, from, to gethcommon.Address, amount *big.Int, ctx sdk.Context, ) (evmResp *evm.MsgEthereumTxResponse, err error) { - input, err := e.ABI.Pack("mint", to, amount) - if err != nil { - return nil, fmt.Errorf("failed to pack ABI args: %w", err) - } - evmResp, _, err = e.CallContractWithInput(ctx, from, &contract, true, input) - return evmResp, err + return e.CallContract(ctx, e.ABI, from, &contract, true, Erc20GasLimitExecute, "mint", to, amount) } /* @@ -73,37 +76,32 @@ Transfer implements "ERC20.transfer" func (e erc20Calls) Transfer( contract, from, to gethcommon.Address, amount *big.Int, ctx sdk.Context, -) (balanceIncrease *big.Int, err error) { +) (balanceIncrease *big.Int, resp *evm.MsgEthereumTxResponse, err error) { recipientBalanceBefore, err := e.BalanceOf(contract, to, ctx) if err != nil { - return balanceIncrease, errors.Wrap(err, "failed to retrieve recipient balance") + return balanceIncrease, nil, errors.Wrap(err, "failed to retrieve recipient balance") } - input, err := e.ABI.Pack("transfer", to, amount) + resp, err = e.CallContract(ctx, e.ABI, from, &contract, true, Erc20GasLimitExecute, "transfer", to, amount) if err != nil { - return balanceIncrease, fmt.Errorf("failed to pack ABI args: %w", err) - } - - resp, _, err := e.CallContractWithInput(ctx, from, &contract, true, input) - if err != nil { - return balanceIncrease, err + return balanceIncrease, nil, err } var erc20Bool ERC20Bool err = e.ABI.UnpackIntoInterface(&erc20Bool, "transfer", resp.Ret) if err != nil { - return balanceIncrease, err + return balanceIncrease, nil, err } // Handle the case of success=false: https://github.com/NibiruChain/nibiru/issues/2080 success := erc20Bool.Value if !success { - return balanceIncrease, fmt.Errorf("transfer executed but returned success=false") + return balanceIncrease, nil, fmt.Errorf("transfer executed but returned success=false") } recipientBalanceAfter, err := e.BalanceOf(contract, to, ctx) if err != nil { - return balanceIncrease, errors.Wrap(err, "failed to retrieve recipient balance") + return balanceIncrease, nil, errors.Wrap(err, "failed to retrieve recipient balance") } balanceIncrease = new(big.Int).Sub(recipientBalanceAfter, recipientBalanceBefore) @@ -113,13 +111,13 @@ func (e erc20Calls) Transfer( // the call "amount". Instead, verify that the recipient got tokens and // return the amount. if balanceIncrease.Sign() <= 0 { - return balanceIncrease, fmt.Errorf( + return balanceIncrease, nil, fmt.Errorf( "amount of ERC20 tokens received MUST be positive: the balance of recipient %s would've changed by %v for token %s", to.Hex(), balanceIncrease.String(), contract.Hex(), ) } - return balanceIncrease, err + return balanceIncrease, resp, err } // BalanceOf retrieves the balance of an ERC20 token for a specific account. @@ -143,153 +141,7 @@ func (e erc20Calls) Burn( contract, from gethcommon.Address, amount *big.Int, ctx sdk.Context, ) (evmResp *evm.MsgEthereumTxResponse, err error) { - input, err := e.ABI.Pack("burn", amount) - if err != nil { - return - } - commit := true - evmResp, _, err = e.CallContractWithInput(ctx, from, &contract, commit, input) - return -} - -// CallContract invokes a smart contract on the method specified by [methodName] -// using the given [args]. -// -// Parameters: -// - ctx: The SDK context for the transaction. -// - abi: The ABI (Application Binary Interface) of the smart contract. -// - fromAcc: The Ethereum address of the account initiating the contract call. -// - contract: Pointer to the Ethereum address of the contract to be called. -// - commit: Boolean flag indicating whether to commit the transaction (true) or simulate it (false). -// - methodName: The name of the contract method to be called. -// - args: Variadic parameter for the arguments to be passed to the contract method. -// -// Note: This function handles both contract method calls and simulations, -// depending on the 'commit' parameter. It uses a default gas limit for -// simulations and estimates gas for actual transactions. -func (k Keeper) CallContract( - ctx sdk.Context, - abi *gethabi.ABI, - fromAcc gethcommon.Address, - contract *gethcommon.Address, - commit bool, - methodName string, - args ...any, -) (evmResp *evm.MsgEthereumTxResponse, err error) { - contractInput, err := abi.Pack(methodName, args...) - if err != nil { - return nil, fmt.Errorf("failed to pack ABI args: %w", err) - } - evmResp, _, err = k.CallContractWithInput( - ctx, fromAcc, contract, commit, contractInput, - ) - return evmResp, err -} - -// CallContractWithInput invokes a smart contract with the given [contractInput] -// or deploys a new contract. -// -// Parameters: -// - ctx: The SDK context for the transaction. -// - fromAcc: The Ethereum address of the account initiating the contract call. -// - contract: Pointer to the Ethereum address of the contract. Nil if new -// contract is deployed. -// - commit: Boolean flag indicating whether to commit the transaction (true) -// or simulate it (false). -// - contractInput: Hexadecimal-encoded bytes use as input data to the call. -// -// Note: This function handles both contract method calls and simulations, -// depending on the 'commit' parameter. It uses a default gas limit. -func (k Keeper) CallContractWithInput( - ctx sdk.Context, - fromAcc gethcommon.Address, - contract *gethcommon.Address, - commit bool, - contractInput []byte, -) (evmResp *evm.MsgEthereumTxResponse, evmObj *vm.EVM, err error) { - // This is a `defer` pattern to add behavior that runs in the case that the - // error is non-nil, creating a concise way to add extra information. - defer func() { - if err != nil { - err = fmt.Errorf("CallContractError: %w", err) - } - }() - nonce := k.GetAccNonce(ctx, fromAcc) - - // Gas cap sufficient for all "honest" ERC20 calls without malicious (gas - // intensive) code in contracts - gasLimit := serverconfig.DefaultEthCallGasLimit - - unusedBigInt := big.NewInt(0) - evmMsg := gethcore.NewMessage( - fromAcc, - contract, - nonce, - unusedBigInt, // amount - gasLimit, - unusedBigInt, // gasFeeCap - unusedBigInt, // gasTipCap - unusedBigInt, // gasPrice - contractInput, - gethcore.AccessList{}, - !commit, // isFake - ) - - // Apply EVM message - evmCfg, err := k.GetEVMConfig( - ctx, - sdk.ConsAddress(ctx.BlockHeader().ProposerAddress), - k.EthChainID(ctx), - ) - if err != nil { - err = errors.Wrapf(err, "failed to load EVM config") - return - } - - // Generating TxConfig with an empty tx hash as there is no actual eth tx - // sent by a user - txConfig := k.TxConfig(ctx, gethcommon.BigToHash(big.NewInt(0))) - - evmResp, evmObj, err = k.ApplyEvmMsg( - ctx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, - ) - if err != nil { - // We don't know the actual gas used, so consuming the gas limit - k.ResetGasMeterAndConsumeGas(ctx, gasLimit) - err = errors.Wrap(err, "failed to apply ethereum core message") - return - } - if evmResp.Failed() { - k.ResetGasMeterAndConsumeGas(ctx, evmResp.GasUsed) - if evmResp.VmError != vm.ErrOutOfGas.Error() { - if evmResp.VmError == vm.ErrExecutionReverted.Error() { - err = fmt.Errorf("VMError: %w", evm.NewExecErrorWithReason(evmResp.Ret)) - return - } - err = fmt.Errorf("VMError: %s", evmResp.VmError) - return - } - err = fmt.Errorf("gas required exceeds allowance (%d)", gasLimit) - return - } else { - // Success, committing the state to ctx - if commit { - totalGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) - if err != nil { - k.ResetGasMeterAndConsumeGas(ctx, ctx.GasMeter().Limit()) - return nil, nil, errors.Wrap(err, "error adding transient gas used to block") - } - k.ResetGasMeterAndConsumeGas(ctx, totalGasUsed) - k.updateBlockBloom(ctx, evmResp, uint64(txConfig.LogIndex)) - err = k.EmitEthereumTxEvents(ctx, contract, gethcore.LegacyTxType, evmMsg, evmResp) - if err != nil { - return nil, nil, errors.Wrap(err, "error emitting ethereum tx events") - } - blockTxIdx := uint64(txConfig.TxIndex) + 1 - k.EvmState.BlockTxIndex.Set(ctx, blockTxIdx) - } - return evmResp, evmObj, nil - } + return e.CallContract(ctx, e.ABI, from, &contract, true, Erc20GasLimitExecute, "burn", amount) } func (k Keeper) LoadERC20Name( @@ -317,10 +169,13 @@ func (k Keeper) LoadERC20String( methodName string, ) (out string, err error) { res, err := k.CallContract( - ctx, erc20Abi, + ctx, + erc20Abi, evm.EVM_MODULE_ADDRESS, &erc20Contract, - false, methodName, + false, + Erc20GasLimitQuery, + methodName, ) if err != nil { return out, err @@ -346,7 +201,9 @@ func (k Keeper) loadERC20Uint8( ctx, erc20Abi, evm.EVM_MODULE_ADDRESS, &erc20Contract, - false, methodName, + false, + Erc20GasLimitQuery, + methodName, ) if err != nil { return out, err @@ -375,6 +232,7 @@ func (k Keeper) LoadERC20BigInt( evm.EVM_MODULE_ADDRESS, &contract, false, + Erc20GasLimitQuery, methodName, args..., ) diff --git a/x/evm/keeper/erc20_test.go b/x/evm/keeper/erc20_test.go index c45ed10a1..9b9ef9715 100644 --- a/x/evm/keeper/erc20_test.go +++ b/x/evm/keeper/erc20_test.go @@ -20,7 +20,7 @@ func (s *Suite) TestERC20Calls() { contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, big.NewInt(69_420), deps.Ctx, ) - s.ErrorContains(err, evm.ErrOwnable) + s.ErrorContains(err, "Ownable: caller is not the owner") } s.T().Log("Mint tokens - Success") @@ -35,7 +35,7 @@ func (s *Suite) TestERC20Calls() { s.T().Log("Transfer - Not enough funds") { amt := big.NewInt(9_420) - _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx) + _, _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, amt, deps.Ctx) s.ErrorContains(err, "ERC20: transfer amount exceeds balance") // balances unchanged evmtest.AssertERC20BalanceEqual(s.T(), deps, contract, deps.Sender.EthAddr, big.NewInt(0)) @@ -45,7 +45,7 @@ func (s *Suite) TestERC20Calls() { s.T().Log("Transfer - Success (sanity check)") { amt := big.NewInt(9_420) - sentAmt, err := deps.EvmKeeper.ERC20().Transfer( + sentAmt, _, err := deps.EvmKeeper.ERC20().Transfer( contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, amt, deps.Ctx, ) s.Require().NoError(err) diff --git a/x/evm/keeper/funtoken_from_coin.go b/x/evm/keeper/funtoken_from_coin.go index 8075107c6..4dfaa5c92 100644 --- a/x/evm/keeper/funtoken_from_coin.go +++ b/x/evm/keeper/funtoken_from_coin.go @@ -79,7 +79,7 @@ func (k *Keeper) deployERC20ForBankCoin( // nil address for contract creation _, _, err = k.CallContractWithInput( - ctx, evm.EVM_MODULE_ADDRESS, nil, true, bytecodeForCall, + ctx, evm.EVM_MODULE_ADDRESS, nil, true, bytecodeForCall, Erc20GasLimitDeploy, ) if err != nil { return gethcommon.Address{}, errors.Wrap(err, "failed to deploy ERC20 contract") diff --git a/x/evm/keeper/funtoken_from_coin_test.go b/x/evm/keeper/funtoken_from_coin_test.go index 646391eea..29c3f2daa 100644 --- a/x/evm/keeper/funtoken_from_coin_test.go +++ b/x/evm/keeper/funtoken_from_coin_test.go @@ -225,6 +225,8 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { ) s.Require().ErrorContains(err, "insufficient funds") + deps.ResetGasMeter() + s.T().Log("Convert erc-20 to back to bank coin") _, err = deps.EvmKeeper.CallContract( deps.Ctx, @@ -232,6 +234,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { alice.EthAddr, &precompile.PrecompileAddr_FunToken, true, + precompile.FunTokenGasLimitBankSend, "bankSend", funToken.Erc20Addr.Address, big.NewInt(10), @@ -259,6 +262,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() { alice.EthAddr, &precompile.PrecompileAddr_FunToken, true, + precompile.FunTokenGasLimitBankSend, "bankSend", funToken.Erc20Addr.Address, big.NewInt(10), @@ -354,6 +358,7 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() { deps.Sender.EthAddr, &testContractAddr, true, + 10_000_000, // 100% sufficient gas "nativeSendThenPrecompileSend", []any{ alice.EthAddr, @@ -439,6 +444,7 @@ func (s *FunTokenFromCoinSuite) TestERC20TransferThenPrecompileSend() { deps.Sender.EthAddr, &testContractAddr, true, + 10_000_000, // 100% sufficient gas "erc20TransferThenPrecompileSend", alice.EthAddr, big.NewInt(1e6), // erc20 created with 6 decimals @@ -544,6 +550,7 @@ func (s *FunTokenFromCoinSuite) TestPrecompileSelfCallRevert() { deps.Sender.EthAddr, &testContractAddr, true, + precompile.FunTokenGasLimitBankSend, "selfCallTransferFunds", alice.EthAddr, evm.NativeToWei(big.NewInt(1e6)), // native send uses wei units, diff --git a/x/evm/keeper/funtoken_from_erc20_test.go b/x/evm/keeper/funtoken_from_erc20_test.go index 53db98b31..538d041d1 100644 --- a/x/evm/keeper/funtoken_from_erc20_test.go +++ b/x/evm/keeper/funtoken_from_erc20_test.go @@ -202,6 +202,7 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() { deps.Sender.EthAddr, &deployResp.ContractAddr, true, + keeper.Erc20GasLimitExecute, "mint", deps.Sender.EthAddr, big.NewInt(69_420), @@ -210,6 +211,8 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() { randomAcc := testutil.AccAddress() + deps.ResetGasMeter() + s.T().Log("send erc20 tokens to Bank") _, err = deps.EvmKeeper.CallContract( deps.Ctx, @@ -217,6 +220,7 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() { deps.Sender.EthAddr, &precompile.PrecompileAddr_FunToken, true, + precompile.FunTokenGasLimitBankSend, "bankSend", deployResp.ContractAddr, big.NewInt(1), @@ -231,6 +235,8 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() { deps.App.BankKeeper.GetBalance(deps.Ctx, randomAcc, bankDemon).Amount, ) + deps.ResetGasMeter() + s.T().Log("sad: send too many erc20 tokens to Bank") evmResp, err := deps.EvmKeeper.CallContract( deps.Ctx, @@ -238,6 +244,7 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() { deps.Sender.EthAddr, &precompile.PrecompileAddr_FunToken, true, + precompile.FunTokenGasLimitBankSend, "bankSend", deployResp.ContractAddr, big.NewInt(70_000), @@ -246,6 +253,8 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() { s.T().Log("check balances") s.Require().Error(err, evmResp.String()) + deps.ResetGasMeter() + s.T().Log("send Bank tokens back to erc20") _, err = deps.EvmKeeper.ConvertCoinToEvm(sdk.WrapSDKContext(deps.Ctx), &evm.MsgConvertCoinToEvm{ @@ -358,6 +367,8 @@ func (s *FunTokenFromErc20Suite) TestFunTokenFromERC20MaliciousTransfer() { s.Require().NoError(err) randomAcc := testutil.AccAddress() + deps.ResetGasMeter() + s.T().Log("send erc20 tokens to cosmos") _, err = deps.EvmKeeper.CallContract( deps.Ctx, @@ -365,6 +376,7 @@ func (s *FunTokenFromErc20Suite) TestFunTokenFromERC20MaliciousTransfer() { deps.Sender.EthAddr, &precompile.PrecompileAddr_FunToken, true, + precompile.FunTokenGasLimitBankSend, "bankSend", deployResp.ContractAddr, big.NewInt(1), diff --git a/x/evm/keeper/gas_fees.go b/x/evm/keeper/gas_fees.go index c373b06ac..4d17de0bd 100644 --- a/x/evm/keeper/gas_fees.go +++ b/x/evm/keeper/gas_fees.go @@ -4,21 +4,18 @@ package keeper import ( "math/big" - gethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - gethcore "github.com/ethereum/go-ethereum/core/types" - "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" - + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + gethcore "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/NibiruChain/nibiru/v2/x/evm" - - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // GetEthIntrinsicGas returns the intrinsic gas cost for the transaction diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 4e13254a9..4e423e881 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -284,7 +284,7 @@ func (k *Keeper) EthCall( txConfig := statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash())) // pass false to not commit StateDB - res, _, err := k.ApplyEvmMsg(ctx, msg, nil, false, cfg, txConfig) + res, _, err := k.ApplyEvmMsg(ctx, msg, nil, false, cfg, txConfig, false) if err != nil { return nil, grpcstatus.Error(grpccodes.Internal, err.Error()) } @@ -323,17 +323,25 @@ func (k Keeper) EstimateGasForEvmCallType( ctx := sdk.UnwrapSDKContext(goCtx) chainID := k.EthChainID(ctx) + cfg, err := k.GetEVMConfig(ctx, ParseProposerAddr(ctx, req.ProposerAddress), chainID) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, "failed to load evm config") + } if req.GasCap < gethparams.TxGas { return nil, grpcstatus.Errorf(grpccodes.InvalidArgument, "gas cap cannot be lower than %d", gethparams.TxGas) } var args evm.JsonTxArgs - err := json.Unmarshal(req.Args, &args) + err = json.Unmarshal(req.Args, &args) if err != nil { return nil, grpcstatus.Error(grpccodes.InvalidArgument, err.Error()) } + // ApplyMessageWithConfig expect correct nonce set in msg + nonce := k.GetAccNonce(ctx, args.GetFrom()) + args.Nonce = (*hexutil.Uint64)(&nonce) + // Binary search the gas requirement, as it may be higher than the amount used var ( lo = gethparams.TxGas - 1 @@ -361,16 +369,6 @@ func (k Keeper) EstimateGasForEvmCallType( } gasCap = hi - cfg, err := k.GetEVMConfig(ctx, ParseProposerAddr(ctx, req.ProposerAddress), chainID) - if err != nil { - return nil, grpcstatus.Error(grpccodes.Internal, "failed to load evm config") - } - - // ApplyMessageWithConfig expect correct nonce set in msg - nonce := k.GetAccNonce(ctx, args.GetFrom()) - args.Nonce = (*hexutil.Uint64)(&nonce) - - txConfig := statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash().Bytes())) // convert the tx args to an ethereum message msg, err := args.ToMessage(req.GasCap, cfg.BaseFeeWei) @@ -422,7 +420,8 @@ func (k Keeper) EstimateGasForEvmCallType( WithTransientKVGasConfig(storetypes.GasConfig{}) } // pass false to not commit StateDB - rsp, _, err = k.ApplyEvmMsg(tmpCtx, msg, nil, false, cfg, txConfig) + txConfig := statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash().Bytes())) + rsp, _, err = k.ApplyEvmMsg(tmpCtx, msg, nil, false, cfg, txConfig, false) if err != nil { if errors.Is(err, core.ErrIntrinsicGas) { return true, nil, nil // Special case, raise gas limit @@ -438,6 +437,7 @@ func (k Keeper) EstimateGasForEvmCallType( return nil, err } + // The gas limit is now the highest gas limit that results in an executable transaction // Reject the transaction as invalid if it still fails at the highest allowance if hi == gasCap { failed, result, err := executable(hi) @@ -445,17 +445,19 @@ func (k Keeper) EstimateGasForEvmCallType( return nil, fmt.Errorf("eth call exec error: %w", err) } - if failed { - if result != nil && result.VmError != vm.ErrOutOfGas.Error() { - if result.VmError == vm.ErrExecutionReverted.Error() { - return nil, fmt.Errorf("VMError: %w", evm.NewExecErrorWithReason(result.Ret)) - } - return nil, fmt.Errorf("VMError: %s", result.VmError) + if failed && result != nil { + if result.VmError == vm.ErrExecutionReverted.Error() { + return nil, fmt.Errorf("Estimate gas VMError: %w", evm.NewRevertError(result.Ret)) + } + + if result.VmError == vm.ErrOutOfGas.Error() { + return nil, fmt.Errorf("gas required exceeds allowance (%d)", gasCap) } - // Otherwise, the specified gas cap is too low - return nil, fmt.Errorf("gas required exceeds allowance (%d)", gasCap) + + return nil, fmt.Errorf("Estimgate gas VMError: %s", result.VmError) } } + return &evm.EstimateGasResponse{Gas: hi}, nil } @@ -518,7 +520,7 @@ func (k Keeper) TraceTx( ctx = ctx.WithGasMeter(eth.NewInfiniteGasMeterWithLimit(msg.Gas())). WithKVGasConfig(storetypes.GasConfig{}). WithTransientKVGasConfig(storetypes.GasConfig{}) - rsp, _, err := k.ApplyEvmMsg(ctx, msg, evm.NewNoOpTracer(), true, cfg, txConfig) + rsp, _, err := k.ApplyEvmMsg(ctx, msg, evm.NewNoOpTracer(), true, cfg, txConfig, false) if err != nil { continue } @@ -800,7 +802,7 @@ func (k *Keeper) TraceEthTxMsg( ctx = ctx.WithGasMeter(eth.NewInfiniteGasMeterWithLimit(msg.Gas())). WithKVGasConfig(storetypes.GasConfig{}). WithTransientKVGasConfig(storetypes.GasConfig{}) - res, _, err := k.ApplyEvmMsg(ctx, msg, tracer, commitMessage, cfg, txConfig) + res, _, err := k.ApplyEvmMsg(ctx, msg, tracer, commitMessage, cfg, txConfig, false) if err != nil { return nil, 0, grpcstatus.Error(grpccodes.Internal, err.Error()) } diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index dd757ced9..6d413e687 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -2,14 +2,15 @@ package keeper import ( + "fmt" "math/big" + "cosmossdk.io/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/vm" gethparams "github.com/ethereum/go-ethereum/params" - sdkerrors "cosmossdk.io/errors" - "cosmossdk.io/math" + "cosmossdk.io/errors" "github.com/cometbft/cometbft/libs/log" "github.com/cosmos/cosmos-sdk/codec" @@ -101,17 +102,25 @@ func (k Keeper) EthChainID(ctx sdk.Context) *big.Int { // block tx. func (k *Keeper) AddToBlockGasUsed( ctx sdk.Context, gasUsed uint64, -) (uint64, error) { - result := k.EvmState.BlockGasUsed.GetOr(ctx, 0) + gasUsed - if result < gasUsed { - return 0, sdkerrors.Wrap(evm.ErrGasOverflow, "transient gas used") +) (blockGasUsed uint64, err error) { + // Either k.EvmState.BlockGasUsed.GetOr() or k.EvmState.BlockGasUsed.Set() + // also consume gas and could panic. + defer HandleOutOfGasPanic(&err, "") + + blockGasUsed = k.EvmState.BlockGasUsed.GetOr(ctx, 0) + gasUsed + if blockGasUsed < gasUsed { + return 0, errors.Wrap(core.ErrGasUintOverflow, "transient gas used") } - k.EvmState.BlockGasUsed.Set(ctx, result) - return result, nil + k.EvmState.BlockGasUsed.Set(ctx, blockGasUsed) + + return blockGasUsed, nil } -// GetMinGasMultiplier returns minimum gas multiplier. -func (k Keeper) GetMinGasMultiplier(ctx sdk.Context) math.LegacyDec { +// GetMinGasUsedMultiplier - value from 0 to 1 +// When executing evm msg, user specifies gasLimit. +// If the gasLimit is X times higher than the actual gasUsed then +// we update gasUsed = max(gasUsed, gasLimit * minGasUsedPct) +func (k Keeper) GetMinGasUsedMultiplier(ctx sdk.Context) math.LegacyDec { return math.LegacyNewDecWithPrec(50, 2) // 50% } @@ -140,3 +149,20 @@ func (k Keeper) Tracer( ) vm.EVMLogger { return evm.NewTracer(k.tracer, msg, ethCfg, ctx.BlockHeight()) } + +// HandleOutOfGasPanic gracefully captures "out of gas" panic and just sets the value to err +func HandleOutOfGasPanic(err *error, format string) func() { + return func() { + if r := recover(); r != nil { + switch r.(type) { + case sdk.ErrorOutOfGas: + *err = vm.ErrOutOfGas + default: + panic(r) + } + } + if err != nil && format != "" { + *err = fmt.Errorf("%s: %w", format, *err) + } + } +} diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index dbc1e8f74..e7002d528 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -62,42 +62,45 @@ func (k *Keeper) EthereumTx( tmpCtx, commitCtx := ctx.CacheContext() // pass true to commit the StateDB - evmResp, _, err = k.ApplyEvmMsg(tmpCtx, evmMsg, nil, true, evmConfig, txConfig) + evmResp, _, err = k.ApplyEvmMsg(tmpCtx, evmMsg, nil, true, evmConfig, txConfig, false) if err != nil { // when a transaction contains multiple msg, as long as one of the msg fails // all gas will be deducted. so is not msg.Gas() k.ResetGasMeterAndConsumeGas(ctx, ctx.GasMeter().Limit()) - return nil, errors.Wrap(err, "failed to apply ethereum core message") + return nil, errors.Wrap(err, "EthereumTx: failed to apply ethereum core message") } if !evmResp.Failed() { commitCtx() } + k.updateBlockBloom(ctx, evmResp, uint64(txConfig.LogIndex)) + + blockGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) + if err != nil { + return nil, errors.Wrap(err, "EthereumTx: error adding transient gas used to block") + } // refund gas in order to match the Ethereum gas consumption instead of the // default SDK one. refundGas := uint64(0) - if evmMsg.Gas() > evmResp.GasUsed { - refundGas = evmMsg.Gas() - evmResp.GasUsed + if evmMsg.Gas() > blockGasUsed { + refundGas = evmMsg.Gas() - blockGasUsed } weiPerGas := txMsg.EffectiveGasPriceWeiPerGas(evmConfig.BaseFeeWei) if err = k.RefundGas(ctx, evmMsg.From(), refundGas, weiPerGas); err != nil { - return nil, errors.Wrapf(err, "error refunding leftover gas to sender %s", evmMsg.From()) - } - - k.updateBlockBloom(ctx, evmResp, uint64(txConfig.LogIndex)) - - totalGasUsed, err := k.AddToBlockGasUsed(ctx, evmResp.GasUsed) - if err != nil { - return nil, errors.Wrap(err, "error adding transient gas used to block") + return nil, errors.Wrapf(err, "EthereumTx: error refunding leftover gas to sender %s", evmMsg.From()) } // reset the gas meter for current TxMsg (EthereumTx) - k.ResetGasMeterAndConsumeGas(ctx, totalGasUsed) + k.ResetGasMeterAndConsumeGas(ctx, blockGasUsed) err = k.EmitEthereumTxEvents(ctx, tx.To(), tx.Type(), evmMsg, evmResp) if err != nil { - return nil, errors.Wrap(err, "error emitting ethereum tx events") + return nil, errors.Wrap(err, "EthereumTx: error emitting ethereum tx events") + } + err = k.EmitLogEvents(ctx, evmResp) + if err != nil { + return nil, errors.Wrap(err, "EthereumTx: error emitting tx logs") } blockTxIdx := uint64(txConfig.TxIndex) + 1 @@ -235,18 +238,21 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { // 1. set up the initial access list // // # Tracer parameter -// // It should be a `vm.Tracer` object or nil, if pass `nil`, it'll create a default one based on keeper options. // // # Commit parameter -// // If commit is true, the `StateDB` will be committed, otherwise discarded. +// +// # fullRefundLeftoverGas parameter +// For internal calls like funtokens, user does not specify gas limit explicitly. +// In this case we don't apply any caps for refund and refund 100% func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool, evmConfig *statedb.EVMConfig, txConfig statedb.TxConfig, + fullRefundLeftoverGas bool, ) (resp *evm.MsgEthereumTxResponse, evmObj *vm.EVM, err error) { var ( ret []byte // return bytes from evm execution @@ -270,10 +276,13 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, sender := vm.AccountRef(msg.From()) contractCreation := msg.To() == nil - intrinsicGas, err := k.GetEthIntrinsicGas(ctx, msg, evmConfig.ChainConfig, contractCreation) + intrinsicGas, err := core.IntrinsicGas( + msg.Data(), msg.AccessList(), + contractCreation, true, true, + ) if err != nil { // should have already been checked on Ante Handler - return nil, evmObj, errors.Wrap(err, "intrinsic gas failed") + return nil, evmObj, errors.Wrap(err, "ApplyEvmMsg: intrinsic gas overflowed") } // Check if the provided gas in the message is enough to cover the intrinsic @@ -286,7 +295,7 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, // eth_estimateGas will check for this exact error return nil, evmObj, errors.Wrapf( core.ErrIntrinsicGas, - "apply message msg.Gas = %d, intrinsic gas = %d.", + "ApplyEvmMsg: provided msg.Gas (%d) is less than intrinsic gas cost (%d)", leftoverGas, intrinsicGas, ) } @@ -304,7 +313,7 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, msgWei, err := ParseWeiAsMultipleOfMicronibi(msg.Value()) if err != nil { - return nil, evmObj, err + return nil, evmObj, errors.Wrapf(err, "ApplyEvmMsg: invalid wei amount %s", msg.Value()) } if contractCreation { @@ -329,21 +338,6 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, ) } - // After EIP-3529: refunds are capped to gasUsed / 5 - refundQuotient := params.RefundQuotientEIP3529 - - // calculate gas refund - if msg.Gas() < leftoverGas { - return nil, evmObj, errors.Wrap(evm.ErrGasOverflow, "apply message") - } - // refund gas - temporaryGasUsed := msg.Gas() - leftoverGas - refund := GasToRefund(stateDB.GetRefund(), temporaryGasUsed, refundQuotient) - - // update leftoverGas and temporaryGasUsed with refund amount - leftoverGas += refund - temporaryGasUsed -= refund - // EVM execution error needs to be available for the JSON-RPC client var vmError string if vmErr != nil { @@ -353,22 +347,38 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context, // The dirty states in `StateDB` is either committed or discarded after return if commit { if err := stateDB.Commit(); err != nil { - return nil, evmObj, fmt.Errorf("failed to commit stateDB: %w", err) + return nil, evmObj, errors.Wrap(err, "ApplyEvmMsg: failed to commit stateDB") } } + // Rare case of uint64 gas overflow + if msg.Gas() < leftoverGas { + return nil, evmObj, errors.Wrapf(core.ErrGasUintOverflow, "ApplyEvmMsg: message gas limit (%d) < leftover gas (%d)", msg.Gas(), leftoverGas) + } - gasLimit := math.LegacyNewDec(int64(msg.Gas())) - minGasMultiplier := k.GetMinGasMultiplier(ctx) - minimumGasUsed := gasLimit.Mul(minGasMultiplier) + // GAS REFUND + // If msg.Gas() > gasUsed, we need to refund extra gas. + // leftoverGas = amount of extra (not used) gas. + // If the msg comes from user, we apply refundQuotient capping the refund to 20% of used gas + // If msg is internal (funtoken), we refund 100% - if !minimumGasUsed.TruncateInt().IsUint64() { - return nil, evmObj, errors.Wrapf(evm.ErrGasOverflow, "minimumGasUsed(%s) is not a uint64", minimumGasUsed.TruncateInt().String()) + refundQuotient := params.RefundQuotientEIP3529 // EIP-3529: refunds are capped to gasUsed / 5 + minGasUsedPct := k.GetMinGasUsedMultiplier(ctx) // Evmos invention: https://github.com/evmos/ethermint/issues/1085 + if fullRefundLeftoverGas { + refundQuotient = 1 // 100% refund + minGasUsedPct = math.LegacyZeroDec() // no minimum, get the actual gasUsed value } + temporaryGasUsed := msg.Gas() - leftoverGas + refund := GasToRefund(stateDB.GetRefund(), temporaryGasUsed, refundQuotient) + // update leftoverGas and temporaryGasUsed with refund amount + leftoverGas += refund + temporaryGasUsed -= refund if msg.Gas() < leftoverGas { - return nil, evmObj, errors.Wrapf(evm.ErrGasOverflow, "message gas limit < leftover gas (%d < %d)", msg.Gas(), leftoverGas) + return nil, evmObj, errors.Wrapf(core.ErrGasUintOverflow, "ApplyEvmMsg: message gas limit (%d) < leftover gas (%d)", msg.Gas(), leftoverGas) } + // Min gas used is a % of gasLimit + minimumGasUsed := math.LegacyNewDec(int64(msg.Gas())).Mul(minGasUsedPct) gasUsed := math.LegacyMaxDec(minimumGasUsed, math.LegacyNewDec(int64(temporaryGasUsed))).TruncateInt().Uint64() // This resulting "leftoverGas" is used by the tracer. This happens as a @@ -395,7 +405,7 @@ func ParseWeiAsMultipleOfMicronibi(weiInt *big.Int) (newWeiInt *big.Int, err err tenPow12 := new(big.Int).Exp(big.NewInt(10), big.NewInt(12), nil) if weiInt.Cmp(tenPow12) < 0 { return weiInt, fmt.Errorf( - "wei amount is too small (%s), cannot transfer less than 1 micronibi. 10^18 wei == 1 NIBI == 10^6 micronibi", weiInt) + "wei amount is too small (%s), cannot transfer less than 1 micronibi. 1 NIBI == 10^6 micronibi == 10^18 wei", weiInt) } // truncate to highest micronibi amount @@ -526,6 +536,7 @@ func (k Keeper) convertCoinToEvmBornCoin( evm.EVM_MODULE_ADDRESS, &erc20Addr, true, + Erc20GasLimitExecute, "mint", recipient, coin.Amount.BigInt(), @@ -578,7 +589,7 @@ func (k Keeper) convertCoinToEvmBornERC20( // converted to its Bank Coin representation, a balance of the ERC20 is left // inside the EVM module account in order to convert the coins back to // ERC20s. - actualSentAmount, err := k.ERC20().Transfer( + actualSentAmount, _, err := k.ERC20().Transfer( erc20Addr, evm.EVM_MODULE_ADDRESS, recipient, @@ -635,20 +646,9 @@ func (k *Keeper) EmitEthereumTxEvents( } err := ctx.EventManager().EmitTypedEvent(eventEthereumTx) if err != nil { - return errors.Wrap(err, "failed to emit event ethereum tx") + return errors.Wrap(err, "EmitEthereumTxEvents: failed to emit event ethereum tx") } - // Typed event: eth.evm.v1.EventTxLog - txLogs := make([]string, len(evmResp.Logs)) - for i, log := range evmResp.Logs { - value, err := json.Marshal(log) - if err != nil { - return errors.Wrap(err, "failed to encode log") - } - txLogs[i] = string(value) - } - _ = ctx.EventManager().EmitTypedEvent(&evm.EventTxLog{TxLogs: txLogs}) - // Untyped event: "message", used for tendermint subscription ctx.EventManager().EmitEvent( sdk.NewEvent( @@ -684,6 +684,25 @@ func (k *Keeper) EmitEthereumTxEvents( return nil } +// EmitLogEvents emits all types of EVM events applicable to a particular execution case +func (k *Keeper) EmitLogEvents( + ctx sdk.Context, + evmResp *evm.MsgEthereumTxResponse, +) error { + // Typed event: eth.evm.v1.EventTxLog + txLogs := make([]string, len(evmResp.Logs)) + for i, log := range evmResp.Logs { + value, err := json.Marshal(log) + if err != nil { + return errors.Wrap(err, "failed to encode log") + } + txLogs[i] = string(value) + } + _ = ctx.EventManager().EmitTypedEvent(&evm.EventTxLog{TxLogs: txLogs}) + + return nil +} + // updateBlockBloom updates transient block bloom filter func (k *Keeper) updateBlockBloom( ctx sdk.Context, diff --git a/x/evm/msg.go b/x/evm/msg.go index e1e4edc6e..53b607106 100644 --- a/x/evm/msg.go +++ b/x/evm/msg.go @@ -15,7 +15,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/signing" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" @@ -154,7 +154,7 @@ func (msg MsgEthereumTx) ValidateBasic() error { // Validate Size_ field, should be kept empty if msg.Size_ != 0 { - return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "tx size is deprecated") + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "tx size is deprecated") } txData, err := UnpackTxData(msg.Data) @@ -166,12 +166,12 @@ func (msg MsgEthereumTx) ValidateBasic() error { // prevent txs with 0 gas to fill up the mempool if gas == 0 { - return errorsmod.Wrap(ErrInvalidGasLimit, "gas limit must not be zero") + return errorsmod.Wrap(sdkerrors.ErrInvalidGasLimit, "gas limit must not be zero") } // prevent gas limit from overflow if g := new(big.Int).SetUint64(gas); !g.IsInt64() { - return errorsmod.Wrap(ErrGasOverflow, "gas limit must be less than math.MaxInt64") + return errorsmod.Wrap(core.ErrGasUintOverflow, "gas limit must be less than math.MaxInt64") } if err := txData.Validate(); err != nil { @@ -181,7 +181,7 @@ func (msg MsgEthereumTx) ValidateBasic() error { // Validate EthHash field after validated txData to avoid panic txHash := msg.AsTransaction().Hash().Hex() if msg.Hash != txHash { - return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid tx hash %s, expected: %s", msg.Hash, txHash) + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid tx hash %s, expected: %s", msg.Hash, txHash) } return nil diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index b1fc0239d..167c815f5 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -23,6 +23,18 @@ var _ vm.PrecompiledContract = (*precompileFunToken)(nil) // using the ERC20's `FunToken` mapping. var PrecompileAddr_FunToken = gethcommon.HexToAddress("0x0000000000000000000000000000000000000800") +const ( + // FunTokenGasLimitBankSend consists of gas for 3 calls: + // 1. transfer erc20 from sender to module + // ~60_000 gas for regular erc20 transfer (our own ERC20Minter contract) + // could be higher for user created contracts, let's cap with 200_000 + // 2. mint native coin (made from erc20) or burn erc20 token (made from coin) + // ~60_000 gas for either mint or burn + // 3. send from module to account: + // ~65_000 gas (bank send) + FunTokenGasLimitBankSend uint64 = 400_000 +) + func (p precompileFunToken) Address() gethcommon.Address { return PrecompileAddr_FunToken } @@ -47,16 +59,19 @@ func (p precompileFunToken) Run( defer func() { err = ErrPrecompileRun(err, p) }() - start, err := OnRunStart(evm, contract.Input, p.ABI()) + startResult, err := OnRunStart(evm, contract.Input, p.ABI(), contract.Gas) if err != nil { return nil, err } - p.evmKeeper.Bank.StateDB = start.StateDB + p.evmKeeper.Bank.StateDB = startResult.StateDB - method := start.Method + // Gracefully handles "out of gas" + defer HandleOutOfGasPanic(&err)() + + method := startResult.Method switch PrecompileMethod(method.Name) { case FunTokenMethod_BankSend: - bz, err = p.bankSend(start, contract.CallerAddress, readonly) + bz, err = p.bankSend(startResult, contract.CallerAddress, readonly) default: // Note that this code path should be impossible to reach since // "DecomposeInput" parses methods directly from the ABI. @@ -66,6 +81,9 @@ func (p precompileFunToken) Run( if err != nil { return nil, err } + + // Gas consumed by a local gas meter + contract.UseGas(startResult.CacheCtx.GasMeter().GasConsumed()) return bz, err } @@ -91,11 +109,11 @@ type precompileFunToken struct { // function bankSend(address erc20, uint256 amount, string memory to) external; // ``` func (p precompileFunToken) bankSend( - start OnRunStartResult, + startResult OnRunStartResult, caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - ctx, method, args := start.CacheCtx, start.Method, start.Args + ctx, method, args := startResult.CacheCtx, startResult.Method, startResult.Args if err := assertNotReadonlyTx(readOnly, method); err != nil { return nil, err } @@ -105,6 +123,8 @@ func (p precompileFunToken) bankSend( return } + var evmResponses []*evm.MsgEthereumTxResponse + // ERC20 must have FunToken mapping funtokens := p.evmKeeper.FunTokens.Collect( ctx, p.evmKeeper.FunTokens.Indexes.ERC20Addr.ExactMatch(ctx, erc20), @@ -128,10 +148,11 @@ func (p precompileFunToken) bankSend( // Caller transfers ERC20 to the EVM account transferTo := evm.EVM_MODULE_ADDRESS - gotAmount, err := p.evmKeeper.ERC20().Transfer(erc20, caller, transferTo, amount, ctx) + gotAmount, transferResp, err := p.evmKeeper.ERC20().Transfer(erc20, caller, transferTo, amount, ctx) if err != nil { return nil, fmt.Errorf("error in ERC20.transfer from caller to EVM account: %w", err) } + evmResponses = append(evmResponses, transferResp) // EVM account mints FunToken.BankDenom to module account coinToSend := sdk.NewCoin(funtoken.BankDenom, math.NewIntFromBigInt(gotAmount)) @@ -140,17 +161,18 @@ func (p precompileFunToken) bankSend( // owns the ERC20 contract and was the original minter of the ERC20 tokens. // Since we're sending them away and want accurate total supply tracking, the // tokens need to be burned. - _, err = p.evmKeeper.ERC20().Burn(erc20, evm.EVM_MODULE_ADDRESS, gotAmount, ctx) - if err != nil { - err = fmt.Errorf("ERC20.Burn: %w", err) + burnResp, e := p.evmKeeper.ERC20().Burn(erc20, evm.EVM_MODULE_ADDRESS, gotAmount, ctx) + if e != nil { + err = fmt.Errorf("ERC20.Burn: %w", e) return } + evmResponses = append(evmResponses, burnResp) } else { // NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before // any operation that has the potential to use Bank send methods. This will // guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are // recorded if wei (NIBI) is transferred. - p.evmKeeper.Bank.StateDB = start.StateDB + p.evmKeeper.Bank.StateDB = startResult.StateDB err = p.evmKeeper.Bank.MintCoins(ctx, evm.ModuleName, sdk.NewCoins(coinToSend)) if err != nil { return nil, fmt.Errorf("mint failed for module \"%s\" (%s): contract caller %s: %w", @@ -165,7 +187,7 @@ func (p precompileFunToken) bankSend( // any operation that has the potential to use Bank send methods. This will // guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are // recorded if wei (NIBI) is transferred. - p.evmKeeper.Bank.StateDB = start.StateDB + p.evmKeeper.Bank.StateDB = startResult.StateDB err = p.evmKeeper.Bank.SendCoinsFromModuleToAccount( ctx, evm.ModuleName, @@ -177,6 +199,11 @@ func (p precompileFunToken) bankSend( evm.ModuleName, evm.EVM_MODULE_ADDRESS.Hex(), caller.Hex(), err, ) } + for _, resp := range evmResponses { + for _, log := range resp.Logs { + startResult.StateDB.AddLog(log.ToEthereum()) + } + } // TODO: UD-DEBUG: feat: Emit EVM events diff --git a/x/evm/precompile/funtoken_test.go b/x/evm/precompile/funtoken_test.go index a17836582..6a6fe29d7 100644 --- a/x/evm/precompile/funtoken_test.go +++ b/x/evm/precompile/funtoken_test.go @@ -14,6 +14,7 @@ import ( "github.com/NibiruChain/nibiru/v2/x/evm" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" "github.com/NibiruChain/nibiru/v2/x/evm/evmtest" + "github.com/NibiruChain/nibiru/v2/x/evm/keeper" "github.com/NibiruChain/nibiru/v2/x/evm/precompile" ) @@ -25,6 +26,16 @@ func TestSuite(t *testing.T) { type FuntokenSuite struct { suite.Suite + deps evmtest.TestDeps + funtoken evm.FunToken +} + +func (s *FuntokenSuite) SetupSuite() { + s.deps = evmtest.NewTestDeps() + + s.T().Log("Create FunToken from coin") + bankDenom := "unibi" + s.funtoken = evmtest.CreateFunTokenForBankCoin(&s.deps, bankDenom, &s.Suite) } func (s *FuntokenSuite) TestFailToPackABI() { @@ -83,6 +94,7 @@ func (s *FuntokenSuite) TestHappyPath() { s.T().Log("Create FunToken mapping and ERC20") bankDenom := "unibi" funtoken := evmtest.CreateFunTokenForBankCoin(&deps, bankDenom, &s.Suite) + erc20 := funtoken.Erc20Addr.Address s.T().Log("Balances of the ERC20 should start empty") @@ -93,14 +105,14 @@ func (s *FuntokenSuite) TestHappyPath() { deps.App.BankKeeper, deps.Ctx, deps.Sender.NibiruAddr, - sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(69_420))), + sdk.NewCoins(sdk.NewCoin(s.funtoken.BankDenom, sdk.NewInt(69_420))), )) _, err := deps.EvmKeeper.ConvertCoinToEvm( sdk.WrapSDKContext(deps.Ctx), &evm.MsgConvertCoinToEvm{ Sender: deps.Sender.NibiruAddr.String(), - BankCoin: sdk.NewCoin(bankDenom, sdk.NewInt(69_420)), + BankCoin: sdk.NewCoin(s.funtoken.BankDenom, sdk.NewInt(69_420)), ToEthAddr: eth.EIP55Addr{ Address: deps.Sender.EthAddr, }, @@ -110,11 +122,8 @@ func (s *FuntokenSuite) TestHappyPath() { s.T().Log("Mint tokens - Fail from non-owner") { - input, err := embeds.SmartContract_ERC20Minter.ABI.Pack("mint", deps.Sender.EthAddr, big.NewInt(69_420)) - s.NoError(err) - _, _, err = deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &erc20, true, input, - ) + s.deps.ResetGasMeter() + _, err = deps.EvmKeeper.CallContract(deps.Ctx, embeds.SmartContract_ERC20Minter.ABI, deps.Sender.EthAddr, &erc20, true, keeper.Erc20GasLimitExecute, "mint", deps.Sender.EthAddr, big.NewInt(69_420)) s.ErrorContains(err, "Ownable: caller is not the owner") } @@ -126,6 +135,7 @@ func (s *FuntokenSuite) TestHappyPath() { input, err := embeds.SmartContract_FunToken.ABI.Pack(string(precompile.FunTokenMethod_BankSend), callArgs...) s.NoError(err) + deps.ResetGasMeter() _, ethTxResp, err := evmtest.CallContractTx( &deps, precompile.PrecompileAddr_FunToken, @@ -145,6 +155,7 @@ func (s *FuntokenSuite) TestHappyPath() { s.Equal(sdk.NewInt(420).String(), deps.App.BankKeeper.GetBalance(deps.Ctx, randomAcc, funtoken.BankDenom).Amount.String(), ) + s.deps.ResetGasMeter() s.Require().NotNil(deps.EvmKeeper.Bank.StateDB) s.T().Log("Parse the response contract addr and response bytes") @@ -157,3 +168,86 @@ func (s *FuntokenSuite) TestHappyPath() { s.NoError(err) s.Require().Equal("420", sentAmt.String()) } + +func (s *FuntokenSuite) TestPrecompileLocalGas() { + deps := s.deps + randomAcc := testutil.AccAddress() + + deployResp, err := evmtest.DeployContract( + &deps, embeds.SmartContract_TestFunTokenPrecompileLocalGas, + s.funtoken.Erc20Addr.Address, + ) + s.Require().NoError(err) + contractAddr := deployResp.ContractAddr + + s.T().Log("Fund sender's wallet") + s.Require().NoError(testapp.FundAccount( + deps.App.BankKeeper, + deps.Ctx, + deps.Sender.NibiruAddr, + sdk.NewCoins(sdk.NewCoin(s.funtoken.BankDenom, sdk.NewInt(1000))), + )) + + s.T().Log("Fund contract with erc20 coins") + _, err = deps.EvmKeeper.ConvertCoinToEvm( + sdk.WrapSDKContext(deps.Ctx), + &evm.MsgConvertCoinToEvm{ + Sender: deps.Sender.NibiruAddr.String(), + BankCoin: sdk.NewCoin(s.funtoken.BankDenom, sdk.NewInt(1000)), + ToEthAddr: eth.EIP55Addr{ + Address: contractAddr, + }, + }, + ) + s.Require().NoError(err) + + s.deps.ResetGasMeter() + + s.T().Log("Happy: callBankSend with default gas") + _, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_TestFunTokenPrecompileLocalGas.ABI, + deps.Sender.EthAddr, + &contractAddr, + true, + precompile.FunTokenGasLimitBankSend, + "callBankSend", + big.NewInt(1), + randomAcc.String(), + ) + s.Require().NoError(err) + + s.deps.ResetGasMeter() + + s.T().Log("Happy: callBankSend with local gas - sufficient gas amount") + _, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_TestFunTokenPrecompileLocalGas.ABI, + deps.Sender.EthAddr, + &contractAddr, + true, + precompile.FunTokenGasLimitBankSend, // gasLimit for the entire call + "callBankSendLocalGas", + big.NewInt(1), // erc20 amount + randomAcc.String(), // to + big.NewInt(int64(precompile.FunTokenGasLimitBankSend)), // customGas + ) + s.Require().NoError(err) + + s.deps.ResetGasMeter() + + s.T().Log("Sad: callBankSend with local gas - insufficient gas amount") + _, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_TestFunTokenPrecompileLocalGas.ABI, + deps.Sender.EthAddr, + &contractAddr, + true, + precompile.FunTokenGasLimitBankSend, // gasLimit for the entire call + "callBankSendLocalGas", + big.NewInt(1), // erc20 amount + randomAcc.String(), // to + big.NewInt(50_000), // customGas - too small + ) + s.Require().ErrorContains(err, "execution reverted") +} diff --git a/x/evm/precompile/oracle.go b/x/evm/precompile/oracle.go index cf461a3c4..6aae97bcc 100644 --- a/x/evm/precompile/oracle.go +++ b/x/evm/precompile/oracle.go @@ -42,7 +42,7 @@ func (p precompileOracle) Run( defer func() { err = ErrPrecompileRun(err, p) }() - startResult, err := OnRunStart(evm, contract.Input, p.ABI()) + startResult, err := OnRunStart(evm, contract.Input, p.ABI(), contract.Gas) if err != nil { return nil, err } diff --git a/x/evm/precompile/oracle_test.go b/x/evm/precompile/oracle_test.go index fa07d72d6..1051e12aa 100644 --- a/x/evm/precompile/oracle_test.go +++ b/x/evm/precompile/oracle_test.go @@ -14,6 +14,8 @@ import ( "github.com/NibiruChain/nibiru/v2/x/evm/precompile" ) +const OracleGasLimitQuery = 100_000 + func (s *OracleSuite) TestOracle_FailToPackABI() { testcases := []struct { name string @@ -60,10 +62,15 @@ func (s *OracleSuite) TestOracle_HappyPath() { deps.Ctx = deps.Ctx.WithBlockTime(time.Unix(69, 420)).WithBlockHeight(69) deps.App.OracleKeeper.SetPrice(deps.Ctx, "unibi:uusd", sdk.MustNewDecFromStr("0.067")) - input, err := embeds.SmartContract_Oracle.ABI.Pack("queryExchangeRate", "unibi:uusd") - s.NoError(err) - resp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Oracle, true, input, + resp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Oracle.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Oracle, + false, + OracleGasLimitQuery, + "queryExchangeRate", + "unibi:uusd", ) s.NoError(err) diff --git a/x/evm/precompile/precompile.go b/x/evm/precompile/precompile.go index 234a27f4b..cf3056a5c 100644 --- a/x/evm/precompile/precompile.go +++ b/x/evm/precompile/precompile.go @@ -19,13 +19,12 @@ import ( "github.com/NibiruChain/collections" store "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" gethabi "github.com/ethereum/go-ethereum/accounts/abi" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" gethparams "github.com/ethereum/go-ethereum/params" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/NibiruChain/nibiru/v2/app/keepers" "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) @@ -179,7 +178,7 @@ type OnRunStartResult struct { // } // ``` func OnRunStart( - evm *vm.EVM, contractInput []byte, abi *gethabi.ABI, + evm *vm.EVM, contractInput []byte, abi *gethabi.ABI, gasLimit uint64, ) (res OnRunStartResult, err error) { method, args, err := decomposeInput(abi, contractInput) if err != nil { @@ -203,6 +202,11 @@ func OnRunStart( return res, fmt.Errorf("error committing dirty journal entries: %w", err) } + // Switching to a local gas meter to enforce gas limit check for a precompile + cacheCtx = cacheCtx.WithGasMeter(sdk.NewGasMeter(gasLimit)). + WithKVGasConfig(store.KVGasConfig()). + WithTransientKVGasConfig(store.TransientGasConfig()) + return OnRunStartResult{ Args: args, CacheCtx: cacheCtx, @@ -222,3 +226,16 @@ var isMutation map[PrecompileMethod]bool = map[PrecompileMethod]bool{ OracleMethod_queryExchangeRate: false, } + +func HandleOutOfGasPanic(err *error) func() { + return func() { + if r := recover(); r != nil { + switch r.(type) { + case sdk.ErrorOutOfGas: + *err = vm.ErrOutOfGas + default: + panic(r) + } + } + } +} diff --git a/x/evm/precompile/test/export.go b/x/evm/precompile/test/export.go index 24700ce85..ef1b91737 100644 --- a/x/evm/precompile/test/export.go +++ b/x/evm/precompile/test/export.go @@ -21,6 +21,13 @@ import ( "github.com/NibiruChain/nibiru/v2/x/evm/precompile" ) +// rough gas limits for wasm execution - used in tests only +const ( + WasmGasLimitInstantiate uint64 = 1_000_000 + WasmGasLimitExecute uint64 = 10_000_000 + WasmGasLimitQuery uint64 = 200_000 +) + // SetupWasmContracts stores all Wasm bytecode and has the "deps.Sender" // instantiate each Wasm contract using the precompile. func SetupWasmContracts(deps *evmtest.TestDeps, s *suite.Suite) ( @@ -56,16 +63,17 @@ func SetupWasmContracts(deps *evmtest.TestDeps, s *suite.Suite) ( msgArgsBz, err := json.Marshal(m.Msg) s.NoError(err) - callArgs := []any{m.Admin, m.CodeID, msgArgsBz, m.Label, []precompile.WasmBankCoin{}} - input, err := embeds.SmartContract_Wasm.ABI.Pack( + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitInstantiate, string(precompile.WasmMethod_instantiate), - callArgs..., + []any{m.Admin, m.CodeID, msgArgsBz, m.Label, []precompile.WasmBankCoin{}}..., ) - s.Require().NoError(err) - ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, - ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) @@ -150,27 +158,27 @@ func AssertWasmCounterState( deps evmtest.TestDeps, wasmContract sdk.AccAddress, wantCount int64, -) (evmObj *vm.EVM) { +) { msgArgsBz := []byte(` { "count": {} } - `) - - callArgs := []any{ - // string memory contractAddr - wasmContract.String(), - // bytes memory req - msgArgsBz, - } - input, err := embeds.SmartContract_Wasm.ABI.Pack( +`) + + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitQuery, string(precompile.WasmMethod_query), - callArgs..., - ) - s.Require().NoError(err) - - ethTxResp, evmObj, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + []any{ + // string memory contractAddr + wasmContract.String(), + // bytes memory req + msgArgsBz, + }..., ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) @@ -191,16 +199,14 @@ func AssertWasmCounterState( s.T().Log("Response is a JSON-encoded struct from the Wasm contract") var wasmMsg wasm.RawContractMessage - err = json.Unmarshal(queryResp, &wasmMsg) - s.NoError(err) + s.NoError(json.Unmarshal(queryResp, &wasmMsg)) s.NoError(wasmMsg.ValidateBasic()) + var typedResp QueryMsgCountResp - err = json.Unmarshal(wasmMsg, &typedResp) - s.NoError(err) + s.NoError(json.Unmarshal(queryResp, &typedResp)) s.EqualValues(wantCount, typedResp.Count) s.EqualValues(deps.Sender.NibiruAddr.String(), typedResp.Owner) - return evmObj } // Result of QueryMsg::Count from the [hello_world_counter] Wasm contract: @@ -292,8 +298,15 @@ func IncrementWasmCounterWithExecuteMulti( ) s.Require().NoError(err) + deps.ResetGasMeter() + ethTxResp, evmObj, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, finalizeTx, input, + deps.Ctx, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + finalizeTx, + input, + WasmGasLimitExecute, ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) diff --git a/x/evm/precompile/wasm.go b/x/evm/precompile/wasm.go index 0c7753564..c42df76eb 100644 --- a/x/evm/precompile/wasm.go +++ b/x/evm/precompile/wasm.go @@ -38,11 +38,14 @@ func (p precompileWasm) Run( defer func() { err = ErrPrecompileRun(err, p) }() - startResult, err := OnRunStart(evm, contract.Input, p.ABI()) + startResult, err := OnRunStart(evm, contract.Input, p.ABI(), contract.Gas) if err != nil { return nil, err } + // Gracefully handles "out of gas" + defer HandleOutOfGasPanic(&err)() + // NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before // any operation that has the potential to use Bank send methods. This will // guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are @@ -68,6 +71,10 @@ func (p precompileWasm) Run( if err != nil { return nil, err } + + // Gas consumed by a local gas meter + contract.UseGas(startResult.CacheCtx.GasMeter().GasConsumed()) + return bz, err } diff --git a/x/evm/precompile/wasm_test.go b/x/evm/precompile/wasm_test.go index 72c45046c..b0f40dd79 100644 --- a/x/evm/precompile/wasm_test.go +++ b/x/evm/precompile/wasm_test.go @@ -19,6 +19,12 @@ import ( "github.com/stretchr/testify/suite" ) +// rough gas limits for wasm execution - used in tests only +const ( + WasmGasLimitQuery uint64 = 200_000 + WasmGasLimitExecute uint64 = 1_000_000 +) + type WasmSuite struct { suite.Suite } @@ -42,19 +48,19 @@ func (s *WasmSuite) TestExecuteHappy() { err = json.Unmarshal(fundsJson, &funds) s.Require().NoError(err, "fundsJson %s, funds %s", fundsJson, funds) - callArgs := []any{ - wasmContract.String(), - msgArgsBz, - funds, - } - input, err := embeds.SmartContract_Wasm.ABI.Pack( + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitExecute, string(precompile.WasmMethod_execute), - callArgs..., - ) - s.Require().NoError(err) - - ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + []any{ + wasmContract.String(), + msgArgsBz, + funds, + }..., ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) @@ -72,23 +78,26 @@ func (s *WasmSuite) TestExecuteHappy() { } } `, coinDenom, deps.Sender.NibiruAddr)) - callArgs = []any{ - wasmContract.String(), - msgArgsBz, - funds, - } - input, err = embeds.SmartContract_Wasm.ABI.Pack( + + ethTxResp, err = deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitExecute, string(precompile.WasmMethod_execute), - callArgs..., - ) - s.Require().NoError(err) - ethTxResp, _, err = deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + []any{ + wasmContract.String(), + msgArgsBz, + funds, + }..., ) + s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) evmtest.AssertBankBalanceEqual( - s.T(), deps, coinDenom, deps.Sender.EthAddr, big.NewInt(69420), + s.T(), deps, coinDenom, deps.Sender.EthAddr, big.NewInt(69_420), ) } @@ -126,19 +135,20 @@ func (s *WasmSuite) assertWasmCounterStateRaw( wasmContract sdk.AccAddress, wantCount int64, ) { - keyBz := []byte(`state`) - callArgs := []any{ - wasmContract.String(), - keyBz, - } - input, err := embeds.SmartContract_Wasm.ABI.Pack( - string(precompile.WasmMethod_queryRaw), - callArgs..., - ) - s.Require().NoError(err) + deps.ResetGasMeter() - ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitQuery, + string(precompile.WasmMethod_queryRaw), + []any{ + wasmContract.String(), + []byte(`state`), + }..., ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) @@ -300,16 +310,17 @@ func (s *WasmSuite) TestSadArgsExecute() { s.Run(tc.name, func() { deps := evmtest.NewTestDeps() - callArgs := tc.callArgs - input, err := abi.Pack( + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + abi, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitExecute, string(tc.methodName), - callArgs..., + tc.callArgs..., ) - s.Require().NoError(err) - ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, - ) s.Require().ErrorContains(err, tc.wantError, "ethTxResp %v", ethTxResp) }) } @@ -432,15 +443,15 @@ func (s *WasmSuite) TestExecuteMultiValidation() { for _, tc := range testCases { s.Run(tc.name, func() { - callArgs := []any{tc.executeMsgs} - input, err := embeds.SmartContract_Wasm.ABI.Pack( + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitExecute, string(precompile.WasmMethod_executeMulti), - callArgs..., - ) - s.Require().NoError(err) - - ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + []any{tc.executeMsgs}..., ) if tc.wantError != "" { @@ -478,15 +489,15 @@ func (s *WasmSuite) TestExecuteMultiPartialExecution() { }, } - callArgs := []any{executeMsgs} - input, err := embeds.SmartContract_Wasm.ABI.Pack( + ethTxResp, err := deps.EvmKeeper.CallContract( + deps.Ctx, + embeds.SmartContract_Wasm.ABI, + deps.Sender.EthAddr, + &precompile.PrecompileAddr_Wasm, + true, + WasmGasLimitExecute, string(precompile.WasmMethod_executeMulti), - callArgs..., - ) - s.Require().NoError(err) - - ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, + []any{executeMsgs}..., ) // Verify that the call failed diff --git a/x/evm/statedb/journal_test.go b/x/evm/statedb/journal_test.go index c1c74110c..75fc9b6a0 100644 --- a/x/evm/statedb/journal_test.go +++ b/x/evm/statedb/journal_test.go @@ -10,6 +10,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/NibiruChain/nibiru/v2/x/evm/keeper" + serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" "github.com/NibiruChain/nibiru/v2/x/common" "github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp" @@ -52,7 +54,12 @@ func (s *Suite) TestComplexJournalChanges() { input, err := deps.EvmKeeper.ERC20().ABI.Pack("mint", to, amount) s.Require().NoError(err) _, evmObj, err := deps.EvmKeeper.CallContractWithInput( - deps.Ctx, deps.Sender.EthAddr, &contract, true, input, + deps.Ctx, + deps.Sender.EthAddr, + &contract, + true, + input, + keeper.Erc20GasLimitExecute, ) s.Require().NoError(err)