diff --git a/Cargo.toml b/Cargo.toml index 6e8a9837..444641d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ alloy = { git = "https://github.com/alloy-rs/alloy", rev = "fd8f065", features = # "rpc-types", "rpc-types-eth", # "rpc-types-engine", - # "rpc-types-trace", + "rpc-types-trace", "signers", # "signer-aws", # "signer-gcp", diff --git a/README.md b/README.md index b0680047..d8c4c637 100644 --- a/README.md +++ b/README.md @@ -46,25 +46,13 @@ cargo run --example mnemonic_signer - [ ] Watch blocks - [ ] Subscribe events by type - [ ] Subscribe logs -- [ ] Transactions - - [ ] Call override - - [ ] Create raw transaction - - [ ] Create typed transaction - - [ ] Decode input - - [ ] EIP-1559 - - [ ] ENS - - [ ] Estimate gas - - [ ] Get gas price - - [ ] Get gas price USD - - [ ] Remove liquidity - - [ ] Set gas for a transaction - - [ ] Send raw transaction - - [ ] Send typed transaction - - [ ] Trace - - [ ] Transaction receipt - - [ ] Transaction status - - [ ] Transfer ETH - - [ ] Transfer ERC20 token +- [x] Transactions + - [x] [Decode input](./examples/transactions/examples/decode_input.rs) + - [x] [Get gas price in USD](./examples/transactions/examples/gas_price_usd.rs) + - [x] [Trace call](./examples/transactions/examples/trace_call.rs) + - [x] [Trace transaction](./examples/transactions/examples/trace_transaction.rs) + - [x] [Transfer ERC20 token](./examples/transactions/examples/transfer_erc20.rs) + - [x] [Transfer ETH](./examples/transactions/examples/transfer_eth.rs) - [ ] Wallets - [ ] AWS signer - [ ] GCP signer diff --git a/examples/transactions/Cargo.toml b/examples/transactions/Cargo.toml new file mode 100644 index 00000000..d5660569 --- /dev/null +++ b/examples/transactions/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "examples-transactions" + +publish.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dev-dependencies] +alloy.workspace = true + +eyre.workspace = true +reqwest.workspace = true +tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } diff --git a/examples/transactions/examples/contracts/ERC20Example.json b/examples/transactions/examples/contracts/ERC20Example.json new file mode 100644 index 00000000..18e3b603 --- /dev/null +++ b/examples/transactions/examples/contracts/ERC20Example.json @@ -0,0 +1,698 @@ +{ + "abi": [ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "spender", + "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": "balanceOf", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "uint8" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decreaseAllowance", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "subtractedValue", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "increaseAllowance", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "addedValue", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "totalSupply", + "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" + }, + { + "type": "event", + "name": "Approval", + "inputs": [ + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "spender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Transfer", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + } + ], + "bytecode": { + "object": "0x60806040523480156200001157600080fd5b506040518060400160405280600c81526020017f45524332304578616d706c6500000000000000000000000000000000000000008152506040518060400160405280600381526020017f58595a000000000000000000000000000000000000000000000000000000000081525081600390816200008f9190620004ed565b508060049081620000a19190620004ed565b505050620000e233620000b9620000e860201b60201c565b600a620000c7919062000764565b6103e8620000d69190620007b5565b620000f160201b60201c565b620008ec565b60006012905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362000163576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015a9062000861565b60405180910390fd5b62000177600083836200026960201b60201c565b80600260008282546200018b919062000883565b92505081905550806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254620001e2919062000883565b925050819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620002499190620008cf565b60405180910390a362000265600083836200026e60201b60201c565b5050565b505050565b505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620002f557607f821691505b6020821081036200030b576200030a620002ad565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003757fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000336565b62000381868362000336565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003ce620003c8620003c28462000399565b620003a3565b62000399565b9050919050565b6000819050919050565b620003ea83620003ad565b62000402620003f982620003d5565b84845462000343565b825550505050565b600090565b620004196200040a565b62000426818484620003df565b505050565b5b818110156200044e57620004426000826200040f565b6001810190506200042c565b5050565b601f8211156200049d57620004678162000311565b620004728462000326565b8101602085101562000482578190505b6200049a620004918562000326565b8301826200042b565b50505b505050565b600082821c905092915050565b6000620004c260001984600802620004a2565b1980831691505092915050565b6000620004dd8383620004af565b9150826002028217905092915050565b620004f88262000273565b67ffffffffffffffff8111156200051457620005136200027e565b5b620005208254620002dc565b6200052d82828562000452565b600060209050601f83116001811462000565576000841562000550578287015190505b6200055c8582620004cf565b865550620005cc565b601f198416620005758662000311565b60005b828110156200059f5784890151825560018201915060208501945060208101905062000578565b86831015620005bf5784890151620005bb601f891682620004af565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b600185111562000662578086048111156200063a5762000639620005d4565b5b60018516156200064a5780820291505b80810290506200065a8562000603565b94506200061a565b94509492505050565b6000826200067d576001905062000750565b816200068d576000905062000750565b8160018114620006a65760028114620006b157620006e7565b600191505062000750565b60ff841115620006c657620006c5620005d4565b5b8360020a915084821115620006e057620006df620005d4565b5b5062000750565b5060208310610133831016604e8410600b8410161715620007215782820a9050838111156200071b576200071a620005d4565b5b62000750565b62000730848484600162000610565b925090508184048111156200074a5762000749620005d4565b5b81810290505b9392505050565b600060ff82169050919050565b6000620007718262000399565b91506200077e8362000757565b9250620007ad7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846200066b565b905092915050565b6000620007c28262000399565b9150620007cf8362000399565b9250828202620007df8162000399565b91508282048414831517620007f957620007f8620005d4565b5b5092915050565b600082825260208201905092915050565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b600062000849601f8362000800565b9150620008568262000811565b602082019050919050565b600060208201905081810360008301526200087c816200083a565b9050919050565b6000620008908262000399565b91506200089d8362000399565b9250828201905080821115620008b857620008b7620005d4565b5b92915050565b620008c98162000399565b82525050565b6000602082019050620008e66000830184620008be565b92915050565b61123880620008fc6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461016857806370a082311461019857806395d89b41146101c8578063a457c2d7146101e6578063a9059cbb14610216578063dd62ed3e14610246576100a9565b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100fc57806323b872dd1461011a578063313ce5671461014a575b600080fd5b6100b6610276565b6040516100c39190610b15565b60405180910390f35b6100e660048036038101906100e19190610bd0565b610308565b6040516100f39190610c2b565b60405180910390f35b61010461032b565b6040516101119190610c55565b60405180910390f35b610134600480360381019061012f9190610c70565b610335565b6040516101419190610c2b565b60405180910390f35b610152610364565b60405161015f9190610cdf565b60405180910390f35b610182600480360381019061017d9190610bd0565b61036d565b60405161018f9190610c2b565b60405180910390f35b6101b260048036038101906101ad9190610cfa565b6103a4565b6040516101bf9190610c55565b60405180910390f35b6101d06103ec565b6040516101dd9190610b15565b60405180910390f35b61020060048036038101906101fb9190610bd0565b61047e565b60405161020d9190610c2b565b60405180910390f35b610230600480360381019061022b9190610bd0565b6104f5565b60405161023d9190610c2b565b60405180910390f35b610260600480360381019061025b9190610d27565b610518565b60405161026d9190610c55565b60405180910390f35b60606003805461028590610d96565b80601f01602080910402602001604051908101604052809291908181526020018280546102b190610d96565b80156102fe5780601f106102d3576101008083540402835291602001916102fe565b820191906000526020600020905b8154815290600101906020018083116102e157829003601f168201915b5050505050905090565b60008061031361059f565b90506103208185856105a7565b600191505092915050565b6000600254905090565b60008061034061059f565b905061034d858285610770565b6103588585856107fc565b60019150509392505050565b60006012905090565b60008061037861059f565b905061039981858561038a8589610518565b6103949190610df6565b6105a7565b600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6060600480546103fb90610d96565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610d96565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505050905090565b60008061048961059f565b905060006104978286610518565b9050838110156104dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d390610e9c565b60405180910390fd5b6104e982868684036105a7565b60019250505092915050565b60008061050061059f565b905061050d8185856107fc565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610616576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060d90610f2e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067c90610fc0565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516107639190610c55565b60405180910390a3505050565b600061077c8484610518565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146107f657818110156107e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107df9061102c565b60405180910390fd5b6107f584848484036105a7565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361086b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610862906110be565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d190611150565b60405180910390fd5b6108e5838383610a7b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561096b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610962906111e2565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546109fe9190610df6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610a629190610c55565b60405180910390a3610a75848484610a80565b50505050565b505050565b505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610abf578082015181840152602081019050610aa4565b60008484015250505050565b6000601f19601f8301169050919050565b6000610ae782610a85565b610af18185610a90565b9350610b01818560208601610aa1565b610b0a81610acb565b840191505092915050565b60006020820190508181036000830152610b2f8184610adc565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610b6782610b3c565b9050919050565b610b7781610b5c565b8114610b8257600080fd5b50565b600081359050610b9481610b6e565b92915050565b6000819050919050565b610bad81610b9a565b8114610bb857600080fd5b50565b600081359050610bca81610ba4565b92915050565b60008060408385031215610be757610be6610b37565b5b6000610bf585828601610b85565b9250506020610c0685828601610bbb565b9150509250929050565b60008115159050919050565b610c2581610c10565b82525050565b6000602082019050610c406000830184610c1c565b92915050565b610c4f81610b9a565b82525050565b6000602082019050610c6a6000830184610c46565b92915050565b600080600060608486031215610c8957610c88610b37565b5b6000610c9786828701610b85565b9350506020610ca886828701610b85565b9250506040610cb986828701610bbb565b9150509250925092565b600060ff82169050919050565b610cd981610cc3565b82525050565b6000602082019050610cf46000830184610cd0565b92915050565b600060208284031215610d1057610d0f610b37565b5b6000610d1e84828501610b85565b91505092915050565b60008060408385031215610d3e57610d3d610b37565b5b6000610d4c85828601610b85565b9250506020610d5d85828601610b85565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610dae57607f821691505b602082108103610dc157610dc0610d67565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e0182610b9a565b9150610e0c83610b9a565b9250828201905080821115610e2457610e23610dc7565b5b92915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000610e86602583610a90565b9150610e9182610e2a565b604082019050919050565b60006020820190508181036000830152610eb581610e79565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000610f18602483610a90565b9150610f2382610ebc565b604082019050919050565b60006020820190508181036000830152610f4781610f0b565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000610faa602283610a90565b9150610fb582610f4e565b604082019050919050565b60006020820190508181036000830152610fd981610f9d565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b6000611016601d83610a90565b915061102182610fe0565b602082019050919050565b6000602082019050818103600083015261104581611009565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006110a8602583610a90565b91506110b38261104c565b604082019050919050565b600060208201905081810360008301526110d78161109b565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b600061113a602383610a90565b9150611145826110de565b604082019050919050565b600060208201905081810360008301526111698161112d565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b60006111cc602683610a90565b91506111d782611170565b604082019050919050565b600060208201905081810360008301526111fb816111bf565b905091905056fea2646970667358221220d6bb44e0a93c4d826ca2f8fe885579926ebb8cdd5455ae7223ebad297341ff4964736f6c63430008180033", + "sourceMap": "116:141:4:-:0;;;153:102;;;;;;;;;;1978:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2052:5;2044;:13;;;;;;:::i;:::-;;2077:7;2067;:17;;;;;;:::i;:::-;;1978:113;;206:42:4::1;212:10;237;:8;;;:10;;:::i;:::-;231:2;:16;;;;:::i;:::-;224:4;:23;;;;:::i;:::-;206:5;;;:42;;:::i;:::-;116:141:::0;;3093:91:0;3151:5;3175:2;3168:9;;3093:91;:::o;8349:389::-;8451:1;8432:21;;:7;:21;;;8424:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;8500:49;8529:1;8533:7;8542:6;8500:20;;;:49;;:::i;:::-;8576:6;8560:12;;:22;;;;;;;:::i;:::-;;;;;;;;8614:6;8592:9;:18;8602:7;8592:18;;;;;;;;;;;;;;;;:28;;;;;;;:::i;:::-;;;;;;;;8656:7;8635:37;;8652:1;8635:37;;;8665:6;8635:37;;;;;;:::i;:::-;;;;;;;;8683:48;8711:1;8715:7;8724:6;8683:19;;;:48;;:::i;:::-;8349:389;;:::o;11673:91::-;;;;:::o;12352:90::-;;;;:::o;7:99:5:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:180::-;160:77;157:1;150:88;257:4;254:1;247:15;281:4;278:1;271:15;298:180;346:77;343:1;336:88;443:4;440:1;433:15;467:4;464:1;457:15;484:320;528:6;565:1;559:4;555:12;545:22;;612:1;606:4;602:12;633:18;623:81;;689:4;681:6;677:17;667:27;;623:81;751:2;743:6;740:14;720:18;717:38;714:84;;770:18;;:::i;:::-;714:84;535:269;484:320;;;:::o;810:141::-;859:4;882:3;874:11;;905:3;902:1;895:14;939:4;936:1;926:18;918:26;;810:141;;;:::o;957:93::-;994:6;1041:2;1036;1029:5;1025:14;1021:23;1011:33;;957:93;;;:::o;1056:107::-;1100:8;1150:5;1144:4;1140:16;1119:37;;1056:107;;;;:::o;1169:393::-;1238:6;1288:1;1276:10;1272:18;1311:97;1341:66;1330:9;1311:97;:::i;:::-;1429:39;1459:8;1448:9;1429:39;:::i;:::-;1417:51;;1501:4;1497:9;1490:5;1486:21;1477:30;;1550:4;1540:8;1536:19;1529:5;1526:30;1516:40;;1245:317;;1169:393;;;;;:::o;1568:77::-;1605:7;1634:5;1623:16;;1568:77;;;:::o;1651:60::-;1679:3;1700:5;1693:12;;1651:60;;;:::o;1717:142::-;1767:9;1800:53;1818:34;1827:24;1845:5;1827:24;:::i;:::-;1818:34;:::i;:::-;1800:53;:::i;:::-;1787:66;;1717:142;;;:::o;1865:75::-;1908:3;1929:5;1922:12;;1865:75;;;:::o;1946:269::-;2056:39;2087:7;2056:39;:::i;:::-;2117:91;2166:41;2190:16;2166:41;:::i;:::-;2158:6;2151:4;2145:11;2117:91;:::i;:::-;2111:4;2104:105;2022:193;1946:269;;;:::o;2221:73::-;2266:3;2221:73;:::o;2300:189::-;2377:32;;:::i;:::-;2418:65;2476:6;2468;2462:4;2418:65;:::i;:::-;2353:136;2300:189;;:::o;2495:186::-;2555:120;2572:3;2565:5;2562:14;2555:120;;;2626:39;2663:1;2656:5;2626:39;:::i;:::-;2599:1;2592:5;2588:13;2579:22;;2555:120;;;2495:186;;:::o;2687:543::-;2788:2;2783:3;2780:11;2777:446;;;2822:38;2854:5;2822:38;:::i;:::-;2906:29;2924:10;2906:29;:::i;:::-;2896:8;2892:44;3089:2;3077:10;3074:18;3071:49;;;3110:8;3095:23;;3071:49;3133:80;3189:22;3207:3;3189:22;:::i;:::-;3179:8;3175:37;3162:11;3133:80;:::i;:::-;2792:431;;2777:446;2687:543;;;:::o;3236:117::-;3290:8;3340:5;3334:4;3330:16;3309:37;;3236:117;;;;:::o;3359:169::-;3403:6;3436:51;3484:1;3480:6;3472:5;3469:1;3465:13;3436:51;:::i;:::-;3432:56;3517:4;3511;3507:15;3497:25;;3410:118;3359:169;;;;:::o;3533:295::-;3609:4;3755:29;3780:3;3774:4;3755:29;:::i;:::-;3747:37;;3817:3;3814:1;3810:11;3804:4;3801:21;3793:29;;3533:295;;;;:::o;3833:1395::-;3950:37;3983:3;3950:37;:::i;:::-;4052:18;4044:6;4041:30;4038:56;;;4074:18;;:::i;:::-;4038:56;4118:38;4150:4;4144:11;4118:38;:::i;:::-;4203:67;4263:6;4255;4249:4;4203:67;:::i;:::-;4297:1;4321:4;4308:17;;4353:2;4345:6;4342:14;4370:1;4365:618;;;;5027:1;5044:6;5041:77;;;5093:9;5088:3;5084:19;5078:26;5069:35;;5041:77;5144:67;5204:6;5197:5;5144:67;:::i;:::-;5138:4;5131:81;5000:222;4335:887;;4365:618;4417:4;4413:9;4405:6;4401:22;4451:37;4483:4;4451:37;:::i;:::-;4510:1;4524:208;4538:7;4535:1;4532:14;4524:208;;;4617:9;4612:3;4608:19;4602:26;4594:6;4587:42;4668:1;4660:6;4656:14;4646:24;;4715:2;4704:9;4700:18;4687:31;;4561:4;4558:1;4554:12;4549:17;;4524:208;;;4760:6;4751:7;4748:19;4745:179;;;4818:9;4813:3;4809:19;4803:26;4861:48;4903:4;4895:6;4891:17;4880:9;4861:48;:::i;:::-;4853:6;4846:64;4768:156;4745:179;4970:1;4966;4958:6;4954:14;4950:22;4944:4;4937:36;4372:611;;;4335:887;;3925:1303;;;3833:1395;;:::o;5234:180::-;5282:77;5279:1;5272:88;5379:4;5376:1;5369:15;5403:4;5400:1;5393:15;5420:102;5462:8;5509:5;5506:1;5502:13;5481:34;;5420:102;;;:::o;5528:848::-;5589:5;5596:4;5620:6;5611:15;;5644:5;5635:14;;5658:712;5679:1;5669:8;5666:15;5658:712;;;5774:4;5769:3;5765:14;5759:4;5756:24;5753:50;;;5783:18;;:::i;:::-;5753:50;5833:1;5823:8;5819:16;5816:451;;;6248:4;6241:5;6237:16;6228:25;;5816:451;6298:4;6292;6288:15;6280:23;;6328:32;6351:8;6328:32;:::i;:::-;6316:44;;5658:712;;;5528:848;;;;;;;:::o;6382:1073::-;6436:5;6627:8;6617:40;;6648:1;6639:10;;6650:5;;6617:40;6676:4;6666:36;;6693:1;6684:10;;6695:5;;6666:36;6762:4;6810:1;6805:27;;;;6846:1;6841:191;;;;6755:277;;6805:27;6823:1;6814:10;;6825:5;;;6841:191;6886:3;6876:8;6873:17;6870:43;;;6893:18;;:::i;:::-;6870:43;6942:8;6939:1;6935:16;6926:25;;6977:3;6970:5;6967:14;6964:40;;;6984:18;;:::i;:::-;6964:40;7017:5;;;6755:277;;7141:2;7131:8;7128:16;7122:3;7116:4;7113:13;7109:36;7091:2;7081:8;7078:16;7073:2;7067:4;7064:12;7060:35;7044:111;7041:246;;;7197:8;7191:4;7187:19;7178:28;;7232:3;7225:5;7222:14;7219:40;;;7239:18;;:::i;:::-;7219:40;7272:5;;7041:246;7312:42;7350:3;7340:8;7334:4;7331:1;7312:42;:::i;:::-;7297:57;;;;7386:4;7381:3;7377:14;7370:5;7367:25;7364:51;;;7395:18;;:::i;:::-;7364:51;7444:4;7437:5;7433:16;7424:25;;6382:1073;;;;;;:::o;7461:86::-;7496:7;7536:4;7529:5;7525:16;7514:27;;7461:86;;;:::o;7553:281::-;7611:5;7635:23;7653:4;7635:23;:::i;:::-;7627:31;;7679:25;7695:8;7679:25;:::i;:::-;7667:37;;7723:104;7760:66;7750:8;7744:4;7723:104;:::i;:::-;7714:113;;7553:281;;;;:::o;7840:410::-;7880:7;7903:20;7921:1;7903:20;:::i;:::-;7898:25;;7937:20;7955:1;7937:20;:::i;:::-;7932:25;;7992:1;7989;7985:9;8014:30;8032:11;8014:30;:::i;:::-;8003:41;;8193:1;8184:7;8180:15;8177:1;8174:22;8154:1;8147:9;8127:83;8104:139;;8223:18;;:::i;:::-;8104:139;7888:362;7840:410;;;;:::o;8256:169::-;8340:11;8374:6;8369:3;8362:19;8414:4;8409:3;8405:14;8390:29;;8256:169;;;;:::o;8431:181::-;8571:33;8567:1;8559:6;8555:14;8548:57;8431:181;:::o;8618:366::-;8760:3;8781:67;8845:2;8840:3;8781:67;:::i;:::-;8774:74;;8857:93;8946:3;8857:93;:::i;:::-;8975:2;8970:3;8966:12;8959:19;;8618:366;;;:::o;8990:419::-;9156:4;9194:2;9183:9;9179:18;9171:26;;9243:9;9237:4;9233:20;9229:1;9218:9;9214:17;9207:47;9271:131;9397:4;9271:131;:::i;:::-;9263:139;;8990:419;;;:::o;9415:191::-;9455:3;9474:20;9492:1;9474:20;:::i;:::-;9469:25;;9508:20;9526:1;9508:20;:::i;:::-;9503:25;;9551:1;9548;9544:9;9537:16;;9572:3;9569:1;9566:10;9563:36;;;9579:18;;:::i;:::-;9563:36;9415:191;;;;:::o;9612:118::-;9699:24;9717:5;9699:24;:::i;:::-;9694:3;9687:37;9612:118;;:::o;9736:222::-;9829:4;9867:2;9856:9;9852:18;9844:26;;9880:71;9948:1;9937:9;9933:17;9924:6;9880:71;:::i;:::-;9736:222;;;;:::o;116:141:4:-;;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461016857806370a082311461019857806395d89b41146101c8578063a457c2d7146101e6578063a9059cbb14610216578063dd62ed3e14610246576100a9565b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100fc57806323b872dd1461011a578063313ce5671461014a575b600080fd5b6100b6610276565b6040516100c39190610b15565b60405180910390f35b6100e660048036038101906100e19190610bd0565b610308565b6040516100f39190610c2b565b60405180910390f35b61010461032b565b6040516101119190610c55565b60405180910390f35b610134600480360381019061012f9190610c70565b610335565b6040516101419190610c2b565b60405180910390f35b610152610364565b60405161015f9190610cdf565b60405180910390f35b610182600480360381019061017d9190610bd0565b61036d565b60405161018f9190610c2b565b60405180910390f35b6101b260048036038101906101ad9190610cfa565b6103a4565b6040516101bf9190610c55565b60405180910390f35b6101d06103ec565b6040516101dd9190610b15565b60405180910390f35b61020060048036038101906101fb9190610bd0565b61047e565b60405161020d9190610c2b565b60405180910390f35b610230600480360381019061022b9190610bd0565b6104f5565b60405161023d9190610c2b565b60405180910390f35b610260600480360381019061025b9190610d27565b610518565b60405161026d9190610c55565b60405180910390f35b60606003805461028590610d96565b80601f01602080910402602001604051908101604052809291908181526020018280546102b190610d96565b80156102fe5780601f106102d3576101008083540402835291602001916102fe565b820191906000526020600020905b8154815290600101906020018083116102e157829003601f168201915b5050505050905090565b60008061031361059f565b90506103208185856105a7565b600191505092915050565b6000600254905090565b60008061034061059f565b905061034d858285610770565b6103588585856107fc565b60019150509392505050565b60006012905090565b60008061037861059f565b905061039981858561038a8589610518565b6103949190610df6565b6105a7565b600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6060600480546103fb90610d96565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610d96565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505050905090565b60008061048961059f565b905060006104978286610518565b9050838110156104dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d390610e9c565b60405180910390fd5b6104e982868684036105a7565b60019250505092915050565b60008061050061059f565b905061050d8185856107fc565b600191505092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610616576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060d90610f2e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067c90610fc0565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040516107639190610c55565b60405180910390a3505050565b600061077c8484610518565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146107f657818110156107e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107df9061102c565b60405180910390fd5b6107f584848484036105a7565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361086b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610862906110be565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036108da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d190611150565b60405180910390fd5b6108e5838383610a7b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561096b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610962906111e2565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546109fe9190610df6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610a629190610c55565b60405180910390a3610a75848484610a80565b50505050565b505050565b505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610abf578082015181840152602081019050610aa4565b60008484015250505050565b6000601f19601f8301169050919050565b6000610ae782610a85565b610af18185610a90565b9350610b01818560208601610aa1565b610b0a81610acb565b840191505092915050565b60006020820190508181036000830152610b2f8184610adc565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610b6782610b3c565b9050919050565b610b7781610b5c565b8114610b8257600080fd5b50565b600081359050610b9481610b6e565b92915050565b6000819050919050565b610bad81610b9a565b8114610bb857600080fd5b50565b600081359050610bca81610ba4565b92915050565b60008060408385031215610be757610be6610b37565b5b6000610bf585828601610b85565b9250506020610c0685828601610bbb565b9150509250929050565b60008115159050919050565b610c2581610c10565b82525050565b6000602082019050610c406000830184610c1c565b92915050565b610c4f81610b9a565b82525050565b6000602082019050610c6a6000830184610c46565b92915050565b600080600060608486031215610c8957610c88610b37565b5b6000610c9786828701610b85565b9350506020610ca886828701610b85565b9250506040610cb986828701610bbb565b9150509250925092565b600060ff82169050919050565b610cd981610cc3565b82525050565b6000602082019050610cf46000830184610cd0565b92915050565b600060208284031215610d1057610d0f610b37565b5b6000610d1e84828501610b85565b91505092915050565b60008060408385031215610d3e57610d3d610b37565b5b6000610d4c85828601610b85565b9250506020610d5d85828601610b85565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610dae57607f821691505b602082108103610dc157610dc0610d67565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610e0182610b9a565b9150610e0c83610b9a565b9250828201905080821115610e2457610e23610dc7565b5b92915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b6000610e86602583610a90565b9150610e9182610e2a565b604082019050919050565b60006020820190508181036000830152610eb581610e79565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000610f18602483610a90565b9150610f2382610ebc565b604082019050919050565b60006020820190508181036000830152610f4781610f0b565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000610faa602283610a90565b9150610fb582610f4e565b604082019050919050565b60006020820190508181036000830152610fd981610f9d565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000600082015250565b6000611016601d83610a90565b915061102182610fe0565b602082019050919050565b6000602082019050818103600083015261104581611009565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b60006110a8602583610a90565b91506110b38261104c565b604082019050919050565b600060208201905081810360008301526110d78161109b565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b600061113a602383610a90565b9150611145826110de565b604082019050919050565b600060208201905081810360008301526111698161112d565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b60006111cc602683610a90565b91506111d782611170565b604082019050919050565b600060208201905081810360008301526111fb816111bf565b905091905056fea2646970667358221220d6bb44e0a93c4d826ca2f8fe885579926ebb8cdd5455ae7223ebad297341ff4964736f6c63430008180033", + "sourceMap": "116:141:4:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2156:98:0;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4433:197;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3244:106;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5192:256;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3093:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5843:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3408:125;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2367:102;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6564:427;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3729:189;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3976:149;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2156:98;2210:13;2242:5;2235:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2156:98;:::o;4433:197::-;4516:4;4532:13;4548:12;:10;:12::i;:::-;4532:28;;4570:32;4579:5;4586:7;4595:6;4570:8;:32::i;:::-;4619:4;4612:11;;;4433:197;;;;:::o;3244:106::-;3305:7;3331:12;;3324:19;;3244:106;:::o;5192:256::-;5289:4;5305:15;5323:12;:10;:12::i;:::-;5305:30;;5345:38;5361:4;5367:7;5376:6;5345:15;:38::i;:::-;5393:27;5403:4;5409:2;5413:6;5393:9;:27::i;:::-;5437:4;5430:11;;;5192:256;;;;;:::o;3093:91::-;3151:5;3175:2;3168:9;;3093:91;:::o;5843:234::-;5931:4;5947:13;5963:12;:10;:12::i;:::-;5947:28;;5985:64;5994:5;6001:7;6038:10;6010:25;6020:5;6027:7;6010:9;:25::i;:::-;:38;;;;:::i;:::-;5985:8;:64::i;:::-;6066:4;6059:11;;;5843:234;;;;:::o;3408:125::-;3482:7;3508:9;:18;3518:7;3508:18;;;;;;;;;;;;;;;;3501:25;;3408:125;;;:::o;2367:102::-;2423:13;2455:7;2448:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2367:102;:::o;6564:427::-;6657:4;6673:13;6689:12;:10;:12::i;:::-;6673:28;;6711:24;6738:25;6748:5;6755:7;6738:9;:25::i;:::-;6711:52;;6801:15;6781:16;:35;;6773:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;6892:60;6901:5;6908:7;6936:15;6917:16;:34;6892:8;:60::i;:::-;6980:4;6973:11;;;;6564:427;;;;:::o;3729:189::-;3808:4;3824:13;3840:12;:10;:12::i;:::-;3824:28;;3862;3872:5;3879:2;3883:6;3862:9;:28::i;:::-;3907:4;3900:11;;;3729:189;;;;:::o;3976:149::-;4065:7;4091:11;:18;4103:5;4091:18;;;;;;;;;;;;;;;:27;4110:7;4091:27;;;;;;;;;;;;;;;;4084:34;;3976:149;;;;:::o;640:96:3:-;693:7;719:10;712:17;;640:96;:::o;10057:340:0:-;10175:1;10158:19;;:5;:19;;;10150:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;10255:1;10236:21;;:7;:21;;;10228:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;10337:6;10307:11;:18;10319:5;10307:18;;;;;;;;;;;;;;;:27;10326:7;10307:27;;;;;;;;;;;;;;;:36;;;;10374:7;10358:32;;10367:5;10358:32;;;10383:6;10358:32;;;;;;:::i;:::-;;;;;;;;10057:340;;;:::o;10678:411::-;10778:24;10805:25;10815:5;10822:7;10805:9;:25::i;:::-;10778:52;;10864:17;10844:16;:37;10840:243;;10925:6;10905:16;:26;;10897:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;11007:51;11016:5;11023:7;11051:6;11032:16;:25;11007:8;:51::i;:::-;10840:243;10768:321;10678:411;;;:::o;7445:621::-;7557:1;7541:18;;:4;:18;;;7533:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;7633:1;7619:16;;:2;:16;;;7611:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;7686:38;7707:4;7713:2;7717:6;7686:20;:38::i;:::-;7735:19;7757:9;:15;7767:4;7757:15;;;;;;;;;;;;;;;;7735:37;;7805:6;7790:11;:21;;7782:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;7920:6;7906:11;:20;7888:9;:15;7898:4;7888:15;;;;;;;;;;;;;;;:38;;;;7963:6;7946:9;:13;7956:2;7946:13;;;;;;;;;;;;;;;;:23;;;;;;;:::i;:::-;;;;;;;;8000:2;7985:26;;7994:4;7985:26;;;8004:6;7985:26;;;;;;:::i;:::-;;;;;;;;8022:37;8042:4;8048:2;8052:6;8022:19;:37::i;:::-;7523:543;7445:621;;;:::o;11673:91::-;;;;:::o;12352:90::-;;;;:::o;7:99:5:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:246::-;368:1;378:113;392:6;389:1;386:13;378:113;;;477:1;472:3;468:11;462:18;458:1;453:3;449:11;442:39;414:2;411:1;407:10;402:15;;378:113;;;525:1;516:6;511:3;507:16;500:27;349:184;287:246;;;:::o;539:102::-;580:6;631:2;627:7;622:2;615:5;611:14;607:28;597:38;;539:102;;;:::o;647:377::-;735:3;763:39;796:5;763:39;:::i;:::-;818:71;882:6;877:3;818:71;:::i;:::-;811:78;;898:65;956:6;951:3;944:4;937:5;933:16;898:65;:::i;:::-;988:29;1010:6;988:29;:::i;:::-;983:3;979:39;972:46;;739:285;647:377;;;;:::o;1030:313::-;1143:4;1181:2;1170:9;1166:18;1158:26;;1230:9;1224:4;1220:20;1216:1;1205:9;1201:17;1194:47;1258:78;1331:4;1322:6;1258:78;:::i;:::-;1250:86;;1030:313;;;;:::o;1430:117::-;1539:1;1536;1529:12;1676:126;1713:7;1753:42;1746:5;1742:54;1731:65;;1676:126;;;:::o;1808:96::-;1845:7;1874:24;1892:5;1874:24;:::i;:::-;1863:35;;1808:96;;;:::o;1910:122::-;1983:24;2001:5;1983:24;:::i;:::-;1976:5;1973:35;1963:63;;2022:1;2019;2012:12;1963:63;1910:122;:::o;2038:139::-;2084:5;2122:6;2109:20;2100:29;;2138:33;2165:5;2138:33;:::i;:::-;2038:139;;;;:::o;2183:77::-;2220:7;2249:5;2238:16;;2183:77;;;:::o;2266:122::-;2339:24;2357:5;2339:24;:::i;:::-;2332:5;2329:35;2319:63;;2378:1;2375;2368:12;2319:63;2266:122;:::o;2394:139::-;2440:5;2478:6;2465:20;2456:29;;2494:33;2521:5;2494:33;:::i;:::-;2394:139;;;;:::o;2539:474::-;2607:6;2615;2664:2;2652:9;2643:7;2639:23;2635:32;2632:119;;;2670:79;;:::i;:::-;2632:119;2790:1;2815:53;2860:7;2851:6;2840:9;2836:22;2815:53;:::i;:::-;2805:63;;2761:117;2917:2;2943:53;2988:7;2979:6;2968:9;2964:22;2943:53;:::i;:::-;2933:63;;2888:118;2539:474;;;;;:::o;3019:90::-;3053:7;3096:5;3089:13;3082:21;3071:32;;3019:90;;;:::o;3115:109::-;3196:21;3211:5;3196:21;:::i;:::-;3191:3;3184:34;3115:109;;:::o;3230:210::-;3317:4;3355:2;3344:9;3340:18;3332:26;;3368:65;3430:1;3419:9;3415:17;3406:6;3368:65;:::i;:::-;3230:210;;;;:::o;3446:118::-;3533:24;3551:5;3533:24;:::i;:::-;3528:3;3521:37;3446:118;;:::o;3570:222::-;3663:4;3701:2;3690:9;3686:18;3678:26;;3714:71;3782:1;3771:9;3767:17;3758:6;3714:71;:::i;:::-;3570:222;;;;:::o;3798:619::-;3875:6;3883;3891;3940:2;3928:9;3919:7;3915:23;3911:32;3908:119;;;3946:79;;:::i;:::-;3908:119;4066:1;4091:53;4136:7;4127:6;4116:9;4112:22;4091:53;:::i;:::-;4081:63;;4037:117;4193:2;4219:53;4264:7;4255:6;4244:9;4240:22;4219:53;:::i;:::-;4209:63;;4164:118;4321:2;4347:53;4392:7;4383:6;4372:9;4368:22;4347:53;:::i;:::-;4337:63;;4292:118;3798:619;;;;;:::o;4423:86::-;4458:7;4498:4;4491:5;4487:16;4476:27;;4423:86;;;:::o;4515:112::-;4598:22;4614:5;4598:22;:::i;:::-;4593:3;4586:35;4515:112;;:::o;4633:214::-;4722:4;4760:2;4749:9;4745:18;4737:26;;4773:67;4837:1;4826:9;4822:17;4813:6;4773:67;:::i;:::-;4633:214;;;;:::o;4853:329::-;4912:6;4961:2;4949:9;4940:7;4936:23;4932:32;4929:119;;;4967:79;;:::i;:::-;4929:119;5087:1;5112:53;5157:7;5148:6;5137:9;5133:22;5112:53;:::i;:::-;5102:63;;5058:117;4853:329;;;;:::o;5188:474::-;5256:6;5264;5313:2;5301:9;5292:7;5288:23;5284:32;5281:119;;;5319:79;;:::i;:::-;5281:119;5439:1;5464:53;5509:7;5500:6;5489:9;5485:22;5464:53;:::i;:::-;5454:63;;5410:117;5566:2;5592:53;5637:7;5628:6;5617:9;5613:22;5592:53;:::i;:::-;5582:63;;5537:118;5188:474;;;;;:::o;5668:180::-;5716:77;5713:1;5706:88;5813:4;5810:1;5803:15;5837:4;5834:1;5827:15;5854:320;5898:6;5935:1;5929:4;5925:12;5915:22;;5982:1;5976:4;5972:12;6003:18;5993:81;;6059:4;6051:6;6047:17;6037:27;;5993:81;6121:2;6113:6;6110:14;6090:18;6087:38;6084:84;;6140:18;;:::i;:::-;6084:84;5905:269;5854:320;;;:::o;6180:180::-;6228:77;6225:1;6218:88;6325:4;6322:1;6315:15;6349:4;6346:1;6339:15;6366:191;6406:3;6425:20;6443:1;6425:20;:::i;:::-;6420:25;;6459:20;6477:1;6459:20;:::i;:::-;6454:25;;6502:1;6499;6495:9;6488:16;;6523:3;6520:1;6517:10;6514:36;;;6530:18;;:::i;:::-;6514:36;6366:191;;;;:::o;6563:224::-;6703:34;6699:1;6691:6;6687:14;6680:58;6772:7;6767:2;6759:6;6755:15;6748:32;6563:224;:::o;6793:366::-;6935:3;6956:67;7020:2;7015:3;6956:67;:::i;:::-;6949:74;;7032:93;7121:3;7032:93;:::i;:::-;7150:2;7145:3;7141:12;7134:19;;6793:366;;;:::o;7165:419::-;7331:4;7369:2;7358:9;7354:18;7346:26;;7418:9;7412:4;7408:20;7404:1;7393:9;7389:17;7382:47;7446:131;7572:4;7446:131;:::i;:::-;7438:139;;7165:419;;;:::o;7590:223::-;7730:34;7726:1;7718:6;7714:14;7707:58;7799:6;7794:2;7786:6;7782:15;7775:31;7590:223;:::o;7819:366::-;7961:3;7982:67;8046:2;8041:3;7982:67;:::i;:::-;7975:74;;8058:93;8147:3;8058:93;:::i;:::-;8176:2;8171:3;8167:12;8160:19;;7819:366;;;:::o;8191:419::-;8357:4;8395:2;8384:9;8380:18;8372:26;;8444:9;8438:4;8434:20;8430:1;8419:9;8415:17;8408:47;8472:131;8598:4;8472:131;:::i;:::-;8464:139;;8191:419;;;:::o;8616:221::-;8756:34;8752:1;8744:6;8740:14;8733:58;8825:4;8820:2;8812:6;8808:15;8801:29;8616:221;:::o;8843:366::-;8985:3;9006:67;9070:2;9065:3;9006:67;:::i;:::-;8999:74;;9082:93;9171:3;9082:93;:::i;:::-;9200:2;9195:3;9191:12;9184:19;;8843:366;;;:::o;9215:419::-;9381:4;9419:2;9408:9;9404:18;9396:26;;9468:9;9462:4;9458:20;9454:1;9443:9;9439:17;9432:47;9496:131;9622:4;9496:131;:::i;:::-;9488:139;;9215:419;;;:::o;9640:179::-;9780:31;9776:1;9768:6;9764:14;9757:55;9640:179;:::o;9825:366::-;9967:3;9988:67;10052:2;10047:3;9988:67;:::i;:::-;9981:74;;10064:93;10153:3;10064:93;:::i;:::-;10182:2;10177:3;10173:12;10166:19;;9825:366;;;:::o;10197:419::-;10363:4;10401:2;10390:9;10386:18;10378:26;;10450:9;10444:4;10440:20;10436:1;10425:9;10421:17;10414:47;10478:131;10604:4;10478:131;:::i;:::-;10470:139;;10197:419;;;:::o;10622:224::-;10762:34;10758:1;10750:6;10746:14;10739:58;10831:7;10826:2;10818:6;10814:15;10807:32;10622:224;:::o;10852:366::-;10994:3;11015:67;11079:2;11074:3;11015:67;:::i;:::-;11008:74;;11091:93;11180:3;11091:93;:::i;:::-;11209:2;11204:3;11200:12;11193:19;;10852:366;;;:::o;11224:419::-;11390:4;11428:2;11417:9;11413:18;11405:26;;11477:9;11471:4;11467:20;11463:1;11452:9;11448:17;11441:47;11505:131;11631:4;11505:131;:::i;:::-;11497:139;;11224:419;;;:::o;11649:222::-;11789:34;11785:1;11777:6;11773:14;11766:58;11858:5;11853:2;11845:6;11841:15;11834:30;11649:222;:::o;11877:366::-;12019:3;12040:67;12104:2;12099:3;12040:67;:::i;:::-;12033:74;;12116:93;12205:3;12116:93;:::i;:::-;12234:2;12229:3;12225:12;12218:19;;11877:366;;;:::o;12249:419::-;12415:4;12453:2;12442:9;12438:18;12430:26;;12502:9;12496:4;12492:20;12488:1;12477:9;12473:17;12466:47;12530:131;12656:4;12530:131;:::i;:::-;12522:139;;12249:419;;;:::o;12674:225::-;12814:34;12810:1;12802:6;12798:14;12791:58;12883:8;12878:2;12870:6;12866:15;12859:33;12674:225;:::o;12905:366::-;13047:3;13068:67;13132:2;13127:3;13068:67;:::i;:::-;13061:74;;13144:93;13233:3;13144:93;:::i;:::-;13262:2;13257:3;13253:12;13246:19;;12905:366;;;:::o;13277:419::-;13443:4;13481:2;13470:9;13466:18;13458:26;;13530:9;13524:4;13520:20;13516:1;13505:9;13501:17;13494:47;13558:131;13684:4;13558:131;:::i;:::-;13550:139;;13277:419;;;:::o", + "linkReferences": {} + }, + "methodIdentifiers": { + "allowance(address,address)": "dd62ed3e", + "approve(address,uint256)": "095ea7b3", + "balanceOf(address)": "70a08231", + "decimals()": "313ce567", + "decreaseAllowance(address,uint256)": "a457c2d7", + "increaseAllowance(address,uint256)": "39509351", + "name()": "06fdde03", + "symbol()": "95d89b41", + "totalSupply()": "18160ddd", + "transfer(address,uint256)": "a9059cbb", + "transferFrom(address,address,uint256)": "23b872dd" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ERC20Example.sol\":\"ERC20Example\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solady/=lib/solady/src/\"]},\"sources\":{\"src/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x1be45089def1d7d2fcdc76c7caedd6f1e89ff334bb8c9e27046f3c6dd72e0655\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6bbe28def3091e1fc903d29b3118d8964826c140d659fd804cb4efb9e7ff81f3\",\"dweb:/ipfs/QmZAPGRzfS7xPhEMN4kWjkrKdkKdg5gKfZh4y344UAsKC3\"]},\"src/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x00c839ff53d07d19db2e7cfa1e5133f9ee90a8d64b0e2e57f50446a2d1a3a0e0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3dac621d015a68a5251b1e5d41dda0faf252699bf6e8bcf46a958b29964d9dd1\",\"dweb:/ipfs/QmP9axjgZv4cezAhALoTemM62sdLtMDJ9MGTxECnNwHgSJ\"]},\"src/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"src/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"src/ERC20Example.sol\":{\"keccak256\":\"0x0abc6dab644c5533cf6828c3184aeed07256cdf9b597be244a7612c50a0ef258\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eda3e2e04667056620ca8d07dee12a46308d87d6f3777b4a68d839999543104a\",\"dweb:/ipfs/QmeMz9jiAGXa1FWvsGdoHaD1LXBs3cdtnz6B4p7ag6REL8\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.24+commit.e11b9ed9" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "spender", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "Approval", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "to", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "Transfer", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "remappings": [ + "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", + "ds-test/=lib/forge-std/lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-std/=lib/forge-std/src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "solady/=lib/solady/src/" + ], + "optimizer": { + "enabled": false, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "src/ERC20Example.sol": "ERC20Example" + }, + "evmVersion": "paris", + "libraries": {} + }, + "sources": { + "src/@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "keccak256": "0x1be45089def1d7d2fcdc76c7caedd6f1e89ff334bb8c9e27046f3c6dd72e0655", + "urls": [ + "bzz-raw://6bbe28def3091e1fc903d29b3118d8964826c140d659fd804cb4efb9e7ff81f3", + "dweb:/ipfs/QmZAPGRzfS7xPhEMN4kWjkrKdkKdg5gKfZh4y344UAsKC3" + ], + "license": "MIT" + }, + "src/@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "keccak256": "0x00c839ff53d07d19db2e7cfa1e5133f9ee90a8d64b0e2e57f50446a2d1a3a0e0", + "urls": [ + "bzz-raw://3dac621d015a68a5251b1e5d41dda0faf252699bf6e8bcf46a958b29964d9dd1", + "dweb:/ipfs/QmP9axjgZv4cezAhALoTemM62sdLtMDJ9MGTxECnNwHgSJ" + ], + "license": "MIT" + }, + "src/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "keccak256": "0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca", + "urls": [ + "bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd", + "dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8" + ], + "license": "MIT" + }, + "src/@openzeppelin/contracts/utils/Context.sol": { + "keccak256": "0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7", + "urls": [ + "bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92", + "dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3" + ], + "license": "MIT" + }, + "src/ERC20Example.sol": { + "keccak256": "0x0abc6dab644c5533cf6828c3184aeed07256cdf9b597be244a7612c50a0ef258", + "urls": [ + "bzz-raw://eda3e2e04667056620ca8d07dee12a46308d87d6f3777b4a68d839999543104a", + "dweb:/ipfs/QmeMz9jiAGXa1FWvsGdoHaD1LXBs3cdtnz6B4p7ag6REL8" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "id": 4 +} \ No newline at end of file diff --git a/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/ERC20.sol b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/ERC20.sol new file mode 100644 index 00000000..e8d46cfc --- /dev/null +++ b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/ERC20.sol @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "./IERC20.sol"; +import "./extensions/IERC20Metadata.sol"; +import "../../utils/Context.sol"; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20 is Context, IERC20, IERC20Metadata { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address to, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _transfer(owner, to, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + * - the caller must have allowance for ``from``'s tokens of at least + * `amount`. + */ + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, allowance(owner, spender) + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + address owner = _msgSender(); + uint256 currentAllowance = allowance(owner, spender); + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(owner, spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + */ + function _transfer(address from, address to, uint256 amount) internal virtual { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(from, to, amount); + + uint256 fromBalance = _balances[from]; + require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[from] = fromBalance - amount; + } + _balances[to] += amount; + + emit Transfer(from, to, amount); + + _afterTokenTransfer(from, to, amount); + } + + /** + * @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve(address owner, address spender, uint256 amount) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Updates `owner` s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance amount in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Might emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require(currentAllowance >= amount, "ERC20: insufficient allowance"); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} +} diff --git a/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/IERC20.sol b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/IERC20.sol new file mode 100644 index 00000000..66c4e4d8 --- /dev/null +++ b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/IERC20.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} diff --git a/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol new file mode 100644 index 00000000..83ba6ac5 --- /dev/null +++ b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) + +pragma solidity ^0.8.0; + +import "../IERC20.sol"; + +/** + * @dev Interface for the optional metadata functions from the ERC20 standard. + * + * _Available since v4.1._ + */ +interface IERC20Metadata is IERC20 { + /** + * @dev Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the decimals places of the token. + */ + function decimals() external view returns (uint8); +} diff --git a/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/utils/Context.sol b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/utils/Context.sol new file mode 100644 index 00000000..f304065b --- /dev/null +++ b/examples/transactions/examples/contracts/erc20_example/@openzeppelin/contracts/utils/Context.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } +} diff --git a/examples/transactions/examples/contracts/erc20_example/ERC20Example.sol b/examples/transactions/examples/contracts/erc20_example/ERC20Example.sol new file mode 100644 index 00000000..e2660ac3 --- /dev/null +++ b/examples/transactions/examples/contracts/erc20_example/ERC20Example.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import "./@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract ERC20Example is ERC20 { + constructor() ERC20("ERC20Example", "XYZ") { + _mint(msg.sender, 1000 * 10 ** decimals()); + } +} diff --git a/examples/transactions/examples/decode_input.rs b/examples/transactions/examples/decode_input.rs new file mode 100644 index 00000000..334ee5ff --- /dev/null +++ b/examples/transactions/examples/decode_input.rs @@ -0,0 +1,46 @@ +//! Example of how to decode the input of a transaction. + +use alloy::{primitives::hex, sol, sol_types::SolCall}; +use eyre::Result; + +// Use the sol! macro to generate bindings for the swapExactTokensForTokens function +sol!( + #[derive(Debug)] + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); +); + +#[tokio::main] +async fn main() -> Result<()> { + println!("Decoding https://etherscan.io/tx/0xd1b449d8b1552156957309bffb988924569de34fbf21b51e7af31070cc80fe9a"); + + let input = "0x38ed173900000000000000000000000000000000000000000001a717cc0a3e4f84c00000000000000000000000000000000000000000000000000000000000000283568400000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000201f129111c60401630932d9f9811bd5b5fff34e000000000000000000000000000000000000000000000000000000006227723d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7"; + + let input = hex::decode(input)?; + + // swapExactTokensForTokensCall generated by the sol! macro above + let decoded = swapExactTokensForTokensCall::abi_decode(&input, false); + + match decoded { + Ok(decoded) => { + let path = decoded.path; + println!( + "Swap {} of token {} to {} of token {}", + decoded.amountIn, + path.first().unwrap(), + decoded.amountOutMin, + path.last().unwrap() + ); + } + Err(e) => { + println!("Error decoding input: {:?}", e); + } + } + + Ok(()) +} diff --git a/examples/transactions/examples/gas_price_usd.rs b/examples/transactions/examples/gas_price_usd.rs new file mode 100644 index 00000000..12b41622 --- /dev/null +++ b/examples/transactions/examples/gas_price_usd.rs @@ -0,0 +1,56 @@ +//! Example of how to get the gas price in USD using the Chainlink ETH/USD feed. + +use alloy::{ + network::Ethereum, + node_bindings::Anvil, + primitives::{address, utils::format_units, Address, Bytes, U256}, + providers::{HttpProvider, Provider}, + rpc::types::eth::TransactionRequest, + sol, + sol_types::SolCall, +}; +use eyre::Result; +use std::str::FromStr; + +const ETH_USD_FEED: Address = address!("5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"); +const ETH_DECIMALS: u32 = 18; + +sol!( + #[derive(Debug)] + function latestAnswer() external view returns (int256); +); + +#[tokio::main] +async fn main() -> Result<()> { + let anvil = Anvil::new().fork("https://eth.merkle.io").spawn(); + let url = anvil.endpoint().parse().unwrap(); + let provider = HttpProvider::::new_http(url); + + let call = latestAnswerCall {}.abi_encode(); + let input = Bytes::from(call); + + let tx = TransactionRequest::default().to(Some(ETH_USD_FEED)).input(Some(input).into()); + + let res = provider.call(&tx, None).await?; + + let u = U256::from_str(res.to_string().as_str()); + + let wei_per_gas = provider.get_gas_price().await?; + + let gwei = format_units(wei_per_gas, "gwei")?.parse::()?; + + let usd = usd_value(wei_per_gas, u.unwrap())?; + + println!("Gas price in Gwei: {}", gwei); + println!("Gas price in USD: {}", usd); + + Ok(()) +} + +fn usd_value(amount: U256, price_usd: U256) -> Result { + let base: U256 = U256::from(10).pow(U256::from(ETH_DECIMALS)); + let value: U256 = amount * price_usd / base; + let usd_price_decimals: u8 = 8; + let f: String = format_units(value, usd_price_decimals)?; + Ok(f.parse::()?) +} diff --git a/examples/transactions/examples/trace_call.rs b/examples/transactions/examples/trace_call.rs new file mode 100644 index 00000000..752ea540 --- /dev/null +++ b/examples/transactions/examples/trace_call.rs @@ -0,0 +1,39 @@ +//! Example of how to trace a transaction using `trace_call`. + +use alloy::{ + network::Ethereum, + node_bindings::Anvil, + primitives::U256, + providers::{HttpProvider, Provider}, + rpc::types::{ + eth::{BlockId, BlockNumberOrTag, TransactionRequest}, + trace::parity::TraceType, + }, +}; +use eyre::Result; +use reqwest::Url; + +#[tokio::main] +async fn main() -> Result<()> { + let anvil = Anvil::new().fork("https://eth.merkle.io").spawn(); + let provider = + HttpProvider::::new_http("https://eth.merkle.io".parse::().unwrap()); + + let from = anvil.addresses()[0]; + let to = anvil.addresses()[1]; + + let tx_req = TransactionRequest { + from: Some(from), + to: Some(to), + value: Some(U256::from(100)), + ..Default::default() + }; + let trace_type = [TraceType::Trace]; + let res = provider + .trace_call(&tx_req, &trace_type, Some(BlockId::Number(BlockNumberOrTag::Latest))) + .await?; + + println!("{:?}", res.trace); + + Ok(()) +} diff --git a/examples/transactions/examples/trace_transaction.rs b/examples/transactions/examples/trace_transaction.rs new file mode 100644 index 00000000..5499129d --- /dev/null +++ b/examples/transactions/examples/trace_transaction.rs @@ -0,0 +1,53 @@ +//! Example of how to trace a transaction using `trace_transaction`. + +use alloy::{ + network::Ethereum, + node_bindings::Anvil, + primitives::fixed_bytes, + providers::{HttpProvider, Provider}, + rpc::types::trace::geth::{ + GethDebugBuiltInTracerType, GethDebugTracerType, GethDebugTracingOptions, + GethDefaultTracingOptions, + }, +}; +use eyre::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let anvil = Anvil::new().fork("https://eth.merkle.io").spawn(); + let url = anvil.endpoint().parse().unwrap(); + let provider = HttpProvider::::new_http(url); + let hash = fixed_bytes!("97a02abf405d36939e5b232a5d4ef5206980c5a6661845436058f30600c52df7"); // Hash of the tx we want to trace + + // Default tracing + let default_options = GethDebugTracingOptions::default(); + let res = provider.debug_trace_transaction(hash, default_options).await?; + + println!("DEFAULT_TRACE: {:?}", res); + + // Call tracing + let call_options = GethDebugTracingOptions { + config: GethDefaultTracingOptions { + disable_storage: Some(true), + enable_memory: Some(false), + ..Default::default() + }, + tracer: Some(GethDebugTracerType::BuiltInTracer(GethDebugBuiltInTracerType::CallTracer)), + ..Default::default() + }; + let res = provider.debug_trace_transaction(hash, call_options).await?; + + println!("CALL_TRACE: {:?}", res); + + // JS tracer + let js_options = GethDebugTracingOptions { + tracer: Some(GethDebugTracerType::JsTracer("{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"DELEGATECALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}".into())), + ..Default::default() + }; + + let res = provider.debug_trace_transaction(hash, js_options).await?; + + println!("JS_TRACER: {:?}", res); + + Ok(()) +} diff --git a/examples/transactions/examples/transfer_erc20.rs b/examples/transactions/examples/transfer_erc20.rs new file mode 100644 index 00000000..b030b68a --- /dev/null +++ b/examples/transactions/examples/transfer_erc20.rs @@ -0,0 +1,101 @@ +//! Example of how to transfer ERC20 tokens from one account to another. + +use alloy::{ + network::Ethereum, + node_bindings::Anvil, + primitives::{Address, Bytes, U256}, + providers::{HttpProvider, Provider}, + rpc::types::eth::TransactionRequest, + sol, + sol_types::SolCall, +}; +use eyre::Result; + +sol!(ERC20Example, "examples/contracts/ERC20Example.json"); + +#[tokio::main] +async fn main() -> Result<()> { + let anvil = Anvil::new().fork("https://eth.merkle.io").spawn(); + let url = anvil.endpoint().parse().unwrap(); + let provider = HttpProvider::::new_http(url); + + let from = anvil.addresses()[0]; + + let contract_address = deploy_token_contract(&provider, from).await?; + + println!("Deployed contract at: {}", contract_address); + + let to = anvil.addresses()[1]; + + let input = ERC20Example::transferCall { to, amount: U256::from(100) }.abi_encode(); + // Convert to Bytes + let input = Bytes::from(input); + + let transfer_tx = TransactionRequest { + from: Some(from), + to: Some(contract_address), + input: Some(input).into(), + ..Default::default() + }; + + let pending_tx = provider.send_transaction(transfer_tx).await?; + + println!("Transfer tx: {:?}", pending_tx.tx_hash()); + + // Wait for confirmation + let _ = pending_tx.with_confirmations(1); + + let to_bal = balance_of(&provider, to, contract_address).await?; + let from_bal = balance_of(&provider, from, contract_address).await?; + + assert_eq!(to_bal, U256::from(100)); + assert_eq!(from_bal, U256::from(999999999999999999900_i128)); + + Ok(()) +} + +async fn deploy_token_contract( + provider: &HttpProvider, + from: Address, +) -> Result
{ + // Compile the contract + let bytecode = ERC20Example::BYTECODE.to_owned(); + + let tx_req = TransactionRequest { + from: Some(from), + input: Some(bytecode).into(), + to: None, + ..Default::default() + }; + + // Deploy the contract + let pending_tx = provider.send_transaction(tx_req).await?; + + // Wait for the transaction to be mined + let _tx = provider.get_transaction_by_hash(pending_tx.tx_hash().to_owned()).await?; + + // Get receipt + let receipt = provider.get_transaction_receipt(pending_tx.tx_hash().to_owned()).await?; + + let contract_address = receipt.unwrap().contract_address.unwrap(); + Ok(contract_address) +} + +async fn balance_of( + provider: &HttpProvider, + account: Address, + contract_address: Address, +) -> Result { + let call = ERC20Example::balanceOfCall { account }.abi_encode(); + let input = Bytes::from(call); + + let tx_req = TransactionRequest { + to: Some(contract_address), + input: Some(input).into(), + ..Default::default() + }; + + let result = provider.call(&tx_req, None).await?; + let result = ERC20Example::balanceOfCall::abi_decode_returns(&result, true)?; + Ok(result._0) +} diff --git a/examples/transactions/examples/transfer_eth.rs b/examples/transactions/examples/transfer_eth.rs new file mode 100644 index 00000000..a837af73 --- /dev/null +++ b/examples/transactions/examples/transfer_eth.rs @@ -0,0 +1,33 @@ +//! Example of how to transfer ETH from one account to another. + +use alloy::{ + network::Ethereum, + node_bindings::Anvil, + primitives::{address, Address, U256}, + providers::{HttpProvider, Provider}, + rpc::types::eth::TransactionRequest, +}; +use eyre::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let anvil = Anvil::new().fork("https://eth.merkle.io").spawn(); + let url = anvil.endpoint().parse().unwrap(); + let provider = HttpProvider::::new_http(url); + + let from = anvil.addresses()[0]; + // Transfer 1ETH from 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 to Address::ZERO + let tx = TransactionRequest::default().from(from).value(U256::from(1)).to(Some(Address::ZERO)); + + let tx = provider.send_transaction(tx).await?; + let hash = tx.tx_hash(); + println!("Pending transaction hash: {}", hash); + + let transaction = provider.get_transaction_by_hash(hash.to_owned()).await?; + + assert_eq!(transaction.from, address!("f39fd6e51aad88f6f4ce6ab8827279cfffb92266")); + assert_eq!(transaction.to, Some(Address::ZERO)); + assert_eq!(transaction.value, U256::from(1)); + + Ok(()) +}