diff --git a/Cargo.lock b/Cargo.lock index ccf00d13fb..9d6a24c147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2539,12 +2539,14 @@ dependencies = [ "cow-contract-honeyswaprouter", "cow-contract-hookstrampoline", "cow-contract-icowwrapper", + "cow-contract-ierc4626", "cow-contract-iswaprpair", "cow-contract-iuniswaplikepair", "cow-contract-iuniswaplikerouter", "cow-contract-iuniswapv3factory", "cow-contract-izeroex", "cow-contract-liquoricesettlement", + "cow-contract-mockerc4626wrapper", "cow-contract-nonstandarderc20balances", "cow-contract-pancakerouter", "cow-contract-permit2", @@ -3216,6 +3218,17 @@ dependencies = [ "anyhow", ] +[[package]] +name = "cow-contract-ierc4626" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-primitives", + "alloy-provider", + "alloy-sol-types", + "anyhow", +] + [[package]] name = "cow-contract-iswaprpair" version = "0.1.0" @@ -3282,6 +3295,17 @@ dependencies = [ "anyhow", ] +[[package]] +name = "cow-contract-mockerc4626wrapper" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-primitives", + "alloy-provider", + "alloy-sol-types", + "anyhow", +] + [[package]] name = "cow-contract-nonstandarderc20balances" version = "0.1.0" @@ -6347,6 +6371,7 @@ dependencies = [ "configs", "const-hex", "contracts", + "dashmap", "derive_more 1.0.0", "ethrpc", "futures", diff --git a/contracts/.gitignore b/contracts/.gitignore index 05923927ff..c0388e3cc4 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -1,2 +1,4 @@ /target +/out +/cache .DS_Store diff --git a/contracts/artifacts/IERC4626.json b/contracts/artifacts/IERC4626.json new file mode 100644 index 0000000000..2d0eac6929 --- /dev/null +++ b/contracts/artifacts/IERC4626.json @@ -0,0 +1,36 @@ +{ + "abi": [ + { + "type": "function", + "name": "asset", + "inputs": [], + "outputs": [ + { + "name": "assetTokenAddress", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "convertToAssets", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + } + ] +} diff --git a/contracts/artifacts/MockERC4626Wrapper.json b/contracts/artifacts/MockERC4626Wrapper.json new file mode 100644 index 0000000000..4bbe02465e --- /dev/null +++ b/contracts/artifacts/MockERC4626Wrapper.json @@ -0,0 +1,240 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [ + { + "name": "_asset", + "type": "address", + "internalType": "address" + }, + { + "name": "_decimals", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "_rateNumerator", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_rateDenominator", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "approve", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "asset", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "convertToAssets", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "uint8" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mint", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "rateDenominator", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "rateNumerator", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "transfer", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [ + { + "name": "from", + "type": "address", + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + } + ], + "bytecode": "0x610100604052348015610010575f5ffd5b50604051610c17380380610c1783398181016040528101906100329190610154565b8373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508260ff1660a08160ff16815250508160c081815250508060e08181525050505050506101b8565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100ba82610091565b9050919050565b6100ca816100b0565b81146100d4575f5ffd5b50565b5f815190506100e5816100c1565b92915050565b5f60ff82169050919050565b610100816100eb565b811461010a575f5ffd5b50565b5f8151905061011b816100f7565b92915050565b5f819050919050565b61013381610121565b811461013d575f5ffd5b50565b5f8151905061014e8161012a565b92915050565b5f5f5f5f6080858703121561016c5761016b61008d565b5b5f610179878288016100d7565b945050602061018a8782880161010d565b935050604061019b87828801610140565b92505060606101ac87828801610140565b91505092959194509250565b60805160a05160c05160e051610a1e6101f95f395f8181610262015261055c01525f8181610283015261034801525f6104aa01525f6104ce0152610a1e5ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c806338d52e0f1161006f57806338d52e0f1461017757806340c10f191461019557806370a08231146101b1578063865192f7146101e1578063a9059cbb146101ff578063dd62ed3e1461022f576100a7565b806307a2d13a146100ab578063095ea7b3146100db5780630b36b8db1461010b57806323b872dd14610129578063313ce56714610159575b5f5ffd5b6100c560048036038101906100c09190610684565b61025f565b6040516100d291906106be565b60405180910390f35b6100f560048036038101906100f09190610731565b6102be565b6040516101029190610789565b60405180910390f35b610113610346565b60405161012091906106be565b60405180910390f35b610143600480360381019061013e91906107a2565b61036a565b6040516101509190610789565b60405180910390f35b6101616104a8565b60405161016e919061080d565b60405180910390f35b61017f6104cc565b60405161018c9190610835565b60405180910390f35b6101af60048036038101906101aa9190610731565b6104f0565b005b6101cb60048036038101906101c6919061084e565b610546565b6040516101d891906106be565b60405180910390f35b6101e961055a565b6040516101f691906106be565b60405180910390f35b61021960048036038101906102149190610731565b61057e565b6040516102269190610789565b60405180910390f35b61024960048036038101906102449190610879565b61062d565b60405161025691906106be565b60405180910390f35b5f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000836102ad91906108e4565b6102b79190610952565b9050919050565b5f8160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546103f29190610982565b92505081905550815f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546104449190610982565b92505081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461049691906109b5565b92505081905550600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461053b91906109b5565b925050819055505050565b5f602052805f5260405f205f915090505481565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f815f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ca9190610982565b92505081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461061c91906109b5565b925050819055506001905092915050565b6001602052815f5260405f20602052805f5260405f205f91509150505481565b5f5ffd5b5f819050919050565b61066381610651565b811461066d575f5ffd5b50565b5f8135905061067e8161065a565b92915050565b5f602082840312156106995761069861064d565b5b5f6106a684828501610670565b91505092915050565b6106b881610651565b82525050565b5f6020820190506106d15f8301846106af565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610700826106d7565b9050919050565b610710816106f6565b811461071a575f5ffd5b50565b5f8135905061072b81610707565b92915050565b5f5f604083850312156107475761074661064d565b5b5f6107548582860161071d565b925050602061076585828601610670565b9150509250929050565b5f8115159050919050565b6107838161076f565b82525050565b5f60208201905061079c5f83018461077a565b92915050565b5f5f5f606084860312156107b9576107b861064d565b5b5f6107c68682870161071d565b93505060206107d78682870161071d565b92505060406107e886828701610670565b9150509250925092565b5f60ff82169050919050565b610807816107f2565b82525050565b5f6020820190506108205f8301846107fe565b92915050565b61082f816106f6565b82525050565b5f6020820190506108485f830184610826565b92915050565b5f602082840312156108635761086261064d565b5b5f6108708482850161071d565b91505092915050565b5f5f6040838503121561088f5761088e61064d565b5b5f61089c8582860161071d565b92505060206108ad8582860161071d565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6108ee82610651565b91506108f983610651565b925082820261090781610651565b9150828204841483151761091e5761091d6108b7565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61095c82610651565b915061096783610651565b92508261097757610976610925565b5b828204905092915050565b5f61098c82610651565b915061099783610651565b92508282039050818111156109af576109ae6108b7565b5b92915050565b5f6109bf82610651565b91506109ca83610651565b92508282019050808211156109e2576109e16108b7565b5b9291505056fea2646970667358221220b5ebafab2270a2c41eb9cd473eb8aca958511fe12b7302559d197e2a8704c94b64736f6c634300081e0033" +} diff --git a/contracts/generated/Cargo.lock b/contracts/generated/Cargo.lock index fd0489b2d0..100d862231 100644 --- a/contracts/generated/Cargo.lock +++ b/contracts/generated/Cargo.lock @@ -1048,6 +1048,7 @@ dependencies = [ "cow-contract-cowammlegacyhelper", "cow-contract-cowammuniswapv2priceoracle", "cow-contract-cowprotocoltoken", + "cow-contract-cowsettlementforwarder", "cow-contract-cowswapethflow", "cow-contract-cowswaponchainorders", "cow-contract-erc1271signaturevalidator", @@ -1064,12 +1065,14 @@ dependencies = [ "cow-contract-honeyswaprouter", "cow-contract-hookstrampoline", "cow-contract-icowwrapper", + "cow-contract-ierc4626", "cow-contract-iswaprpair", "cow-contract-iuniswaplikepair", "cow-contract-iuniswaplikerouter", "cow-contract-iuniswapv3factory", "cow-contract-izeroex", "cow-contract-liquoricesettlement", + "cow-contract-mockerc4626wrapper", "cow-contract-nonstandarderc20balances", "cow-contract-pancakerouter", "cow-contract-permit2", @@ -1468,6 +1471,17 @@ dependencies = [ "anyhow", ] +[[package]] +name = "cow-contract-cowsettlementforwarder" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-primitives", + "alloy-provider", + "alloy-sol-types", + "anyhow", +] + [[package]] name = "cow-contract-cowswapethflow" version = "0.1.0" @@ -1644,6 +1658,17 @@ dependencies = [ "anyhow", ] +[[package]] +name = "cow-contract-ierc4626" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-primitives", + "alloy-provider", + "alloy-sol-types", + "anyhow", +] + [[package]] name = "cow-contract-iswaprpair" version = "0.1.0" @@ -1710,6 +1735,17 @@ dependencies = [ "anyhow", ] +[[package]] +name = "cow-contract-mockerc4626wrapper" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-primitives", + "alloy-provider", + "alloy-sol-types", + "anyhow", +] + [[package]] name = "cow-contract-nonstandarderc20balances" version = "0.1.0" diff --git a/contracts/generated/contracts-facade/Cargo.toml b/contracts/generated/contracts-facade/Cargo.toml index ca824f689c..902099c993 100644 --- a/contracts/generated/contracts-facade/Cargo.toml +++ b/contracts/generated/contracts-facade/Cargo.toml @@ -59,12 +59,14 @@ cow-contract-gpv2settlement = { path = "../contracts-generated/gpv2settlement" } cow-contract-honeyswaprouter = { path = "../contracts-generated/honeyswaprouter" } cow-contract-hookstrampoline = { path = "../contracts-generated/hookstrampoline" } cow-contract-icowwrapper = { path = "../contracts-generated/icowwrapper" } +cow-contract-ierc4626 = { path = "../contracts-generated/ierc4626" } cow-contract-iswaprpair = { path = "../contracts-generated/iswaprpair" } cow-contract-iuniswaplikepair = { path = "../contracts-generated/iuniswaplikepair" } cow-contract-iuniswaplikerouter = { path = "../contracts-generated/iuniswaplikerouter" } cow-contract-iuniswapv3factory = { path = "../contracts-generated/iuniswapv3factory" } cow-contract-izeroex = { path = "../contracts-generated/izeroex" } cow-contract-liquoricesettlement = { path = "../contracts-generated/liquoricesettlement" } +cow-contract-mockerc4626wrapper = { path = "../contracts-generated/mockerc4626wrapper" } cow-contract-nonstandarderc20balances = { path = "../contracts-generated/nonstandarderc20balances" } cow-contract-pancakerouter = { path = "../contracts-generated/pancakerouter" } cow-contract-permit2 = { path = "../contracts-generated/permit2" } diff --git a/contracts/generated/contracts-facade/src/lib.rs b/contracts/generated/contracts-facade/src/lib.rs index 91abfdf567..331b6a21aa 100644 --- a/contracts/generated/contracts-facade/src/lib.rs +++ b/contracts/generated/contracts-facade/src/lib.rs @@ -48,6 +48,7 @@ pub use { cow_contract_honeyswaprouter as HoneyswapRouter, cow_contract_hookstrampoline as HooksTrampoline, cow_contract_icowwrapper as ICowWrapper, + cow_contract_ierc4626 as IERC4626, cow_contract_iswaprpair as ISwaprPair, cow_contract_iuniswaplikepair as IUniswapLikePair, cow_contract_iuniswaplikerouter as IUniswapLikeRouter, @@ -82,6 +83,7 @@ pub mod test { cow_contract_counter as Counter, cow_contract_cowprotocoltoken as CowProtocolToken, cow_contract_gashog as GasHog, + cow_contract_mockerc4626wrapper as MockERC4626Wrapper, cow_contract_nonstandarderc20balances as NonStandardERC20Balances, cow_contract_remoteerc20balances as RemoteERC20Balances, }; diff --git a/contracts/generated/contracts-generated/ierc4626/Cargo.toml b/contracts/generated/contracts-generated/ierc4626/Cargo.toml new file mode 100644 index 0000000000..fe00f44d09 --- /dev/null +++ b/contracts/generated/contracts-generated/ierc4626/Cargo.toml @@ -0,0 +1,19 @@ +# Auto-generated by contracts-generate. Do not edit. +[package] +name = "cow-contract-ierc4626" +version = "0.1.0" +edition = "2024" +publish = false + +[lib] +doctest = false + +[dependencies] +alloy-contract = { workspace = true } +alloy-primitives = { workspace = true } +alloy-provider = { workspace = true } +alloy-sol-types = { workspace = true } +anyhow = { workspace = true } + +[lints] +workspace = true diff --git a/contracts/generated/contracts-generated/ierc4626/src/lib.rs b/contracts/generated/contracts-generated/ierc4626/src/lib.rs new file mode 100644 index 0000000000..11f48918c2 --- /dev/null +++ b/contracts/generated/contracts-generated/ierc4626/src/lib.rs @@ -0,0 +1,648 @@ +#![allow( + unused_imports, + unused_attributes, + clippy::all, + rustdoc::all, + non_snake_case +)] +//! Auto-generated contract bindings. Do not edit. +/** + +Generated by the following Solidity interface... +```solidity +interface IERC4626 { + function asset() external view returns (address assetTokenAddress); + function convertToAssets(uint256 shares) external view returns (uint256 assets); +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "function", + "name": "asset", + "inputs": [], + "outputs": [ + { + "name": "assetTokenAddress", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "convertToAssets", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod IERC4626 { + use {super::*, alloy_sol_types}; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `asset()` and selector `0x38d52e0f`. + ```solidity + function asset() external view returns (address assetTokenAddress); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct assetCall; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`asset()`](assetCall) + /// function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct assetReturn { + #[allow(missing_docs)] + pub assetTokenAddress: alloy_sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: assetCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for assetCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: assetReturn) -> Self { + (value.assetTokenAddress,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for assetReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + assetTokenAddress: tuple.0, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for assetCall { + type Parameters<'a> = (); + type Return = alloy_sol_types::private::Address; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [56u8, 213u8, 46u8, 15u8]; + const SIGNATURE: &'static str = "asset()"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: assetReturn = r.into(); + r.assetTokenAddress + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: assetReturn = r.into(); + r.assetTokenAddress + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `convertToAssets(uint256)` and selector `0x07a2d13a`. + ```solidity + function convertToAssets(uint256 shares) external view returns (uint256 assets); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct convertToAssetsCall { + #[allow(missing_docs)] + pub shares: alloy_sol_types::private::primitives::aliases::U256, + } + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`convertToAssets(uint256)`](convertToAssetsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct convertToAssetsReturn { + #[allow(missing_docs)] + pub assets: alloy_sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: convertToAssetsCall) -> Self { + (value.shares,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for convertToAssetsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { shares: tuple.0 } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: convertToAssetsReturn) -> Self { + (value.assets,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for convertToAssetsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { assets: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for convertToAssetsCall { + type Parameters<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Return = alloy_sol_types::private::primitives::aliases::U256; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [7u8, 162u8, 209u8, 58u8]; + const SIGNATURE: &'static str = "convertToAssets(uint256)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.shares, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + ret, + ), + ) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: convertToAssetsReturn = r.into(); + r.assets + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: convertToAssetsReturn = r.into(); + r.assets + }) + } + } + }; + ///Container for all the [`IERC4626`](self) function calls. + #[derive(Clone)] + pub enum IERC4626Calls { + #[allow(missing_docs)] + asset(assetCall), + #[allow(missing_docs)] + convertToAssets(convertToAssetsCall), + } + impl IERC4626Calls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the + /// variants. No guarantees are made about the order of the + /// selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = + &[[7u8, 162u8, 209u8, 58u8], [56u8, 213u8, 46u8, 15u8]]; + /// The signatures in the same order as `SELECTORS`. + pub const SIGNATURES: &'static [&'static str] = &[ + ::SIGNATURE, + ::SIGNATURE, + ]; + /// The names of the variants in the same order as `SELECTORS`. + pub const VARIANT_NAMES: &'static [&'static str] = &[ + ::core::stringify!(convertToAssets), + ::core::stringify!(asset), + ]; + + /// Returns the signature for the given selector, if known. + #[inline] + pub fn signature_by_selector( + selector: [u8; 4usize], + ) -> ::core::option::Option<&'static str> { + match Self::SELECTORS.binary_search(&selector) { + ::core::result::Result::Ok(idx) => { + ::core::option::Option::Some(Self::SIGNATURES[idx]) + } + ::core::result::Result::Err(_) => ::core::option::Option::None, + } + } + + /// Returns the enum variant name for the given selector, if known. + #[inline] + pub fn name_by_selector(selector: [u8; 4usize]) -> ::core::option::Option<&'static str> { + let sig = Self::signature_by_selector(selector)?; + sig.split_once('(').map(|(name, _)| name) + } + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for IERC4626Calls { + const COUNT: usize = 2usize; + const MIN_DATA_LENGTH: usize = 0usize; + const NAME: &'static str = "IERC4626Calls"; + + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::asset(_) => ::SELECTOR, + Self::convertToAssets(_) => { + ::SELECTOR + } + } + } + + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw(selector: [u8; 4], data: &[u8]) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn(&[u8]) -> alloy_sol_types::Result] = &[ + { + fn convertToAssets(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(IERC4626Calls::convertToAssets) + } + convertToAssets + }, + { + fn asset(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(IERC4626Calls::asset) + } + asset + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_SHIMS[idx](data) + } + + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn(&[u8]) -> alloy_sol_types::Result] = + &[ + { + fn convertToAssets(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(IERC4626Calls::convertToAssets) + } + convertToAssets + }, + { + fn asset(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(IERC4626Calls::asset) + } + asset + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::asset(inner) => { + ::abi_encoded_size(inner) + } + Self::convertToAssets(inner) => { + ::abi_encoded_size(inner) + } + } + } + + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::asset(inner) => { + ::abi_encode_raw(inner, out) + } + Self::convertToAssets(inner) => { + ::abi_encode_raw(inner, out) + } + } + } + } + use alloy_contract; + /**Creates a new wrapper around an on-chain [`IERC4626`](self) contract instance. + + See the [wrapper's documentation](`IERC4626Instance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + __provider: P, + ) -> IERC4626Instance { + IERC4626Instance::::new(address, __provider) + } + /**A [`IERC4626`](self) instance. + + Contains type-safe methods for interacting with an on-chain instance of the + [`IERC4626`](self) contract located at a given `address`, using a given + provider `P`. + + If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) + documentation on how to provide it), the `deploy` and `deploy_builder` methods can + be used to deploy a new instance of the contract. + + See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct IERC4626Instance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for IERC4626Instance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("IERC4626Instance") + .field(&self.address) + .finish() + } + } + /// Instantiation and getters/setters. + impl, N: alloy_contract::private::Network> + IERC4626Instance + { + /**Creates a new wrapper around an on-chain [`IERC4626`](self) contract instance. + + See the [wrapper's documentation](`IERC4626Instance`) for more details.*/ + #[inline] + pub const fn new(address: alloy_sol_types::private::Address, __provider: P) -> Self { + Self { + address, + provider: __provider, + _network: ::core::marker::PhantomData, + } + } + + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl IERC4626Instance<&P, N> { + /// Clones the provider and returns a new instance with the cloned + /// provider. + #[inline] + pub fn with_cloned_provider(self) -> IERC4626Instance { + IERC4626Instance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + impl, N: alloy_contract::private::Network> + IERC4626Instance + { + /// Creates a new call builder using this contract instance's provider + /// and address. + /// + /// Note that the call can be any function call, not just those defined + /// in this contract. Prefer using the other methods for + /// building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + + ///Creates a new call builder for the [`asset`] function. + pub fn asset(&self) -> alloy_contract::SolCallBuilder<&P, assetCall, N> { + self.call_builder(&assetCall) + } + + ///Creates a new call builder for the [`convertToAssets`] function. + pub fn convertToAssets( + &self, + shares: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, convertToAssetsCall, N> { + self.call_builder(&convertToAssetsCall { shares }) + } + } + /// Event filters. + impl, N: alloy_contract::private::Network> + IERC4626Instance + { + /// Creates a new event filter using this contract instance's provider + /// and address. + /// + /// Note that the type can be any event, not just those defined in this + /// contract. Prefer using the other methods for building + /// type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +pub type Instance = IERC4626::IERC4626Instance<::alloy_provider::DynProvider>; diff --git a/contracts/generated/contracts-generated/mockerc4626wrapper/Cargo.toml b/contracts/generated/contracts-generated/mockerc4626wrapper/Cargo.toml new file mode 100644 index 0000000000..77ca06c21e --- /dev/null +++ b/contracts/generated/contracts-generated/mockerc4626wrapper/Cargo.toml @@ -0,0 +1,19 @@ +# Auto-generated by contracts-generate. Do not edit. +[package] +name = "cow-contract-mockerc4626wrapper" +version = "0.1.0" +edition = "2024" +publish = false + +[lib] +doctest = false + +[dependencies] +alloy-contract = { workspace = true } +alloy-primitives = { workspace = true } +alloy-provider = { workspace = true } +alloy-sol-types = { workspace = true } +anyhow = { workspace = true } + +[lints] +workspace = true diff --git a/contracts/generated/contracts-generated/mockerc4626wrapper/src/lib.rs b/contracts/generated/contracts-generated/mockerc4626wrapper/src/lib.rs new file mode 100644 index 0000000000..33f38b216f --- /dev/null +++ b/contracts/generated/contracts-generated/mockerc4626wrapper/src/lib.rs @@ -0,0 +1,2768 @@ +#![allow( + unused_imports, + unused_attributes, + clippy::all, + rustdoc::all, + non_snake_case +)] +//! Auto-generated contract bindings. Do not edit. +/** + +Generated by the following Solidity interface... +```solidity +interface MockERC4626Wrapper { + constructor(address _asset, uint8 _decimals, uint256 _rateNumerator, uint256 _rateDenominator); + + function allowance(address, address) external view returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); + function asset() external view returns (address); + function balanceOf(address) external view returns (uint256); + function convertToAssets(uint256 shares) external view returns (uint256); + function decimals() external view returns (uint8); + function mint(address to, uint256 amount) external; + function rateDenominator() external view returns (uint256); + function rateNumerator() external view returns (uint256); + function transfer(address to, uint256 amount) external returns (bool); + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "constructor", + "inputs": [ + { + "name": "_asset", + "type": "address", + "internalType": "address" + }, + { + "name": "_decimals", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "_rateNumerator", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_rateDenominator", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + }, + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "approve", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "asset", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "convertToAssets", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "uint8" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mint", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "rateDenominator", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "rateNumerator", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "transfer", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [ + { + "name": "from", + "type": "address", + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod MockERC4626Wrapper { + use {super::*, alloy_sol_types}; + /// The creation / init bytecode of the contract. + /// + /// ```text + ///0x610100604052348015610010575f5ffd5b50604051610c17380380610c1783398181016040528101906100329190610154565b8373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508260ff1660a08160ff16815250508160c081815250508060e08181525050505050506101b8565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100ba82610091565b9050919050565b6100ca816100b0565b81146100d4575f5ffd5b50565b5f815190506100e5816100c1565b92915050565b5f60ff82169050919050565b610100816100eb565b811461010a575f5ffd5b50565b5f8151905061011b816100f7565b92915050565b5f819050919050565b61013381610121565b811461013d575f5ffd5b50565b5f8151905061014e8161012a565b92915050565b5f5f5f5f6080858703121561016c5761016b61008d565b5b5f610179878288016100d7565b945050602061018a8782880161010d565b935050604061019b87828801610140565b92505060606101ac87828801610140565b91505092959194509250565b60805160a05160c05160e051610a1e6101f95f395f8181610262015261055c01525f8181610283015261034801525f6104aa01525f6104ce0152610a1e5ff3fe608060405234801561000f575f5ffd5b50600436106100a7575f3560e01c806338d52e0f1161006f57806338d52e0f1461017757806340c10f191461019557806370a08231146101b1578063865192f7146101e1578063a9059cbb146101ff578063dd62ed3e1461022f576100a7565b806307a2d13a146100ab578063095ea7b3146100db5780630b36b8db1461010b57806323b872dd14610129578063313ce56714610159575b5f5ffd5b6100c560048036038101906100c09190610684565b61025f565b6040516100d291906106be565b60405180910390f35b6100f560048036038101906100f09190610731565b6102be565b6040516101029190610789565b60405180910390f35b610113610346565b60405161012091906106be565b60405180910390f35b610143600480360381019061013e91906107a2565b61036a565b6040516101509190610789565b60405180910390f35b6101616104a8565b60405161016e919061080d565b60405180910390f35b61017f6104cc565b60405161018c9190610835565b60405180910390f35b6101af60048036038101906101aa9190610731565b6104f0565b005b6101cb60048036038101906101c6919061084e565b610546565b6040516101d891906106be565b60405180910390f35b6101e961055a565b6040516101f691906106be565b60405180910390f35b61021960048036038101906102149190610731565b61057e565b6040516102269190610789565b60405180910390f35b61024960048036038101906102449190610879565b61062d565b60405161025691906106be565b60405180910390f35b5f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000836102ad91906108e4565b6102b79190610952565b9050919050565b5f8160015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546103f29190610982565b92505081905550815f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546104449190610982565b92505081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461049691906109b5565b92505081905550600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461053b91906109b5565b925050819055505050565b5f602052805f5260405f205f915090505481565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f815f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546105ca9190610982565b92505081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461061c91906109b5565b925050819055506001905092915050565b6001602052815f5260405f20602052805f5260405f205f91509150505481565b5f5ffd5b5f819050919050565b61066381610651565b811461066d575f5ffd5b50565b5f8135905061067e8161065a565b92915050565b5f602082840312156106995761069861064d565b5b5f6106a684828501610670565b91505092915050565b6106b881610651565b82525050565b5f6020820190506106d15f8301846106af565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610700826106d7565b9050919050565b610710816106f6565b811461071a575f5ffd5b50565b5f8135905061072b81610707565b92915050565b5f5f604083850312156107475761074661064d565b5b5f6107548582860161071d565b925050602061076585828601610670565b9150509250929050565b5f8115159050919050565b6107838161076f565b82525050565b5f60208201905061079c5f83018461077a565b92915050565b5f5f5f606084860312156107b9576107b861064d565b5b5f6107c68682870161071d565b93505060206107d78682870161071d565b92505060406107e886828701610670565b9150509250925092565b5f60ff82169050919050565b610807816107f2565b82525050565b5f6020820190506108205f8301846107fe565b92915050565b61082f816106f6565b82525050565b5f6020820190506108485f830184610826565b92915050565b5f602082840312156108635761086261064d565b5b5f6108708482850161071d565b91505092915050565b5f5f6040838503121561088f5761088e61064d565b5b5f61089c8582860161071d565b92505060206108ad8582860161071d565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6108ee82610651565b91506108f983610651565b925082820261090781610651565b9150828204841483151761091e5761091d6108b7565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61095c82610651565b915061096783610651565b92508261097757610976610925565b5b828204905092915050565b5f61098c82610651565b915061099783610651565b92508282039050818111156109af576109ae6108b7565b5b92915050565b5f6109bf82610651565b91506109ca83610651565b92508282019050808211156109e2576109e16108b7565b5b9291505056fea2646970667358221220b5ebafab2270a2c41eb9cd473eb8aca958511fe12b7302559d197e2a8704c94b64736f6c634300081e0033 + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"a\x01\0`@R4\x80\x15a\0\x10W__\xFD[P`@Qa\x0C\x178\x03\x80a\x0C\x17\x839\x81\x81\x01`@R\x81\x01\x90a\x002\x91\x90a\x01TV[\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`\x80\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81RPP\x82`\xFF\x16`\xA0\x81`\xFF\x16\x81RPP\x81`\xC0\x81\x81RPP\x80`\xE0\x81\x81RPPPPPPa\x01\xB8V[__\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\0\xBA\x82a\0\x91V[\x90P\x91\x90PV[a\0\xCA\x81a\0\xB0V[\x81\x14a\0\xD4W__\xFD[PV[_\x81Q\x90Pa\0\xE5\x81a\0\xC1V[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a\x01\0\x81a\0\xEBV[\x81\x14a\x01\nW__\xFD[PV[_\x81Q\x90Pa\x01\x1B\x81a\0\xF7V[\x92\x91PPV[_\x81\x90P\x91\x90PV[a\x013\x81a\x01!V[\x81\x14a\x01=W__\xFD[PV[_\x81Q\x90Pa\x01N\x81a\x01*V[\x92\x91PPV[____`\x80\x85\x87\x03\x12\x15a\x01lWa\x01ka\0\x8DV[[_a\x01y\x87\x82\x88\x01a\0\xD7V[\x94PP` a\x01\x8A\x87\x82\x88\x01a\x01\rV[\x93PP`@a\x01\x9B\x87\x82\x88\x01a\x01@V[\x92PP``a\x01\xAC\x87\x82\x88\x01a\x01@V[\x91PP\x92\x95\x91\x94P\x92PV[`\x80Q`\xA0Q`\xC0Q`\xE0Qa\n\x1Ea\x01\xF9_9_\x81\x81a\x02b\x01Ra\x05\\\x01R_\x81\x81a\x02\x83\x01Ra\x03H\x01R_a\x04\xAA\x01R_a\x04\xCE\x01Ra\n\x1E_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0\xA7W_5`\xE0\x1C\x80c8\xD5.\x0F\x11a\0oW\x80c8\xD5.\x0F\x14a\x01wW\x80c@\xC1\x0F\x19\x14a\x01\x95W\x80cp\xA0\x821\x14a\x01\xB1W\x80c\x86Q\x92\xF7\x14a\x01\xE1W\x80c\xA9\x05\x9C\xBB\x14a\x01\xFFW\x80c\xDDb\xED>\x14a\x02/Wa\0\xA7V[\x80c\x07\xA2\xD1:\x14a\0\xABW\x80c\t^\xA7\xB3\x14a\0\xDBW\x80c\x0B6\xB8\xDB\x14a\x01\x0BW\x80c#\xB8r\xDD\x14a\x01)W\x80c1<\xE5g\x14a\x01YW[__\xFD[a\0\xC5`\x04\x806\x03\x81\x01\x90a\0\xC0\x91\x90a\x06\x84V[a\x02_V[`@Qa\0\xD2\x91\x90a\x06\xBEV[`@Q\x80\x91\x03\x90\xF3[a\0\xF5`\x04\x806\x03\x81\x01\x90a\0\xF0\x91\x90a\x071V[a\x02\xBEV[`@Qa\x01\x02\x91\x90a\x07\x89V[`@Q\x80\x91\x03\x90\xF3[a\x01\x13a\x03FV[`@Qa\x01 \x91\x90a\x06\xBEV[`@Q\x80\x91\x03\x90\xF3[a\x01C`\x04\x806\x03\x81\x01\x90a\x01>\x91\x90a\x07\xA2V[a\x03jV[`@Qa\x01P\x91\x90a\x07\x89V[`@Q\x80\x91\x03\x90\xF3[a\x01aa\x04\xA8V[`@Qa\x01n\x91\x90a\x08\rV[`@Q\x80\x91\x03\x90\xF3[a\x01\x7Fa\x04\xCCV[`@Qa\x01\x8C\x91\x90a\x085V[`@Q\x80\x91\x03\x90\xF3[a\x01\xAF`\x04\x806\x03\x81\x01\x90a\x01\xAA\x91\x90a\x071V[a\x04\xF0V[\0[a\x01\xCB`\x04\x806\x03\x81\x01\x90a\x01\xC6\x91\x90a\x08NV[a\x05FV[`@Qa\x01\xD8\x91\x90a\x06\xBEV[`@Q\x80\x91\x03\x90\xF3[a\x01\xE9a\x05ZV[`@Qa\x01\xF6\x91\x90a\x06\xBEV[`@Q\x80\x91\x03\x90\xF3[a\x02\x19`\x04\x806\x03\x81\x01\x90a\x02\x14\x91\x90a\x071V[a\x05~V[`@Qa\x02&\x91\x90a\x07\x89V[`@Q\x80\x91\x03\x90\xF3[a\x02I`\x04\x806\x03\x81\x01\x90a\x02D\x91\x90a\x08yV[a\x06-V[`@Qa\x02V\x91\x90a\x06\xBEV[`@Q\x80\x91\x03\x90\xF3[_\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x83a\x02\xAD\x91\x90a\x08\xE4V[a\x02\xB7\x91\x90a\tRV[\x90P\x91\x90PV[_\x81`\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x81\x90UP`\x01\x90P\x92\x91PPV[\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81V[_\x81`\x01_\x86s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\x03\xF2\x91\x90a\t\x82V[\x92PP\x81\x90UP\x81__\x86s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\x04D\x91\x90a\t\x82V[\x92PP\x81\x90UP\x81__\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\x04\x96\x91\x90a\t\xB5V[\x92PP\x81\x90UP`\x01\x90P\x93\x92PPPV[\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81V[\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81V[\x80__\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\x05;\x91\x90a\t\xB5V[\x92PP\x81\x90UPPPV[_` R\x80_R`@_ _\x91P\x90PT\x81V[\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81V[_\x81__3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\x05\xCA\x91\x90a\t\x82V[\x92PP\x81\x90UP\x81__\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\x06\x1C\x91\x90a\t\xB5V[\x92PP\x81\x90UP`\x01\x90P\x92\x91PPV[`\x01` R\x81_R`@_ ` R\x80_R`@_ _\x91P\x91PPT\x81V[__\xFD[_\x81\x90P\x91\x90PV[a\x06c\x81a\x06QV[\x81\x14a\x06mW__\xFD[PV[_\x815\x90Pa\x06~\x81a\x06ZV[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x06\x99Wa\x06\x98a\x06MV[[_a\x06\xA6\x84\x82\x85\x01a\x06pV[\x91PP\x92\x91PPV[a\x06\xB8\x81a\x06QV[\x82RPPV[_` \x82\x01\x90Pa\x06\xD1_\x83\x01\x84a\x06\xAFV[\x92\x91PPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\x07\0\x82a\x06\xD7V[\x90P\x91\x90PV[a\x07\x10\x81a\x06\xF6V[\x81\x14a\x07\x1AW__\xFD[PV[_\x815\x90Pa\x07+\x81a\x07\x07V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x07GWa\x07Fa\x06MV[[_a\x07T\x85\x82\x86\x01a\x07\x1DV[\x92PP` a\x07e\x85\x82\x86\x01a\x06pV[\x91PP\x92P\x92\x90PV[_\x81\x15\x15\x90P\x91\x90PV[a\x07\x83\x81a\x07oV[\x82RPPV[_` \x82\x01\x90Pa\x07\x9C_\x83\x01\x84a\x07zV[\x92\x91PPV[___``\x84\x86\x03\x12\x15a\x07\xB9Wa\x07\xB8a\x06MV[[_a\x07\xC6\x86\x82\x87\x01a\x07\x1DV[\x93PP` a\x07\xD7\x86\x82\x87\x01a\x07\x1DV[\x92PP`@a\x07\xE8\x86\x82\x87\x01a\x06pV[\x91PP\x92P\x92P\x92V[_`\xFF\x82\x16\x90P\x91\x90PV[a\x08\x07\x81a\x07\xF2V[\x82RPPV[_` \x82\x01\x90Pa\x08 _\x83\x01\x84a\x07\xFEV[\x92\x91PPV[a\x08/\x81a\x06\xF6V[\x82RPPV[_` \x82\x01\x90Pa\x08H_\x83\x01\x84a\x08&V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x08cWa\x08ba\x06MV[[_a\x08p\x84\x82\x85\x01a\x07\x1DV[\x91PP\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x08\x8FWa\x08\x8Ea\x06MV[[_a\x08\x9C\x85\x82\x86\x01a\x07\x1DV[\x92PP` a\x08\xAD\x85\x82\x86\x01a\x07\x1DV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x08\xEE\x82a\x06QV[\x91Pa\x08\xF9\x83a\x06QV[\x92P\x82\x82\x02a\t\x07\x81a\x06QV[\x91P\x82\x82\x04\x84\x14\x83\x15\x17a\t\x1EWa\t\x1Da\x08\xB7V[[P\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x12`\x04R`$_\xFD[_a\t\\\x82a\x06QV[\x91Pa\tg\x83a\x06QV[\x92P\x82a\twWa\tva\t%V[[\x82\x82\x04\x90P\x92\x91PPV[_a\t\x8C\x82a\x06QV[\x91Pa\t\x97\x83a\x06QV[\x92P\x82\x82\x03\x90P\x81\x81\x11\x15a\t\xAFWa\t\xAEa\x08\xB7V[[\x92\x91PPV[_a\t\xBF\x82a\x06QV[\x91Pa\t\xCA\x83a\x06QV[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15a\t\xE2Wa\t\xE1a\x08\xB7V[[\x92\x91PPV\xFE\xA2dipfsX\"\x12 \xB5\xEB\xAF\xAB\"p\xA2\xC4\x1E\xB9\xCDG>\xB8\xAC\xA9XQ\x1F\xE1+s\x02U\x9D\x19~*\x87\x04\xC9KdsolcC\0\x08\x1E\x003", + ); + /**Constructor`. + ```solidity + constructor(address _asset, uint8 _decimals, uint256 _rateNumerator, uint256 _rateDenominator); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct constructorCall { + #[allow(missing_docs)] + pub _asset: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub _decimals: u8, + #[allow(missing_docs)] + pub _rateNumerator: alloy_sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub _rateDenominator: alloy_sol_types::private::primitives::aliases::U256, + } + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<8>, + alloy_sol_types::sol_data::Uint<256>, + alloy_sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy_sol_types::private::Address, + u8, + alloy_sol_types::private::primitives::aliases::U256, + alloy_sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: constructorCall) -> Self { + ( + value._asset, + value._decimals, + value._rateNumerator, + value._rateDenominator, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for constructorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _asset: tuple.0, + _decimals: tuple.1, + _rateNumerator: tuple.2, + _rateDenominator: tuple.3, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolConstructor for constructorCall { + type Parameters<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<8>, + alloy_sol_types::sol_data::Uint<256>, + alloy_sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self._asset, + ), + as alloy_sol_types::SolType>::tokenize( + &self._decimals, + ), + as alloy_sol_types::SolType>::tokenize( + &self._rateNumerator, + ), + as alloy_sol_types::SolType>::tokenize( + &self._rateDenominator, + ), + ) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `allowance(address,address)` and selector `0xdd62ed3e`. + ```solidity + function allowance(address, address) external view returns (uint256); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct allowanceCall { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub _1: alloy_sol_types::private::Address, + } + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`allowance(address,address)`](allowanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct allowanceReturn { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy_sol_types::private::Address, + alloy_sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: allowanceCall) -> Self { + (value._0, value._1) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for allowanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _0: tuple.0, + _1: tuple.1, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: allowanceReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for allowanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for allowanceCall { + type Parameters<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Address, + ); + type Return = alloy_sol_types::private::primitives::aliases::U256; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [221u8, 98u8, 237u8, 62u8]; + const SIGNATURE: &'static str = "allowance(address,address)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self._0, + ), + ::tokenize( + &self._1, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + ret, + ), + ) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: allowanceReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: allowanceReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `approve(address,uint256)` and selector `0x095ea7b3`. + ```solidity + function approve(address spender, uint256 amount) external returns (bool); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct approveCall { + #[allow(missing_docs)] + pub spender: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy_sol_types::private::primitives::aliases::U256, + } + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`approve(address,uint256)`](approveCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct approveReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy_sol_types::private::Address, + alloy_sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: approveCall) -> Self { + (value.spender, value.amount) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for approveCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + spender: tuple.0, + amount: tuple.1, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: approveReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for approveReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for approveCall { + type Parameters<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + type Return = bool; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Bool,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [9u8, 94u8, 167u8, 179u8]; + const SIGNATURE: &'static str = "approve(address,uint256)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.spender, + ), + as alloy_sol_types::SolType>::tokenize( + &self.amount, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: approveReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: approveReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `asset()` and selector `0x38d52e0f`. + ```solidity + function asset() external view returns (address); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct assetCall; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`asset()`](assetCall) + /// function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct assetReturn { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: assetCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for assetCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: assetReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for assetReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for assetCall { + type Parameters<'a> = (); + type Return = alloy_sol_types::private::Address; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [56u8, 213u8, 46u8, 15u8]; + const SIGNATURE: &'static str = "asset()"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: assetReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: assetReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `balanceOf(address)` and selector `0x70a08231`. + ```solidity + function balanceOf(address) external view returns (uint256); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct balanceOfCall(pub alloy_sol_types::private::Address); + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`balanceOf(address)`](balanceOfCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct balanceOfReturn { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: balanceOfCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for balanceOfCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: balanceOfReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for balanceOfReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for balanceOfCall { + type Parameters<'a> = (alloy_sol_types::sol_data::Address,); + type Return = alloy_sol_types::private::primitives::aliases::U256; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [112u8, 160u8, 130u8, 49u8]; + const SIGNATURE: &'static str = "balanceOf(address)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.0, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + ret, + ), + ) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: balanceOfReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: balanceOfReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `convertToAssets(uint256)` and selector `0x07a2d13a`. + ```solidity + function convertToAssets(uint256 shares) external view returns (uint256); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct convertToAssetsCall { + #[allow(missing_docs)] + pub shares: alloy_sol_types::private::primitives::aliases::U256, + } + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`convertToAssets(uint256)`](convertToAssetsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct convertToAssetsReturn { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: convertToAssetsCall) -> Self { + (value.shares,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for convertToAssetsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { shares: tuple.0 } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: convertToAssetsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for convertToAssetsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for convertToAssetsCall { + type Parameters<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Return = alloy_sol_types::private::primitives::aliases::U256; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [7u8, 162u8, 209u8, 58u8]; + const SIGNATURE: &'static str = "convertToAssets(uint256)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self.shares, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + ret, + ), + ) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: convertToAssetsReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: convertToAssetsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `decimals()` and selector `0x313ce567`. + ```solidity + function decimals() external view returns (uint8); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct decimalsCall; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`decimals()`](decimalsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct decimalsReturn { + #[allow(missing_docs)] + pub _0: u8, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: decimalsCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for decimalsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<8>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u8,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: decimalsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for decimalsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for decimalsCall { + type Parameters<'a> = (); + type Return = u8; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<8>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [49u8, 60u8, 229u8, 103u8]; + const SIGNATURE: &'static str = "decimals()"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( as alloy_sol_types::SolType>::tokenize(ret),) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: decimalsReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: decimalsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `mint(address,uint256)` and selector `0x40c10f19`. + ```solidity + function mint(address to, uint256 amount) external; + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mintCall { + #[allow(missing_docs)] + pub to: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy_sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the + /// [`mint(address,uint256)`](mintCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mintReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy_sol_types::private::Address, + alloy_sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mintCall) -> Self { + (value.to, value.amount) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mintCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + to: tuple.0, + amount: tuple.1, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mintReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mintReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl mintReturn { + fn _tokenize(&self) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for mintCall { + type Parameters<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + type Return = mintReturn; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [64u8, 193u8, 15u8, 25u8]; + const SIGNATURE: &'static str = "mint(address,uint256)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.to, + ), + as alloy_sol_types::SolType>::tokenize( + &self.amount, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + mintReturn::_tokenize(ret) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(Into::into) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `rateDenominator()` and selector `0x865192f7`. + ```solidity + function rateDenominator() external view returns (uint256); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct rateDenominatorCall; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`rateDenominator()`](rateDenominatorCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct rateDenominatorReturn { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: rateDenominatorCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for rateDenominatorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: rateDenominatorReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for rateDenominatorReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for rateDenominatorCall { + type Parameters<'a> = (); + type Return = alloy_sol_types::private::primitives::aliases::U256; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [134u8, 81u8, 146u8, 247u8]; + const SIGNATURE: &'static str = "rateDenominator()"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + ret, + ), + ) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: rateDenominatorReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: rateDenominatorReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `rateNumerator()` and selector `0x0b36b8db`. + ```solidity + function rateNumerator() external view returns (uint256); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct rateNumeratorCall; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`rateNumerator()`](rateNumeratorCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct rateNumeratorReturn { + #[allow(missing_docs)] + pub _0: alloy_sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: rateNumeratorCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for rateNumeratorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy_sol_types::private::primitives::aliases::U256,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: rateNumeratorReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for rateNumeratorReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for rateNumeratorCall { + type Parameters<'a> = (); + type Return = alloy_sol_types::private::primitives::aliases::U256; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [11u8, 54u8, 184u8, 219u8]; + const SIGNATURE: &'static str = "rateNumerator()"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + ret, + ), + ) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: rateNumeratorReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: rateNumeratorReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `transfer(address,uint256)` and selector `0xa9059cbb`. + ```solidity + function transfer(address to, uint256 amount) external returns (bool); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferCall { + #[allow(missing_docs)] + pub to: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy_sol_types::private::primitives::aliases::U256, + } + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`transfer(address,uint256)`](transferCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy_sol_types::private::Address, + alloy_sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferCall) -> Self { + (value.to, value.amount) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + to: tuple.0, + amount: tuple.1, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for transferCall { + type Parameters<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + type Return = bool; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Bool,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [169u8, 5u8, 156u8, 187u8]; + const SIGNATURE: &'static str = "transfer(address,uint256)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.to, + ), + as alloy_sol_types::SolType>::tokenize( + &self.amount, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: transferReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: transferReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `transferFrom(address,address,uint256)` and selector `0x23b872dd`. + ```solidity + function transferFrom(address from, address to, uint256 amount) external returns (bool); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferFromCall { + #[allow(missing_docs)] + pub from: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub to: alloy_sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy_sol_types::private::primitives::aliases::U256, + } + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the + /// [`transferFrom(address,address,uint256)`](transferFromCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferFromReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy_sol_types::private::Address, + alloy_sol_types::private::Address, + alloy_sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferFromCall) -> Self { + (value.from, value.to, value.amount) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferFromCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + from: tuple.0, + to: tuple.1, + amount: tuple.2, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy_sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferFromReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferFromReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for transferFromCall { + type Parameters<'a> = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Uint<256>, + ); + type Return = bool; + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type ReturnTuple<'a> = (alloy_sol_types::sol_data::Bool,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + + const SELECTOR: [u8; 4] = [35u8, 184u8, 114u8, 221u8]; + const SIGNATURE: &'static str = "transferFrom(address,address,uint256)"; + + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.from, + ), + ::tokenize( + &self.to, + ), + as alloy_sol_types::SolType>::tokenize( + &self.amount, + ), + ) + } + + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: transferFromReturn = r.into(); + r._0 + }, + ) + } + + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: transferFromReturn = r.into(); + r._0 + }) + } + } + }; + ///Container for all the [`MockERC4626Wrapper`](self) function calls. + #[derive(Clone)] + pub enum MockERC4626WrapperCalls { + #[allow(missing_docs)] + allowance(allowanceCall), + #[allow(missing_docs)] + approve(approveCall), + #[allow(missing_docs)] + asset(assetCall), + #[allow(missing_docs)] + balanceOf(balanceOfCall), + #[allow(missing_docs)] + convertToAssets(convertToAssetsCall), + #[allow(missing_docs)] + decimals(decimalsCall), + #[allow(missing_docs)] + mint(mintCall), + #[allow(missing_docs)] + rateDenominator(rateDenominatorCall), + #[allow(missing_docs)] + rateNumerator(rateNumeratorCall), + #[allow(missing_docs)] + transfer(transferCall), + #[allow(missing_docs)] + transferFrom(transferFromCall), + } + impl MockERC4626WrapperCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the + /// variants. No guarantees are made about the order of the + /// selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [7u8, 162u8, 209u8, 58u8], + [9u8, 94u8, 167u8, 179u8], + [11u8, 54u8, 184u8, 219u8], + [35u8, 184u8, 114u8, 221u8], + [49u8, 60u8, 229u8, 103u8], + [56u8, 213u8, 46u8, 15u8], + [64u8, 193u8, 15u8, 25u8], + [112u8, 160u8, 130u8, 49u8], + [134u8, 81u8, 146u8, 247u8], + [169u8, 5u8, 156u8, 187u8], + [221u8, 98u8, 237u8, 62u8], + ]; + /// The signatures in the same order as `SELECTORS`. + pub const SIGNATURES: &'static [&'static str] = &[ + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ]; + /// The names of the variants in the same order as `SELECTORS`. + pub const VARIANT_NAMES: &'static [&'static str] = &[ + ::core::stringify!(convertToAssets), + ::core::stringify!(approve), + ::core::stringify!(rateNumerator), + ::core::stringify!(transferFrom), + ::core::stringify!(decimals), + ::core::stringify!(asset), + ::core::stringify!(mint), + ::core::stringify!(balanceOf), + ::core::stringify!(rateDenominator), + ::core::stringify!(transfer), + ::core::stringify!(allowance), + ]; + + /// Returns the signature for the given selector, if known. + #[inline] + pub fn signature_by_selector( + selector: [u8; 4usize], + ) -> ::core::option::Option<&'static str> { + match Self::SELECTORS.binary_search(&selector) { + ::core::result::Result::Ok(idx) => { + ::core::option::Option::Some(Self::SIGNATURES[idx]) + } + ::core::result::Result::Err(_) => ::core::option::Option::None, + } + } + + /// Returns the enum variant name for the given selector, if known. + #[inline] + pub fn name_by_selector(selector: [u8; 4usize]) -> ::core::option::Option<&'static str> { + let sig = Self::signature_by_selector(selector)?; + sig.split_once('(').map(|(name, _)| name) + } + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for MockERC4626WrapperCalls { + const COUNT: usize = 11usize; + const MIN_DATA_LENGTH: usize = 0usize; + const NAME: &'static str = "MockERC4626WrapperCalls"; + + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::allowance(_) => ::SELECTOR, + Self::approve(_) => ::SELECTOR, + Self::asset(_) => ::SELECTOR, + Self::balanceOf(_) => ::SELECTOR, + Self::convertToAssets(_) => { + ::SELECTOR + } + Self::decimals(_) => ::SELECTOR, + Self::mint(_) => ::SELECTOR, + Self::rateDenominator(_) => { + ::SELECTOR + } + Self::rateNumerator(_) => ::SELECTOR, + Self::transfer(_) => ::SELECTOR, + Self::transferFrom(_) => ::SELECTOR, + } + } + + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw(selector: [u8; 4], data: &[u8]) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) + -> alloy_sol_types::Result] = &[ + { + fn convertToAssets( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::convertToAssets) + } + convertToAssets + }, + { + fn approve(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::approve) + } + approve + }, + { + fn rateNumerator( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::rateNumerator) + } + rateNumerator + }, + { + fn transferFrom( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::transferFrom) + } + transferFrom + }, + { + fn decimals(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::decimals) + } + decimals + }, + { + fn asset(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::asset) + } + asset + }, + { + fn mint(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::mint) + } + mint + }, + { + fn balanceOf(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::balanceOf) + } + balanceOf + }, + { + fn rateDenominator( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::rateDenominator) + } + rateDenominator + }, + { + fn transfer(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::transfer) + } + transfer + }, + { + fn allowance(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(MockERC4626WrapperCalls::allowance) + } + allowance + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_SHIMS[idx](data) + } + + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result< + MockERC4626WrapperCalls, + >] = &[ + { + fn convertToAssets( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(MockERC4626WrapperCalls::convertToAssets) + } + convertToAssets + }, + { + fn approve(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::approve) + } + approve + }, + { + fn rateNumerator( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(MockERC4626WrapperCalls::rateNumerator) + } + rateNumerator + }, + { + fn transferFrom( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(MockERC4626WrapperCalls::transferFrom) + } + transferFrom + }, + { + fn decimals(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::decimals) + } + decimals + }, + { + fn asset(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::asset) + } + asset + }, + { + fn mint(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::mint) + } + mint + }, + { + fn balanceOf(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::balanceOf) + } + balanceOf + }, + { + fn rateDenominator( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(MockERC4626WrapperCalls::rateDenominator) + } + rateDenominator + }, + { + fn transfer(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::transfer) + } + transfer + }, + { + fn allowance(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate(data) + .map(MockERC4626WrapperCalls::allowance) + } + allowance + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::allowance(inner) => { + ::abi_encoded_size(inner) + } + Self::approve(inner) => { + ::abi_encoded_size(inner) + } + Self::asset(inner) => { + ::abi_encoded_size(inner) + } + Self::balanceOf(inner) => { + ::abi_encoded_size(inner) + } + Self::convertToAssets(inner) => { + ::abi_encoded_size(inner) + } + Self::decimals(inner) => { + ::abi_encoded_size(inner) + } + Self::mint(inner) => { + ::abi_encoded_size(inner) + } + Self::rateDenominator(inner) => { + ::abi_encoded_size(inner) + } + Self::rateNumerator(inner) => { + ::abi_encoded_size(inner) + } + Self::transfer(inner) => { + ::abi_encoded_size(inner) + } + Self::transferFrom(inner) => { + ::abi_encoded_size(inner) + } + } + } + + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::allowance(inner) => { + ::abi_encode_raw(inner, out) + } + Self::approve(inner) => { + ::abi_encode_raw(inner, out) + } + Self::asset(inner) => { + ::abi_encode_raw(inner, out) + } + Self::balanceOf(inner) => { + ::abi_encode_raw(inner, out) + } + Self::convertToAssets(inner) => { + ::abi_encode_raw(inner, out) + } + Self::decimals(inner) => { + ::abi_encode_raw(inner, out) + } + Self::mint(inner) => { + ::abi_encode_raw(inner, out) + } + Self::rateDenominator(inner) => { + ::abi_encode_raw(inner, out) + } + Self::rateNumerator(inner) => { + ::abi_encode_raw(inner, out) + } + Self::transfer(inner) => { + ::abi_encode_raw(inner, out) + } + Self::transferFrom(inner) => { + ::abi_encode_raw(inner, out) + } + } + } + } + use alloy_contract; + /**Creates a new wrapper around an on-chain [`MockERC4626Wrapper`](self) contract instance. + + See the [wrapper's documentation](`MockERC4626WrapperInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + __provider: P, + ) -> MockERC4626WrapperInstance { + MockERC4626WrapperInstance::::new(address, __provider) + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + + Returns a new instance of the contract, if the deployment was successful. + + For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub fn deploy, N: alloy_contract::private::Network>( + __provider: P, + _asset: alloy_sol_types::private::Address, + _decimals: u8, + _rateNumerator: alloy_sol_types::private::primitives::aliases::U256, + _rateDenominator: alloy_sol_types::private::primitives::aliases::U256, + ) -> impl ::core::future::Future>> + { + MockERC4626WrapperInstance::::deploy( + __provider, + _asset, + _decimals, + _rateNumerator, + _rateDenominator, + ) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` + and constructor arguments, if any. + + This is a simple wrapper around creating a `RawCallBuilder` with the data set to + the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + __provider: P, + _asset: alloy_sol_types::private::Address, + _decimals: u8, + _rateNumerator: alloy_sol_types::private::primitives::aliases::U256, + _rateDenominator: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::RawCallBuilder { + MockERC4626WrapperInstance::::deploy_builder( + __provider, + _asset, + _decimals, + _rateNumerator, + _rateDenominator, + ) + } + /**A [`MockERC4626Wrapper`](self) instance. + + Contains type-safe methods for interacting with an on-chain instance of the + [`MockERC4626Wrapper`](self) contract located at a given `address`, using a given + provider `P`. + + If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) + documentation on how to provide it), the `deploy` and `deploy_builder` methods can + be used to deploy a new instance of the contract. + + See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct MockERC4626WrapperInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for MockERC4626WrapperInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("MockERC4626WrapperInstance") + .field(&self.address) + .finish() + } + } + /// Instantiation and getters/setters. + impl, N: alloy_contract::private::Network> + MockERC4626WrapperInstance + { + /**Creates a new wrapper around an on-chain [`MockERC4626Wrapper`](self) contract instance. + + See the [wrapper's documentation](`MockERC4626WrapperInstance`) for more details.*/ + #[inline] + pub const fn new(address: alloy_sol_types::private::Address, __provider: P) -> Self { + Self { + address, + provider: __provider, + _network: ::core::marker::PhantomData, + } + } + + /**Deploys this contract using the given `provider` and constructor arguments, if any. + + Returns a new instance of the contract, if the deployment was successful. + + For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub async fn deploy( + __provider: P, + _asset: alloy_sol_types::private::Address, + _decimals: u8, + _rateNumerator: alloy_sol_types::private::primitives::aliases::U256, + _rateDenominator: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::Result> { + let call_builder = Self::deploy_builder( + __provider, + _asset, + _decimals, + _rateNumerator, + _rateDenominator, + ); + let contract_address = call_builder.deploy().await?; + Ok(Self::new(contract_address, call_builder.provider)) + } + + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` + and constructor arguments, if any. + + This is a simple wrapper around creating a `RawCallBuilder` with the data set to + the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder( + __provider: P, + _asset: alloy_sol_types::private::Address, + _decimals: u8, + _rateNumerator: alloy_sol_types::private::primitives::aliases::U256, + _rateDenominator: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::RawCallBuilder { + alloy_contract::RawCallBuilder::new_raw_deploy( + __provider, + [ + &BYTECODE[..], + &alloy_sol_types::SolConstructor::abi_encode(&constructorCall { + _asset, + _decimals, + _rateNumerator, + _rateDenominator, + })[..], + ] + .concat() + .into(), + ) + } + + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl MockERC4626WrapperInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned + /// provider. + #[inline] + pub fn with_cloned_provider(self) -> MockERC4626WrapperInstance { + MockERC4626WrapperInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + impl, N: alloy_contract::private::Network> + MockERC4626WrapperInstance + { + /// Creates a new call builder using this contract instance's provider + /// and address. + /// + /// Note that the call can be any function call, not just those defined + /// in this contract. Prefer using the other methods for + /// building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + + ///Creates a new call builder for the [`allowance`] function. + pub fn allowance( + &self, + _0: alloy_sol_types::private::Address, + _1: alloy_sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, allowanceCall, N> { + self.call_builder(&allowanceCall { _0, _1 }) + } + + ///Creates a new call builder for the [`approve`] function. + pub fn approve( + &self, + spender: alloy_sol_types::private::Address, + amount: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, approveCall, N> { + self.call_builder(&approveCall { spender, amount }) + } + + ///Creates a new call builder for the [`asset`] function. + pub fn asset(&self) -> alloy_contract::SolCallBuilder<&P, assetCall, N> { + self.call_builder(&assetCall) + } + + ///Creates a new call builder for the [`balanceOf`] function. + pub fn balanceOf( + &self, + _0: alloy_sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, balanceOfCall, N> { + self.call_builder(&balanceOfCall(_0)) + } + + ///Creates a new call builder for the [`convertToAssets`] function. + pub fn convertToAssets( + &self, + shares: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, convertToAssetsCall, N> { + self.call_builder(&convertToAssetsCall { shares }) + } + + ///Creates a new call builder for the [`decimals`] function. + pub fn decimals(&self) -> alloy_contract::SolCallBuilder<&P, decimalsCall, N> { + self.call_builder(&decimalsCall) + } + + ///Creates a new call builder for the [`mint`] function. + pub fn mint( + &self, + to: alloy_sol_types::private::Address, + amount: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, mintCall, N> { + self.call_builder(&mintCall { to, amount }) + } + + ///Creates a new call builder for the [`rateDenominator`] function. + pub fn rateDenominator( + &self, + ) -> alloy_contract::SolCallBuilder<&P, rateDenominatorCall, N> { + self.call_builder(&rateDenominatorCall) + } + + ///Creates a new call builder for the [`rateNumerator`] function. + pub fn rateNumerator(&self) -> alloy_contract::SolCallBuilder<&P, rateNumeratorCall, N> { + self.call_builder(&rateNumeratorCall) + } + + ///Creates a new call builder for the [`transfer`] function. + pub fn transfer( + &self, + to: alloy_sol_types::private::Address, + amount: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, transferCall, N> { + self.call_builder(&transferCall { to, amount }) + } + + ///Creates a new call builder for the [`transferFrom`] function. + pub fn transferFrom( + &self, + from: alloy_sol_types::private::Address, + to: alloy_sol_types::private::Address, + amount: alloy_sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, transferFromCall, N> { + self.call_builder(&transferFromCall { from, to, amount }) + } + } + /// Event filters. + impl, N: alloy_contract::private::Network> + MockERC4626WrapperInstance + { + /// Creates a new event filter using this contract instance's provider + /// and address. + /// + /// Note that the type can be any event, not just those defined in this + /// contract. Prefer using the other methods for building + /// type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +pub type Instance = MockERC4626Wrapper::MockERC4626WrapperInstance<::alloy_provider::DynProvider>; diff --git a/contracts/solidity/interfaces/IERC4626.sol b/contracts/solidity/interfaces/IERC4626.sol new file mode 100644 index 0000000000..ca6522cca7 --- /dev/null +++ b/contracts/solidity/interfaces/IERC4626.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +/// @title ERC-4626 vaults interface +interface IERC4626 { + function asset() external view returns (address assetTokenAddress); + function convertToAssets(uint256 shares) external view returns (uint256 assets); +} diff --git a/contracts/solidity/tests/MockERC4626Wrapper.sol b/contracts/solidity/tests/MockERC4626Wrapper.sol new file mode 100644 index 0000000000..8a33eef4e8 --- /dev/null +++ b/contracts/solidity/tests/MockERC4626Wrapper.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +/// @title MockERC4626Wrapper +/// @notice Minimal EIP-4626 wrapper for testing recursive vault pricing. +/// @dev Wraps another ERC-4626 vault (or any ERC-20) with a configurable +/// conversion rate. Not a real vault -- just enough to satisfy `asset()`, +/// `decimals()`, `convertToAssets()`, `balanceOf()`, `approve()`, and +/// `transfer()` so the e2e pricing pipeline works. +contract MockERC4626Wrapper { + address public immutable asset; + uint8 public immutable decimals; + uint256 public immutable rateNumerator; + uint256 public immutable rateDenominator; + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + + constructor(address _asset, uint8 _decimals, uint256 _rateNumerator, uint256 _rateDenominator) { + asset = _asset; + decimals = _decimals; + rateNumerator = _rateNumerator; + rateDenominator = _rateDenominator; + } + + /// @notice Returns the equivalent amount of underlying assets for the + /// given number of vault shares, scaled by the configured rate. + function convertToAssets(uint256 shares) external view returns (uint256) { + return shares * rateNumerator / rateDenominator; + } + + function transfer(address to, uint256 amount) external returns (bool) { + balanceOf[msg.sender] -= amount; + balanceOf[to] += amount; + return true; + } + + function approve(address spender, uint256 amount) external returns (bool) { + allowance[msg.sender][spender] = amount; + return true; + } + + function transferFrom(address from, address to, uint256 amount) external returns (bool) { + allowance[from][msg.sender] -= amount; + balanceOf[from] -= amount; + balanceOf[to] += amount; + return true; + } + + /// @notice Mints tokens to an address. Only for testing. + function mint(address to, uint256 amount) external { + balanceOf[to] += amount; + } +} diff --git a/contracts/src/main.rs b/contracts/src/main.rs index 1f4ed17afa..61962946fe 100644 --- a/contracts/src/main.rs +++ b/contracts/src/main.rs @@ -105,6 +105,7 @@ fn build_module() -> Module { // Misc .add_contract(Contract::new("ERC20")) .add_contract(Contract::new("ERC20Mintable")) + .add_contract(Contract::new("IERC4626")) // GnosisSafe .add_contract(Contract::new("GnosisSafe")) .add_contract(Contract::new("GnosisSafeCompatibilityFallbackHandler")) @@ -505,6 +506,7 @@ fn build_module() -> Module { Submodule::new("test") .add_contract(Contract::new("GasHog")) .add_contract(Contract::new("Counter")) + .add_contract(Contract::new("MockERC4626Wrapper")) .add_contract(Contract::new("CowProtocolToken").with_networks(networks![ MAINNET => "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB", GNOSIS => "0x177127622c4A00F3d409B75571e12cB3c8973d3c", diff --git a/contracts/src/vendor.rs b/contracts/src/vendor.rs index 576ae5fe2a..4c9584243e 100644 --- a/contracts/src/vendor.rs +++ b/contracts/src/vendor.rs @@ -162,6 +162,10 @@ pub fn run(artifacts_dir: &Path) -> Result<()> { "ERC1271SignatureValidator", "Manually vendored ABI for ERC-1271 signature validation", ) + .manual( + "IERC4626", + "Manually vendored ABI for ERC-4626 tokenized vault interface", + ) .npm( "IUniswapLikePair", "@uniswap/v2-periphery@1.1.0-beta.0/build/IUniswapV2Pair.json", diff --git a/crates/autopilot/src/run.rs b/crates/autopilot/src/run.rs index 9d0a1cdf24..1f0482cf66 100644 --- a/crates/autopilot/src/run.rs +++ b/crates/autopilot/src/run.rs @@ -346,6 +346,7 @@ pub async fn run(config: Configuration, shutdown_controller: ShutdownController) config.native_price_estimation.shared.results_required, &weth, shared_cache.clone(), + config.native_price_estimation.eip4626, ) .instrument(info_span!("api_native_price_estimator")) .await, @@ -358,6 +359,7 @@ pub async fn run(config: Configuration, shutdown_controller: ShutdownController) config.native_price_estimation.shared.results_required, &weth, shared_cache.clone(), + config.native_price_estimation.eip4626, ) .instrument(info_span!("competition_native_price_updater")) .await; diff --git a/crates/autopilot/src/solvable_orders.rs b/crates/autopilot/src/solvable_orders.rs index ee1c0cd603..dd3007b7e1 100644 --- a/crates/autopilot/src/solvable_orders.rs +++ b/crates/autopilot/src/solvable_orders.rs @@ -28,14 +28,11 @@ use { signature::Signature, time::now_in_epoch_seconds, }, - price_estimation::{ - native::{NativePriceEstimating, to_normalized_price}, - native_price_cache::NativePriceUpdater, - }, + price_estimation::{native::to_normalized_price, native_price_cache::NativePriceUpdater}, prometheus::{Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec}, shared::remaining_amounts, std::{ - collections::{BTreeMap, HashMap, HashSet, btree_map::Entry}, + collections::{BTreeMap, HashMap, HashSet}, future::Future, sync::Arc, time::{Duration, Instant}, @@ -292,21 +289,11 @@ impl SolvableOrdersCache { ) .await; tracing::trace!("fetched native prices for solvable orders"); - // Add WETH price if it's not already there to support ETH wrap when required. - if let Entry::Vacant(entry) = prices.entry(self.weth) { - let weth_price = self - .timed_future( - "weth_price_fetch", - self.native_price_estimator - .estimate_native_price(self.weth, Default::default()), - ) - .await - .expect("weth price fetching can never fail"); - let weth_price = to_normalized_price(weth_price) - .expect("weth price can never be outside of U256 range"); - - entry.insert(weth_price); - } + // WETH's native price is 1 by definition — insert it directly to + // support ETH wrap when required. + prices + .entry(self.weth) + .or_insert_with(|| to_normalized_price(1.0).unwrap()); Metrics::track_filtered_orders(MissingNativePrice, &removed); filtered_order_events.extend(removed.into_iter().map(|uid| (uid, MissingNativePrice))); diff --git a/crates/configs/src/autopilot/native_price.rs b/crates/configs/src/autopilot/native_price.rs index 74ac52635f..7ebf0f77bc 100644 --- a/crates/configs/src/autopilot/native_price.rs +++ b/crates/configs/src/autopilot/native_price.rs @@ -46,6 +46,12 @@ pub struct NativePriceConfig { )] pub prefetch_time: Duration, + /// Enable EIP-4626 vault token pricing. When enabled, the native price + /// estimator will attempt to price vault tokens by querying their + /// underlying asset and conversion rate on-chain. + #[serde(default)] + pub eip4626: bool, + /// Shared native price settings (cache, approximation tokens, etc.). #[serde(flatten)] pub shared: crate::native_price::NativePriceConfig, @@ -62,6 +68,7 @@ impl NativePriceConfig { api_estimators: Default::default(), cache_refresh_interval: default_native_price_cache_refresh(), prefetch_time: Duration::from_millis(500), + eip4626: false, shared: crate::native_price::NativePriceConfig { cache: crate::native_price::CacheConfig { max_age: Duration::from_secs(2), diff --git a/crates/e2e/tests/e2e/eip4626.rs b/crates/e2e/tests/e2e/eip4626.rs new file mode 100644 index 0000000000..fd7fef837e --- /dev/null +++ b/crates/e2e/tests/e2e/eip4626.rs @@ -0,0 +1,236 @@ +use { + ::alloy::{ + primitives::{Address, U256, address}, + providers::ext::{AnvilApi, ImpersonateConfig}, + }, + configs::{ + autopilot::{Configuration, native_price::NativePriceConfig}, + native_price_estimators::{NativePriceEstimator, NativePriceEstimators}, + test_util::TestDefault, + }, + contracts::ERC20, + e2e::setup::*, + ethrpc::alloy::CallBuilderExt, + model::quote::{OrderQuoteRequest, OrderQuoteSide, SellAmount}, + number::units::EthUnit, + shared::web3::Web3, +}; + +/// The block number from which we will fetch state for the forked test. +const FORK_BLOCK_MAINNET: u64 = 23112197; + +/// sDAI (Savings DAI) – an EIP-4626 vault wrapping DAI. +const SDAI: Address = address!("83F20F44975D03b1b09e64809B757c47f942BEeA"); + +/// sDAI whale at [`FORK_BLOCK_MAINNET`]. +const SDAI_WHALE: Address = address!("4C612E3B15b96Ff9A6faED838F8d07d479a8dD4c"); + +/// WETH on mainnet. +const WETH: Address = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); + +#[tokio::test] +#[ignore] +async fn forked_node_mainnet_eip4626_native_price() { + run_forked_test_with_block_number( + eip4626_native_price_test, + std::env::var("FORK_URL_MAINNET") + .expect("FORK_URL_MAINNET must be set to run forked tests"), + FORK_BLOCK_MAINNET, + ) + .await; +} + +async fn eip4626_native_price_test(web3: Web3) { + let mut onchain = OnchainComponents::deployed(web3.clone()).await; + + let [solver] = onchain.make_solvers_forked(1u64.eth()).await; + let [trader] = onchain.make_accounts(1u64.eth()).await; + + let sdai = ERC20::Instance::new(SDAI, web3.provider.clone()); + + // Transfer sDAI from whale to trader. + web3.provider + .anvil_send_impersonated_transaction_with_config( + sdai.transfer(trader.address(), 1000u64.eth()) + .from(SDAI_WHALE) + .into_transaction_request(), + ImpersonateConfig { + fund_amount: Some(1u64.eth()), + stop_impersonate: true, + }, + ) + .await + .unwrap() + .get_receipt() + .await + .unwrap(); + + // Approve the vault-relayer for trading. + sdai.approve(onchain.contracts().allowance, 1000u64.eth()) + .from(trader.address()) + .send_and_watch() + .await + .unwrap(); + + let driver_url: url::Url = "http://localhost:11088/test_solver".parse().unwrap(); + let autopilot_config = Configuration { + native_price_estimation: NativePriceConfig { + eip4626: true, + estimators: NativePriceEstimators::new(vec![vec![NativePriceEstimator::driver( + "test_quoter".to_string(), + driver_url, + )]]), + shared: configs::native_price::NativePriceConfig { + results_required: 1.try_into().unwrap(), + ..Default::default() + }, + ..NativePriceConfig::test_default() + }, + ..Configuration::test("test_solver", solver.address()) + }; + + let services = Services::new(&onchain).await; + services + .start_protocol_with_args( + autopilot_config, + configs::orderbook::Configuration::test_default(), + solver, + ) + .await; + + onchain.mint_block().await; + + // Submit a quote selling sDAI for WETH. If the EIP-4626 native price + // estimator works, the protocol can price sDAI and the quote succeeds. + let quote = services + .submit_quote(&OrderQuoteRequest { + from: trader.address(), + sell_token: SDAI, + buy_token: WETH, + side: OrderQuoteSide::Sell { + sell_amount: SellAmount::BeforeFee { + value: (100u64.eth()).try_into().unwrap(), + }, + }, + ..Default::default() + }) + .await; + + assert!( + quote.is_ok(), + "quote for sDAI should succeed with EIP-4626 native price estimator: {:?}", + quote.err() + ); +} + +#[tokio::test] +#[ignore] +async fn forked_node_mainnet_eip4626_recursive_native_price() { + run_forked_test_with_block_number( + eip4626_recursive_native_price_test, + std::env::var("FORK_URL_MAINNET") + .expect("FORK_URL_MAINNET must be set to run forked tests"), + FORK_BLOCK_MAINNET, + ) + .await; +} + +/// Tests pricing of mock EIP-4626 vaults with non-trivial conversion rates. +/// Deploys wrapper vaults on top of sDAI (which itself wraps DAI) with +/// different rates and verifies native prices are proportional to their +/// conversion rates. +async fn eip4626_recursive_native_price_test(web3: Web3) { + let mut onchain = OnchainComponents::deployed(web3.clone()).await; + + let [solver] = onchain.make_solvers_forked(1u64.eth()).await; + + // Deploy mock EIP-4626 vaults wrapping sDAI with different conversion rates. + // Each wrapper applies `convertToAssets(shares) = shares * num / den`, so a + // (3, 2) wrapper means 1 share = 1.5 sDAI, making it 1.5x the sDAI price. + let rates: &[(u64, u64)] = &[(3, 2), (2, 1), (1, 3)]; + let mut wrapper_addrs = Vec::with_capacity(rates.len()); + for &(num, den) in rates { + let wrapper = contracts::test::MockERC4626Wrapper::Instance::deploy( + web3.provider.clone(), + SDAI, + 18u8, + U256::from(num), + U256::from(den), + ) + .await + .unwrap(); + wrapper_addrs.push(*wrapper.address()); + } + + let driver_url: url::Url = "http://localhost:11088/test_solver".parse().unwrap(); + let autopilot_config = Configuration { + native_price_estimation: NativePriceConfig { + eip4626: true, + estimators: NativePriceEstimators::new(vec![vec![NativePriceEstimator::driver( + "test_quoter".to_string(), + driver_url, + )]]), + shared: configs::native_price::NativePriceConfig { + results_required: 1.try_into().unwrap(), + ..Default::default() + }, + ..NativePriceConfig::test_default() + }, + ..Configuration::test("test_solver", solver.address()) + }; + + let services = Services::new(&onchain).await; + services + .start_protocol_with_args( + autopilot_config, + configs::orderbook::Configuration::test_default(), + solver, + ) + .await; + + onchain.mint_block().await; + + // Verify native prices: use the first wrapper (3/2) as a baseline and + // check that the others are priced proportionally to their conversion rate. + let baseline_addr = wrapper_addrs[0]; + wait_for_condition(TIMEOUT, || async { + services.get_native_price(&baseline_addr).await.is_ok() + }) + .await + .expect("native price for wrapper (3/2) should be available"); + let baseline_price = services + .get_native_price(&baseline_addr) + .await + .unwrap() + .price; + + // Wrapper (2/1) has rate 2/1 vs baseline 3/2, so its price should be + // (2/1) / (3/2) = 4/3 of the baseline. + let addr = wrapper_addrs[1]; + wait_for_condition(TIMEOUT, || async { + services.get_native_price(&addr).await.is_ok() + }) + .await + .expect("native price for wrapper (2/1) should be available"); + let price = services.get_native_price(&addr).await.unwrap().price; + let ratio = price / baseline_price; + assert!( + (ratio - 4.0 / 3.0).abs() / (4.0 / 3.0) < 0.01, + "wrapper (2/1) price ratio to baseline (3/2) should be 4/3: got {ratio:.6}", + ); + + // Wrapper (1/3) has rate 1/3 vs baseline 3/2, so its price should be + // (1/3) / (3/2) = 2/9 of the baseline. + let addr = wrapper_addrs[2]; + wait_for_condition(TIMEOUT, || async { + services.get_native_price(&addr).await.is_ok() + }) + .await + .expect("native price for wrapper (1/3) should be available"); + let price = services.get_native_price(&addr).await.unwrap().price; + let ratio = price / baseline_price; + assert!( + (ratio - 2.0 / 9.0).abs() / (2.0 / 9.0) < 0.01, + "wrapper (1/3) price ratio to baseline (3/2) should be 2/9: got {ratio:.6}", + ); +} diff --git a/crates/e2e/tests/e2e/main.rs b/crates/e2e/tests/e2e/main.rs index 7240e75349..fdf61242bf 100644 --- a/crates/e2e/tests/e2e/main.rs +++ b/crates/e2e/tests/e2e/main.rs @@ -15,6 +15,7 @@ mod cow_amm; mod database; mod debug_order; mod deprecated_endpoints; +mod eip4626; mod eth_integration; mod eth_safe; mod ethflow; diff --git a/crates/price-estimation/Cargo.toml b/crates/price-estimation/Cargo.toml index c2596b132a..42f08ca145 100644 --- a/crates/price-estimation/Cargo.toml +++ b/crates/price-estimation/Cargo.toml @@ -22,6 +22,7 @@ clap = { workspace = true } configs = { workspace = true } const-hex = { workspace = true } contracts = { workspace = true } +dashmap = { workspace = true } derive_more = { workspace = true } ethrpc = { workspace = true } futures = { workspace = true } diff --git a/crates/price-estimation/src/factory.rs b/crates/price-estimation/src/factory.rs index 4d5268ca64..6dc1e9c971 100644 --- a/crates/price-estimation/src/factory.rs +++ b/crates/price-estimation/src/factory.rs @@ -368,7 +368,9 @@ impl<'a> PriceEstimatorFactory<'a> { )) } - /// Creates a native price estimator from the given sources. + /// Creates a native price estimator from the given sources. When `eip4626` + /// is true the resulting estimator is wrapped in an [`native::Eip4626`] + /// layer that transparently prices vault tokens. pub async fn native_price_estimator( &mut self, native: &[Vec], @@ -393,17 +395,29 @@ impl<'a> PriceEstimatorFactory<'a> { /// Creates a [`CachingNativePriceEstimator`] that wraps a native price /// estimator with an in-memory cache. + /// + /// If `eip4626` is true, it will wrap the estimator with EIP-4626 + /// unwrapping. pub async fn caching_native_price_estimator( &mut self, native: &[Vec], results_required: NonZeroUsize, weth: &WETH9::Instance, cache: native_price_cache::Cache, + eip4626: bool, ) -> native_price_cache::CachingNativePriceEstimator { let inner = self .native_price_estimator(native, results_required, weth) .await .expect("failed to build native price estimator"); + let inner = if eip4626 { + Box::new(InstrumentedPriceEstimator::new( + native::Eip4626::new(inner, self.network.web3.provider.clone()), + "Eip4626".to_string(), + )) + } else { + inner + }; self.caching_native_price_estimator_from_inner(inner, cache) .await } diff --git a/crates/price-estimation/src/native/eip4626.rs b/crates/price-estimation/src/native/eip4626.rs new file mode 100644 index 0000000000..7493294ad7 --- /dev/null +++ b/crates/price-estimation/src/native/eip4626.rs @@ -0,0 +1,275 @@ +use { + super::{NativePriceEstimateResult, NativePriceEstimating}, + crate::PriceEstimationError, + alloy::primitives::{Address, U256}, + anyhow::Context, + contracts::{ERC20, IERC4626}, + dashmap::DashSet, + ethrpc::{AlloyProvider, alloy::errors::ContractErrorExt}, + futures::{FutureExt, future::BoxFuture}, + num::{BigInt, BigRational, ToPrimitive}, + number::conversions::u256_to_big_rational, + std::time::{Duration, Instant}, +}; + +/// Estimates the native price of EIP-4626 vault tokens by: +/// 1. Querying `asset()` and `decimals()` on the vault +/// 2. Querying `convertToAssets(10^vault_decimals)` and `decimals()` on the +/// underlying asset +/// 3. Computing the conversion rate accounting for decimal differences +/// 4. Delegating to an inner estimator for the underlying token's native price +/// +/// For non-vault tokens, delegates directly to the inner estimator +/// (pass-through). +/// +/// Tokens whose `asset()` call reverts are remembered in a negative cache so +/// subsequent requests skip the RPC and go straight to the inner estimator. +pub struct Eip4626 { + inner: Box, + provider: AlloyProvider, + /// Addresses that are known *not* to be EIP-4626 vaults (i.e. `asset()` + /// reverted). Checked before making any RPC calls. + non_vault_tokens: DashSet
, +} + +impl Eip4626 { + pub fn new(inner: Box, provider: AlloyProvider) -> Self { + Self { + inner, + provider, + non_vault_tokens: DashSet::new(), + } + } + + async fn estimate(&self, token: Address, timeout: Duration) -> NativePriceEstimateResult { + let deadline = Instant::now() + timeout; + let (underlying, cumulative_rate) = + tokio::time::timeout(timeout, self.unwrap_all_layers(token)) + .await + .map_err(|_| { + PriceEstimationError::EstimatorInternal(anyhow::anyhow!( + "timeout while unwrapping EIP-4626 layers for {token}" + )) + })??; + + let remaining = deadline.saturating_duration_since(Instant::now()); + let asset_price = self + .inner + .estimate_native_price(underlying, remaining) + .await?; + Ok(asset_price * cumulative_rate) + } + + /// Follows the vault chain (e.g. vault → vault → asset) until reaching a + /// non-vault token, returning the terminal token and the cumulative + /// shares-to-assets rate. + async fn unwrap_all_layers( + &self, + token: Address, + ) -> Result<(Address, f64), PriceEstimationError> { + let mut current_token = token; + let mut cumulative_rate = 1.0; + while let Some((asset, rate)) = self.unwrap_vault_layer(current_token).await? { + cumulative_rate *= rate; + current_token = asset; + } + Ok((current_token, cumulative_rate)) + } + + /// Returns: + /// - `Ok(Some((asset, rate)))` when `token` is a vault. + /// - `Ok(None)` when it's a plain ERC-20. + /// - `Err` on RPC/computation failures that don't let us classify the + /// token. + async fn unwrap_vault_layer( + &self, + token: Address, + ) -> Result, PriceEstimationError> { + if self.non_vault_tokens.contains(&token) { + return Ok(None); + } + + let Some((asset, vault_decimals)) = self.fetch_vault_info(token).await? else { + self.non_vault_tokens.insert(token); + metrics::non_vault_cache_size(self.non_vault_tokens.len()); + return Ok(None); + }; + let (assets, asset_decimals) = self + .fetch_conversion_data(token, asset, vault_decimals) + .await?; + let rate = conversion_rate(assets, asset_decimals) + .context("conversion rate is not representable as f64") + .map_err(PriceEstimationError::EstimatorInternal)?; + Ok(Some((asset, rate))) + } + + /// Fetches the vault's underlying asset address and vault token decimals. + /// + /// Returns: + /// - `Ok(Some(...))` when `token` is a vault. + /// - `Ok(None)` when `asset()` reverts (indicating it is a regular ERC-20). + /// - `Err` on transient transport failures — those are *not* cached as + /// non-vault. + async fn fetch_vault_info( + &self, + token: Address, + ) -> Result, PriceEstimationError> { + let vault = IERC4626::IERC4626::new(token, &self.provider); + let vault_erc20 = ERC20::ERC20::new(token, &self.provider); + let asset_call = vault.asset(); + let decimals_call = vault_erc20.decimals(); + let (asset_result, decimals_result) = tokio::join!(asset_call.call(), decimals_call.call()); + + match asset_result { + Ok(asset) => { + // EIP-4626 vaults implement ERC-20 so decimals() must succeed too. + let vault_decimals = decimals_result.map_err(|err| { + PriceEstimationError::EstimatorInternal(anyhow::anyhow!( + "failed to call decimals() on {token}: {err}" + )) + })?; + Ok(Some((asset, vault_decimals))) + } + // `asset()` reverted but the contract is a valid ERC-20 (decimals() + // succeeded). Classify as non-vault. + Err(err) if err.is_contract_error() && decimals_result.is_ok() => Ok(None), + Err(err) => Err(PriceEstimationError::EstimatorInternal(anyhow::anyhow!( + "failed to call asset() on {token}: {err}" + ))), + } + } + + /// Fetches `convertToAssets(10^vault_decimals)` — how many atomic units of + /// the underlying asset correspond to one full vault token — and the + /// asset's decimals. + async fn fetch_conversion_data( + &self, + token: Address, + asset: Address, + vault_decimals: u8, + ) -> Result<(U256, u8), PriceEstimationError> { + let one_token = U256::from(10u64) + .checked_pow(U256::from(vault_decimals)) + .ok_or_else(|| { + PriceEstimationError::EstimatorInternal(anyhow::anyhow!( + "vault decimals {vault_decimals} for {token} cause U256 overflow" + )) + })?; + + let vault = IERC4626::IERC4626::new(token, &self.provider); + let asset_erc20 = ERC20::ERC20::new(asset, &self.provider); + let convert_call = vault.convertToAssets(one_token); + let asset_decimals_call = asset_erc20.decimals(); + tokio::try_join!(convert_call.call(), asset_decimals_call.call()).map_err(|err| { + PriceEstimationError::EstimatorInternal(anyhow::anyhow!( + "failed to call convertToAssets()/decimals() on {token}: {err}" + )) + }) + } +} + +impl NativePriceEstimating for Eip4626 { + fn estimate_native_price( + &self, + token: Address, + timeout: Duration, + ) -> BoxFuture<'_, NativePriceEstimateResult> { + self.estimate(token, timeout).boxed() + } +} + +/// Computes the full-asset-tokens per full-vault-token conversion rate. +/// +/// `assets` is the return value of `convertToAssets(10^vault_decimals)` — i.e. +/// asset-atomic-units for exactly 1 full vault token. Dividing by +/// `10^asset_decimals` converts to full asset tokens. +/// +/// Returns `None` when the result is not representable as `f64`. +fn conversion_rate(assets: U256, asset_decimals: u8) -> Option { + let denominator = BigRational::from_integer(BigInt::from(10u64).pow(asset_decimals as u32)); + (u256_to_big_rational(&assets) / denominator).to_f64() +} + +mod metrics { + use {observe::metrics, prometheus::IntGauge}; + + #[derive(prometheus_metric_storage::MetricStorage)] + struct Metrics { + /// Number of tokens in the EIP-4626 negative cache (known non-vault + /// tokens). + eip4626_non_vault_cache_size: IntGauge, + } + + impl Metrics { + fn get() -> &'static Self { + Metrics::instance(metrics::get_storage_registry()).unwrap() + } + } + + pub(super) fn non_vault_cache_size(size: usize) { + Metrics::get() + .eip4626_non_vault_cache_size + .set(i64::try_from(size).unwrap_or(i64::MAX)); + } +} + +#[cfg(test)] +mod tests { + use { + super::*, + crate::{HEALTHY_PRICE_ESTIMATION_TIME, native::MockNativePriceEstimating}, + }; + + #[test] + fn rate_math_same_decimals() { + // 18-decimal vault wrapping 18-decimal asset, 1 share = 1.5 asset tokens. + // convertToAssets(10^18) = 1.5 * 10^18 asset-atomic-units + let assets = U256::from(15u64) * U256::from(10u64).pow(U256::from(17u64)); + let rate = conversion_rate(assets, 18).unwrap(); + assert!((rate - 1.5).abs() < 1e-9, "rate={rate}"); + } + + #[test] + fn rate_math_vault_18_asset_6() { + // 18-decimal vault wrapping 6-decimal USDC, 1 share = 1.5 USDC. + // convertToAssets(10^18) = 1_500_000 asset-atomic-units (1.5 * 10^6) + let assets = U256::from(1_500_000u64); + let rate = conversion_rate(assets, 6).unwrap(); + assert!((rate - 1.5).abs() < 1e-9, "rate={rate}"); + } + + #[test] + fn rate_math_vault_6_asset_18() { + // 6-decimal vault wrapping 18-decimal asset, 1 share = 2 asset tokens. + // convertToAssets(10^6) = 2 * 10^18 asset-atomic-units + let assets = U256::from(2u64) * U256::from(10u64).pow(U256::from(18u64)); + let rate = conversion_rate(assets, 18).unwrap(); + assert!((rate - 2.0).abs() < 1e-9, "rate={rate}"); + } + + #[tokio::test] + async fn non_vault_tokens_delegate_to_inner() { + let mut inner = MockNativePriceEstimating::new(); + let token = Address::repeat_byte(0x42); + let expected_price = 1.5; + inner + .expect_estimate_native_price() + .withf(move |t, _| *t == token) + .returning(move |_, _| Box::pin(async move { Ok(expected_price) })); + + let non_vault_tokens = DashSet::new(); + non_vault_tokens.insert(token); + + let estimator = Eip4626 { + inner: Box::new(inner), + // The provider is never reached because the cache short-circuits. + provider: ethrpc::Web3::new_from_url("http://localhost:1").provider, + non_vault_tokens, + }; + + let result = estimator + .estimate(token, HEALTHY_PRICE_ESTIMATION_TIME) + .await; + assert_eq!(result.unwrap(), expected_price); + } +} diff --git a/crates/price-estimation/src/native/mod.rs b/crates/price-estimation/src/native/mod.rs index f39dd7666c..95338b3562 100644 --- a/crates/price-estimation/src/native/mod.rs +++ b/crates/price-estimation/src/native/mod.rs @@ -13,12 +13,14 @@ use { }; mod coingecko; +mod eip4626; pub mod fallback; mod forwarder; mod oneinch; pub use self::{ coingecko::CoinGecko, + eip4626::Eip4626, fallback::FallbackNativePriceEstimator, forwarder::Forwarder, oneinch::OneInch,