From a30f202f7f66130324396f001e45ae8e2ee8beb2 Mon Sep 17 00:00:00 2001 From: Quazia Date: Thu, 13 Jun 2024 11:44:57 -0400 Subject: [PATCH] feat(budget): add quest budget contract and support (#281) --- README.md | 9 + .../11155111/run-1717432982.json | 178 +++ .../11155111/run-1717437866.json | 178 +++ .../11155111/run-1717450347.json | 178 +++ .../11155111/run-1717450764.json | 178 +++ .../11155111/run-latest.json | 178 +++ contracts/QuestBudget.sol | 396 +++++++ contracts/interfaces/IQuestFactory.sol | 20 +- contracts/references/BoostError.sol | 34 + contracts/references/Budget.sol | 142 +++ contracts/references/Cloneable.sol | 42 + contracts/references/Mocks.sol | 74 ++ lib/solady | 2 +- script/QuestBudget.s.sol | 26 + test/QuestBudget.t.sol | 1011 +++++++++++++++++ test/mocks/QuestFactoryMock.sol | 70 ++ 16 files changed, 2714 insertions(+), 2 deletions(-) create mode 100644 broadcast/QuestBudget.s.sol/11155111/run-1717432982.json create mode 100644 broadcast/QuestBudget.s.sol/11155111/run-1717437866.json create mode 100644 broadcast/QuestBudget.s.sol/11155111/run-1717450347.json create mode 100644 broadcast/QuestBudget.s.sol/11155111/run-1717450764.json create mode 100644 broadcast/QuestBudget.s.sol/11155111/run-latest.json create mode 100644 contracts/QuestBudget.sol create mode 100644 contracts/references/BoostError.sol create mode 100644 contracts/references/Budget.sol create mode 100644 contracts/references/Cloneable.sol create mode 100644 contracts/references/Mocks.sol create mode 100644 script/QuestBudget.s.sol create mode 100644 test/QuestBudget.t.sol diff --git a/README.md b/README.md index 0c25f64f..e0b4c3e3 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,13 @@ sed -i '' "s/TEST_CLAIM_SIGNER_PRIVATE_KEY=/TEST_CLAIM_SIGNER_PRIVATE_KEY=0xac09 forge test ``` +### Run a specific test Contract: + +Test QuestBudgetTest contracts: +```bash +forge test --match-contract QuestBudgetTest +``` + ### Run test coverage report: ```bash @@ -167,6 +174,8 @@ If you see something like this `expected error: 0xdd8133e6 != 0xce3f0005` in For 1. Deploy the ProtocolRewards `forge script script/ProtocolRewards.s.sol:ProtocolRewardsDeploy --rpc-url sepolia --broadcast --verify -vvvv` 1. Set any storage variables manually if needed +1. Deploy the QuestBudget +`forge script script/QuestBudget.s.sol:QuestBudgetDeploy --rpc-url sepolia --broadcast --verify -vvvv` ### with mantel, add: diff --git a/broadcast/QuestBudget.s.sol/11155111/run-1717432982.json b/broadcast/QuestBudget.s.sol/11155111/run-1717432982.json new file mode 100644 index 00000000..1c8d101a --- /dev/null +++ b/broadcast/QuestBudget.s.sol/11155111/run-1717432982.json @@ -0,0 +1,178 @@ +{ + "transactions": [ + { + "hash": "0x2bbe866c2a8747925d91f146337b921a9d0172d4c70383a7bb21dc614f4311f2", + "transactionType": "CREATE", + "contractName": "QuestBudget", + "contractAddress": "0xf995FC2DFd2D296Afa43CC1A71db1F2aee3f6f3d", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x25cbf6", + "value": "0x0", + "data": "0x608080604052346100b95733638b78c6d819553360007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a363409feecd19805490600182166100ab576001600160401b039160011c6002600160401b031901610071575b6120a683816100bf8239f35b6002600160411b03905560209081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29080a13880610065565b63f92ee8a96000526004601cfd5b600080fdfe608060408181526004918236101561001f575b505050361561001d57005b005b600092833560e01c91826301ffc9a714610ded5750816310098ad514610dc75781631c9fd0c314610d7d5781632569296214610d325781634359d28a14610c46578163439fab9114610a24578163451cc191146109e957816354d1f13d146109a3578163578bcf351461096c5781635aef467a1461093357816361400c99146108f5578163627bbbaa14610889578163715018a614610843578163774c33ab14610803578163825677fc146107de5781638da5cb5b146107b257816392f5e0eb1461078c578163bc197c81146106e9578163d2514e84146106a5578163de0580dc146104ab578163f04e283e1461042b578163f1c30ec0146103e5578163f23a6e6114610375578163f2fde38b14610307578163f8724aba146102de578163f9a802c314610213578163fa4ca9b1146101d257508063fe9fbb80146101a45763fee81cf41461016e5780610012565b346101a05760203660031901126101a05760209161018a610ef1565b9063389a75e1600c525281600c20549051908152f35b5080fd5b50346101a05760203660031901126101a0576020906101c96101c4610ef1565b611f47565b90519015158152f35b8284346102105760203660031901126102105782359067ffffffffffffffff8211610210575061020a6020936101c992369101610f67565b906119ea565b80fd5b82843461021057816003193601126102105761022d610ef1565b8251627eeac760e11b8152309481019485526024356020868101829052956001600160a01b039093169391928690849081906040010381875afa9283156102d45790829186939461029b575b50610294948252600287528282209082528652205490611f7e565b9051908152f35b91935091508581813d81116102cd575b6102b58183610fdb565b810103126102c95751918491610294610279565b8280fd5b503d6102ab565b85513d84823e3d90fd5b5050346101a057806003193601126101a0576020906102946102fe610ef1565b60243590611fa9565b839060203660031901126101a05761031d610ef1565b90610326612024565b8160601b1561036a57506001600160a01b0316638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08580a35580f35b637448fbae8352601cfd5b8284346102105760a036600319011261021057610390610ef1565b50610399610f0c565b506084359067ffffffffffffffff821161021057506020926103bd91369101610f67565b5050517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b8284346102105760203660031901126102105782359067ffffffffffffffff8211610210575061041d6020936101c992369101610f67565b90610426612024565b61157c565b83602036600319011261021057610440610ef1565b610448612024565b63389a75e1600c528082526020600c2092835442116104a05750816001600160a01b0392935516638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08580a35580f35b636f5e88188352601cfd5b839150346101a05760031992610160368501811361066d57823563ffffffff81168091036106a1576104db610f0c565b9367ffffffffffffffff60c43581811161069d576104fc9036908401611050565b9760e435828111610699576105149036908501611050565b9161010480358281116106955761052e9036908701611050565b90610124928335908111610691576105499036908801611050565b9461055333611f47565b15610683578b9c6001600160a01b039c9b9c809c5416998c8c519e8f9b8c9b7fde0580dc000000000000000000000000000000000000000000000000000000008d528c01521660248a015260443560448a015260643560648a015260843560848a015260a43560a48a015260c489015261016488016105d1916111ee565b858882030160e48901526105e4916111ee565b908487830301908701526105f7916111ee565b918483030190840152610609916111ee565b6101448035908301520381875a94602095f1928315610679578493610635575b50602093505191168152f35b9092506020813d8211610671575b8161065060209383610fdb565b8101031261066d5751818116810361066d57602093509184610629565b8380fd5b3d9150610643565b81513d86823e3d90fd5b868a516282b42960e81b8152fd5b8b80fd5b8a80fd5b8880fd5b8780fd5b8480fd5b5050346101a05760203660031901126101a057610294602092826106c7610ef1565b916001600160a01b036106d984611f8b565b9316815260018652205490611f7e565b8284346102105760a036600319011261021057610704610ef1565b5061070d610f0c565b5067ffffffffffffffff906044358281116101a05761072f9036908601610f36565b50506064358281116101a0576107489036908601610f36565b5050608435918211610210575060209261076491369101610f67565b5050517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b5050346101a057816003193601126101a0576001600160a01b0360209254169051908152f35b5050346101a057816003193601126101a0576020906001600160a01b03638b78c6d81954915191168152f35b5050346101a057816003193601126101a05760ff6020925460a01c1690519015158152f35b5050346101a057806003193601126101a057806020926001600160a01b03610829610ef1565b168152600284528181206024358252845220549051908152f35b838060031936011261021057610857612024565b80638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35580f35b8390346101a05760203660031901126101a057358015158091036101a0576108af612024565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000083549260a01b16911617815580f35b8284346102105760203660031901126102105782359067ffffffffffffffff8211610210575061092d6020936101c992369101610f36565b90611eb5565b828460203660031901126102105782359067ffffffffffffffff821161021057506109666020936101c992369101610f67565b90611277565b5050346101a05760203660031901126101a057806020926001600160a01b03610993610ef1565b1681526001845220549051908152f35b83806003193601126102105763389a75e1600c52338152806020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c928280a280f35b8383346101a05760203660031901126101a057823567ffffffffffffffff81116102c957602093610a1c91369101610f67565b505051908152f35b8383346101a057602091826003193601126102105767ffffffffffffffff9284358481116102c957610a599036908701610f67565b919063409feecd199687549360039480868b55610c1e575b508201918381840312610c1657803590888211610c1a570191606083820312610c1657865190610aa082610f95565b610aa984610f22565b8252610ab6858501610f22565b9385830194855288810135908a821161069957019281601f8501121561069d578335998a11610c03575060059289841b9089519a610af68884018d610fdb565b8b5286808c01928201019283116106995786809101915b838310610beb57505050508681019788526001600160a01b0392838092511680638b78c6d81955877f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3511673ffffffffffffffffffffffffffffffffffffffff19865416178555845b87518051821015610bae5781831b0184015183168652848452868620805460ff19166001179055610ba99061106e565b610b79565b868a8681610bba578280f35b60027fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d292556001815280a181808280f35b8190610bf684610f22565b8152019101908690610b0d565b876041602492634e487b7160e01b835252fd5b8580fd5b8680fd5b600181819b939b1c14303b1015610c3a5760ff1b1b9789610a71565b8263f92ee8a98852601cfd5b919050346102c957806003193601126102c95767ffffffffffffffff9082358281116106a157610c799036908501610f36565b9092602435908111610c1657610c929036908601610f36565b9094610c9c612024565b818303610d0b5750855b828110610cb1578680f35b610cbc818388611f21565b359081151580920361069d57610cd3818588611f21565b35916001600160a01b03831680930361069957610d0692895260036020528589209060ff8019835416911617905561106e565b610ca6565b83517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b83806003193601126102105763389a75e1600c523381526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d8280a280f35b8334610210576020366003190112610210576001600160a01b03610d9f610ef1565b610da7612024565b1673ffffffffffffffffffffffffffffffffffffffff1982541617815580f35b5050346101a05760203660031901126101a057602090610294610de8610ef1565b611f8b565b8491346102c95760203660031901126102c957357fffffffff0000000000000000000000000000000000000000000000000000000081168091036102c957602092507f4e2312e0000000000000000000000000000000000000000000000000000000008114908115610e61575b5015158152f35b7f5cd687ca00000000000000000000000000000000000000000000000000000000811491508115610e94575b5083610e5a565b7f4260623600000000000000000000000000000000000000000000000000000000811491508115610ec7575b5083610e8d565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610ec0565b600435906001600160a01b0382168203610f0757565b600080fd5b602435906001600160a01b0382168203610f0757565b35906001600160a01b0382168203610f0757565b9181601f84011215610f075782359167ffffffffffffffff8311610f07576020808501948460051b010111610f0757565b9181601f84011215610f075782359167ffffffffffffffff8311610f075760208381860195010111610f0757565b6060810190811067ffffffffffffffff821117610fb157604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff8111610fb157604052565b90601f8019910116810190811067ffffffffffffffff821117610fb157604052565b67ffffffffffffffff8111610fb157601f01601f191660200190565b92919261102582610ffd565b916110336040519384610fdb565b829481845281830111610f07578281602093846000960137010152565b9080601f83011215610f075781602061106b93359101611019565b90565b600019811461107d5760010190565b634e487b7160e01b600052601160045260246000fd5b90602082820312610f0757813567ffffffffffffffff92838211610f07570191608083830312610f0757604051926080840184811083821117610fb15760405280356003811015610f075784526110ec60208201610f22565b60208501526110fd60408201610f22565b60408501526060810135918211610f0757019080601f83011215610f075781602061112a93359101611019565b606082015290565b60005b8381106111455750506000910152565b8181015183820152602001611135565b9060208083830312610f0757825167ffffffffffffffff93848211610f07570192606084840312610f07576040519361118d85610f95565b8051855282810151838601526040810151918211610f07570182601f82011215610f07578051906111bd82610ffd565b936111cb6040519586610fdb565b828552838383010111610f0757826111e69385019101611132565b604082015290565b9060209161120781518092818552858086019101611132565b601f01601f1916010190565b919261106b95949160a0946001600160a01b0380921685521660208401526040830152606082015281608082015201906111ee565b90816020910312610f0757604051906020820182811067ffffffffffffffff821117610fb15760405251815290565b61128391810190611093565b80516000906003811015611568576112ef57506112ad606082015160208082518301019101611248565b51908134036112bd575050600190565b6020015160405163cece04c560e01b81526001600160a01b0390911660048201526024810191909152604490fd5b0390fd5b81516003811015611568576001036113e657611318606083015160208082518301019101611248565b9160208101906001600160a01b03926020816064601c82604089895116970151968a519760405198606052306040526bffffffffffffffffffffffff199060601b16602c526f23b872dd000000000000000000000000600c525af13d1560018351141716156113d9576060526040526113943083835116612041565b92518093106113a557505050600190565b51166112eb60405192839263cece04c560e01b845260048401602090939291936001600160a01b0360408201951681520152565b637939f42490526004601cfd5b908051600381101561155457600203611550576060810151611412602091828082518301019101611155565b818301906001600160a01b0392838351169184604080970151168151838301948551918985015193823b1561069157908b809493926114688d5197889687958694637921219560e11b8652309060048701611213565b03925af180156115465761152d575b50835190518651627eeac760e11b8152306004820152602481019190915291908190839087168180604481015b03915afa96871561152257966114f2575b5050518094106114c85750505050600190565b51915163cece04c560e01b815291166001600160a01b031660048201526024810191909152604490fd5b9080929650813d831161151b575b61150a8183610fdb565b81010312610f0757519338806114b5565b503d611500565b8651903d90823e3d90fd5b9180919761153d6114a494610fc7565b97919250611477565b87513d8a823e3d90fd5b5090565b602483634e487b7160e01b81526021600452fd5b602482634e487b7160e01b81526021600452fd5b61158891810190611093565b805160038110156119c0571580156119d6575b1561178e576115b7606082015160208082518301019101611248565b906001600160a01b03604081602084015116920151169151801560001461178857506115e281611f8b565b915b68929eee149b4bd21268923084541461177a57308455811561174a5761160983611f8b565b8111611709578260005260016020526040600020611628828254611f7e565b90558261169857600038818084865af11561168a577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542915b604080516001600160a01b039092168252602082019290925290819081015b0390a2389055600190565b63b12d13eb6000526004601cfd5b81601452806034526fa9059cbb000000000000000000000000600052602060006044601082875af13d156001600051141716156116fb577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542916000603452611660565b6390b8ec186000526004601cfd5b826112eb61171682611f8b565b92604051938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b6040516317e3057d60e31b81526001600160a01b0384811660048301529290921660248301526044820152606490fd5b63ab143c066000526004601cfd5b916115e4565b805160038110156119c0576002036119ba576060810151906117ba602092838082518301019101611155565b6001600160a01b03918284820151169260408092015116908251818685015180156000146119b4575051627eeac760e11b8152306004820152602481018290528681604481895afa9081156119a957908391600091611979575b50945b01519068929eee149b4bd21268963088541461177a57308855841561194a576118408288611fa9565b86116119085786600052600281528360002090826000525282600020611867868254611f7e565b9055853b15610f07578460009161189385519485938493637921219560e11b8552893060048701611213565b038183895af180156118fd579161167f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429594936118ee575b505192839283602090939291936001600160a01b0360408201951681520152565b6118f790610fc7565b386118cd565b82513d6000823e3d90fd5b83876112eb886119188684611fa9565b9351938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b83516317e3057d60e31b81526001600160a01b0388811660048301528616602482015260448101879052606490fd5b91508782813d83116119a2575b6119908183610fdb565b81010312610210575082905138611814565b503d611986565b83513d6000823e3d90fd5b94611817565b50600090565b634e487b7160e01b600052602160045260246000fd5b50805160038110156119c05760011461159b565b906119f433611f47565b15611a025761106b91611a12565b60046040516282b42960e81b8152fd5b9060009160ff835460a01c1615611a0257611a2f91810190611093565b80516003811015611554576001148015611ea3575b15611c2557611a60606082015160208082518301019101611248565b602082016001600160a01b0390611a7982825116611f8b565b8351818111611bf35750508160409151169301511690519068929eee149b4bd212689330855414611be6573085558115611bb357611ab684611f8b565b8311611ba557838152600160205260408120611ad3848254611f7e565b905583611b39578038818086865af115611b2c5750604080516001600160a01b03909216825260208201929092527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542918190810161167f565b63b12d13eb90526004601cfd5b81601452826034526fa9059cbb00000000000000000000000081526020816044601082885af13d156001835114171615611b98576034527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429190611660565b6390b8ec1890526004601cfd5b82846112eb61171682611f8b565b506040516317e3057d60e31b81526001600160a01b03848116600483015291909116602482015260448101829052606490fd5b63ab143c0690526004601cfd5b8251604051632e2a182f60e11b81529085166001600160a01b0316600482015260248101929092526044820152606490fd5b805160038110156115545760020361155057606081015191611c51602093848082518301019101611155565b908383016001600160a01b039182825116908451936040938885518095627eeac760e11b82528180611c9e60049b308d8401602090939291936001600160a01b0360408201951681520152565b03915afa938415611e99578394611e6a575b5088870193845190808211611e2f57505081859151169701511693838651935196015168929eee149b4bd2126898308a5414611e2357308a558615611dee57611cf9858a611fa9565b8811611dae57888452600281528584209085855252848320611d1c888254611f7e565b9055873b156102c9578291611d4787928988519788958695637921219560e11b875230908701611213565b0381838a5af1908115611da357509161167f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429594936118ee57505192839283602090939291936001600160a01b0360408201951681520152565b8351903d90823e3d90fd5b88836112eb8a89611dbf8a86611fa9565b9051632e2a182f60e11b81526001600160a01b0390951693850193845260208401526040830152829160600190565b85516317e3057d60e31b81526001600160a01b03808b168286019081529089166020820152604081018a905281906060010390fd5b8263ab143c068552601cfd5b86945087936112eb9351169451948594632e2a182f60e11b865285016040919493926001600160a01b03606083019616825260208201520152565b9093508881813d8311611e92575b611e828183610fdb565b810103126102c957519238611cb0565b503d611e78565b85513d85823e3d90fd5b50805160038110156115545715611a44565b60005b828110611ec757505050600190565b8060051b820135601e1983360301811215610f0757820180359067ffffffffffffffff8211610f0757602001908036038213610f0757611f06916119ea565b15611f1957611f149061106e565b611eb8565b505050600090565b9190811015611f315760051b0190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0380911680600052600360205260ff60406000205416918215611f7057505090565b638b78c6d819541614919050565b9190820180921161107d57565b6001600160a01b038116611f9e57504790565b61106b903090612041565b604051627eeac760e11b81523060048201526024810192909252602090829060449082906001600160a01b03165afa90811561201857600091611fea575090565b906020823d8211612010575b8161200360209383610fdb565b8101031261021057505190565b3d9150611ff6565b6040513d6000823e3d90fd5b638b78c6d81954330361203357565b6382b429006000526004601cfd5b602460106020939284936014526f70a082310000000000000000000000006000525afa601f3d1116602051029056fea264697066735822122072d20eaaedb23a82898c30e7b29d23fd51d9c4f6b5b01a0a5c13c1c1498abc8f64736f6c63430008130033", + "nonce": "0xa9", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe7bc407fdf6dad795cd7765a56d9c9cbc5728d603f0a9e685dd30099e5854d19", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0xf59DE11783a631c0BA9f174C872469aC01c69531", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x13e46", + "value": "0x0", + "data": "0x602c3d8160093d39f33d3d3d3d363d3d37363d73f995fc2dfd2d296afa43cc1a71db1f2aee3f6f3d5af43d3d93803e602a57fd5bf3", + "nonce": "0xaa", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe06e7205c8ec086378df14496c8ec9f18b44f6a7de5b8fd6c4ec1b814641be06", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0xf59DE11783a631c0BA9f174C872469aC01c69531", + "function": "initialize(bytes)", + "arguments": [ + "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c00000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c" + ], + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "to": "0xf59de11783a631c0ba9f174c872469ac01c69531", + "gas": "0x27e86", + "value": "0x0", + "data": "0x439fab91000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c00000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c", + "nonce": "0xab", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0x2bbe866c2a8747925d91f146337b921a9d0172d4c70383a7bb21dc614f4311f2", + "transactionIndex": "0xe", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x307819", + "gasUsed": "0x1d1524", + "contractAddress": "0xf995FC2DFd2D296Afa43CC1A71db1F2aee3f6f3d", + "logs": [ + { + "address": "0xf995FC2DFd2D296Afa43CC1A71db1F2aee3f6f3d", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "transactionHash": "0x2bbe866c2a8747925d91f146337b921a9d0172d4c70383a7bb21dc614f4311f2", + "transactionIndex": "0xe", + "logIndex": "0xb", + "removed": false + }, + { + "address": "0xf995FC2DFd2D296Afa43CC1A71db1F2aee3f6f3d", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "transactionHash": "0x2bbe866c2a8747925d91f146337b921a9d0172d4c70383a7bb21dc614f4311f2", + "transactionIndex": "0xe", + "logIndex": "0xc", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000010000000000000000000000000000000000804000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000004000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x1f9235b9e" + }, + { + "transactionHash": "0xe7bc407fdf6dad795cd7765a56d9c9cbc5728d603f0a9e685dd30099e5854d19", + "transactionIndex": "0xf", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x316cf1", + "gasUsed": "0xf4d8", + "contractAddress": "0xf59DE11783a631c0BA9f174C872469aC01c69531", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x1f9235b9e" + }, + { + "transactionHash": "0xe06e7205c8ec086378df14496c8ec9f18b44f6a7de5b8fd6c4ec1b814641be06", + "transactionIndex": "0x10", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": "0xf59DE11783a631c0BA9f174C872469aC01c69531", + "cumulativeGasUsed": "0x333b39", + "gasUsed": "0x1ce48", + "contractAddress": null, + "logs": [ + { + "address": "0xf59DE11783a631c0BA9f174C872469aC01c69531", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c" + ], + "data": "0x", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "transactionHash": "0xe06e7205c8ec086378df14496c8ec9f18b44f6a7de5b8fd6c4ec1b814641be06", + "transactionIndex": "0x10", + "logIndex": "0xd", + "removed": false + }, + { + "address": "0xf59DE11783a631c0BA9f174C872469aC01c69531", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x0e9b44b38b8a136468d6563ccdfbf4d2826f6c22062a269a1ec3df242431f23b", + "blockNumber": "0x5c0cb1", + "transactionHash": "0xe06e7205c8ec086378df14496c8ec9f18b44f6a7de5b8fd6c4ec1b814641be06", + "transactionIndex": "0x10", + "logIndex": "0xe", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000400000000000000000000000000000002000000000000000000000000000000000000000400000000000001000000000000000000000000000000000000020000000000000000000800200000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000100000004000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x1f9235b9e" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1717432982, + "chain": 11155111, + "commit": "ad4bf2e" +} \ No newline at end of file diff --git a/broadcast/QuestBudget.s.sol/11155111/run-1717437866.json b/broadcast/QuestBudget.s.sol/11155111/run-1717437866.json new file mode 100644 index 00000000..5e27d237 --- /dev/null +++ b/broadcast/QuestBudget.s.sol/11155111/run-1717437866.json @@ -0,0 +1,178 @@ +{ + "transactions": [ + { + "hash": "0xd287327909739b467e2a4e6af08abff214a9f1d3aaaa22843a53601bff794e4e", + "transactionType": "CREATE", + "contractName": "QuestBudget", + "contractAddress": "0x5D8AA745C4b35Fb46AF555a6FcD464946e9FD9D9", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x25fe93", + "value": "0x0", + "data": "0x608080604052346100b95733638b78c6d819553360007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a363409feecd19805490600182166100ab576001600160401b039160011c6002600160401b031901610071575b6120da83816100bf8239f35b6002600160411b03905560209081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29080a13880610065565b63f92ee8a96000526004601cfd5b600080fdfe608080604052600436101561001a575b50361561001857005b005b60003560e01c90816301ffc9a714610e525750806310098ad514610e2f57806319cbad0614610e095780631c9fd0c314610dbc5780632569296214610d705780634359d28a14610c7f578063439fab9114610a5e578063451cc19114610a2057806354d1f13d146109d8578063578bcf351461099e5780635aef467a1461096757806361400c991461092b578063627bbbaa146108bb578063715018a614610875578063774c33ab1461082d5780638da5cb5b1461080257806392f5e0eb146107db578063bc197c8114610737578063d2514e84146106f3578063de0580dc14610491578063f04e283e1461040f578063f1c30ec0146103cb578063f23a6e611461035c578063f2fde38b146102ef578063f8724aba146102c8578063f9a802c314610207578063fa4ca9b1146101cb578063fe9fbb801461019e5763fee81cf414610166573861000f565b346101995760203660031901126101995761017f610f56565b63389a75e1600c52600052602080600c2054604051908152f35b600080fd5b346101995760203660031901126101995760206101c16101bc610f56565b611f87565b6040519015158152f35b346101995760203660031901126101995760043567ffffffffffffffff8111610199576101c16102016020923690600401610fc7565b90611a3b565b3461019957604036600319011261019957610220610f56565b604051627eeac760e11b8152306004820152602480359082018190526020926001600160a01b0316908383604481855afa9182156102bc5760009261028b575b610283935060005260028452604060002090600052835260406000205490611fbe565b604051908152f35b91508383813d83116102b5575b6102a28183611025565b8101031261019957610283925191610260565b503d610298565b6040513d6000823e3d90fd5b346101995760403660031901126101995760206102836102e6610f56565b60243590611fe9565b602036600319011261019957610303610f56565b61030b612058565b8060601b1561034e576001600160a01b0316638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355005b637448fbae6000526004601cfd5b346101995760a036600319011261019957610375610f56565b5061037e610f6c565b5060843567ffffffffffffffff81116101995761039f903690600401610fc7565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b346101995760203660031901126101995760043567ffffffffffffffff8111610199576101c16104016020923690600401610fc7565b9061040a612058565b6115ca565b602036600319011261019957610423610f56565b61042b612058565b63389a75e1600c52806000526020600c2090815442116104835760006001600160a01b03925516638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355005b636f5e88186000526004601cfd5b34610199576101603660031901126101995760043563ffffffff81168103610199576104bb610f6c565b67ffffffffffffffff9060c435828111610199576104dd90369060040161109a565b60e435838111610199576104f590369060040161109a565b610104358481116101995761050e90369060040161109a565b93610124359081116101995761052890369060040161109a565b9061053233611f87565b156106c9576001600160a01b036000541660145260a4356034526f095ea7b3000000000000000000000000600052602060006044601082885af13d156001600051141716156106bb576001600160a01b039561064963ffffffff93610636602098610623600096876034526106118d8954169a6040519e8f9d8e9c8d9b7fde0580dc000000000000000000000000000000000000000000000000000000008d521660048c01521660248a015260443560448a015260643560648a015260843560848a015260a43560a48a015261016060c48a0152610164890190611238565b8781036003190160e489015290611238565b8581036003190161010487015290611238565b8381036003190161012485015290611238565b61014480359083015203925af180156102bc57600090610678575b6020906001600160a01b0360405191168152f35b506020813d6020116106b3575b8161069260209383611025565b8101031261019957516001600160a01b038116810361019957602090610664565b3d9150610685565b633e3f8f736000526004601cfd5b60046040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b34610199576020366003190112610199576020610283610711610f56565b6001600160a01b0361072282611fcb565b91166000526001835260406000205490611fbe565b346101995760a036600319011261019957610750610f56565b50610759610f6c565b5067ffffffffffffffff6044358181116101995761077b903690600401610f96565b505060643581811161019957610795903690600401610f96565b5050608435908111610199576107af903690600401610fc7565b505060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b346101995760003660031901126101995760206001600160a01b0360005416604051908152f35b34610199576000366003190112610199576020638b78c6d819546001600160a01b0360405191168152f35b34610199576040366003190112610199576001600160a01b0361084e610f56565b16600052600260205260406000206024356000526020526020604060002054604051908152f35b600036600319011261019957610889612058565b6000638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a355005b3461019957602036600319011261019957600435801515809103610199576108e1612058565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006000549260a01b16911617600055600080f35b346101995760203660031901126101995760043567ffffffffffffffff8111610199576101c16109616020923690600401610f96565b90611ef5565b60203660031901126101995760043567ffffffffffffffff8111610199576101c16109986020923690600401610fc7565b906112c1565b34610199576020366003190112610199576001600160a01b036109bf610f56565b1660005260016020526020604060002054604051908152f35b60003660031901126101995763389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2005b346101995760203660031901126101995760043567ffffffffffffffff811161019957610a51903690600401610fc7565b5050602060405160008152f35b34610199576020806003193601126101995767ffffffffffffffff60043581811161019957610a91903690600401610fc7565b909263409feecd199384549260039380858855610c55575b5081019082818303126101995780359085821161019957019060608282031261019957604051610ad881610ff5565b610ae183610f82565b8152610aee848401610f82565b9284820193845260408101359087821161019957019180601f84011215610199578235968711610c3f5760059287841b9060405198610b2f8884018b611025565b895286808a01928201019283116101995786809101915b838310610c275750505050604081019586526001600160a01b0392838092511680638b78c6d8195560007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3511673ffffffffffffffffffffffffffffffffffffffff19600054161760005560005b8551878151831015610bf25750908385610bed9383861b010151166000528585526040600020600160ff198254161790556110b8565b610bb7565b8581610bfa57005b60027fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d292556001815280a1005b8190610c3284610f82565b8152019101908690610b46565b634e487b7160e01b600052604160045260246000fd5b600181819893981c14303b1015610c715760ff1b1b9486610aa9565b63f92ee8a96000526004601cfd5b346101995760403660031901126101995767ffffffffffffffff60043581811161019957610cb1903690600401610f96565b909160243590811161019957610ccb903690600401610f96565b610cd6929192612058565b808203610d465760005b828110610ce957005b610cf4818386611f61565b359081151580920361019957610d0b818588611f61565b35916001600160a01b03831680930361019957610d4192600052600360205260406000209060ff801983541691161790556110b8565b610ce0565b60046040517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b60003660031901126101995763389a75e1600c52336000526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a2005b34610199576020366003190112610199576001600160a01b03610ddd610f56565b610de5612058565b1673ffffffffffffffffffffffffffffffffffffffff196000541617600055600080f35b3461019957600036600319011261019957602060ff60005460a01c166040519015158152f35b34610199576020366003190112610199576020610283610e4d610f56565b611fcb565b3461019957602036600319011261019957600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361019957817f4e2312e00000000000000000000000000000000000000000000000000000000060209314908115610ec6575b5015158152f35b7f5cd687ca00000000000000000000000000000000000000000000000000000000811491508115610ef9575b5083610ebf565b7f4260623600000000000000000000000000000000000000000000000000000000811491508115610f2c575b5083610ef2565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501483610f25565b600435906001600160a01b038216820361019957565b602435906001600160a01b038216820361019957565b35906001600160a01b038216820361019957565b9181601f840112156101995782359167ffffffffffffffff8311610199576020808501948460051b01011161019957565b9181601f840112156101995782359167ffffffffffffffff8311610199576020838186019501011161019957565b6060810190811067ffffffffffffffff821117610c3f57604052565b67ffffffffffffffff8111610c3f57604052565b90601f8019910116810190811067ffffffffffffffff821117610c3f57604052565b67ffffffffffffffff8111610c3f57601f01601f191660200190565b92919261106f82611047565b9161107d6040519384611025565b829481845281830111610199578281602093846000960137010152565b9080601f83011215610199578160206110b593359101611063565b90565b60001981146110c75760010190565b634e487b7160e01b600052601160045260246000fd5b9060208282031261019957813567ffffffffffffffff9283821161019957019160808383031261019957604051926080840184811083821117610c3f576040528035600381101561019957845261113660208201610f82565b602085015261114760408201610f82565b6040850152606081013591821161019957019080601f830112156101995781602061117493359101611063565b606082015290565b60005b83811061118f5750506000910152565b818101518382015260200161117f565b906020808383031261019957825167ffffffffffffffff9384821161019957019260608484031261019957604051936111d785610ff5565b8051855282810151838601526040810151918211610199570182601f820112156101995780519061120782611047565b936112156040519586611025565b8285528383830101116101995782611230938501910161117c565b604082015290565b906020916112518151809281855285808601910161117c565b601f01601f1916010190565b91926110b595949160a0946001600160a01b038092168552166020840152604083015260608201528160808201520190611238565b9081602091031261019957604051906020820182811067ffffffffffffffff821117610c3f5760405251815290565b6112cd918101906110dd565b805160009060038110156115b65761133957506112f7606082015160208082518301019101611292565b5190813403611307575050600190565b6020015160405163cece04c560e01b81526001600160a01b0390911660048201526024810191909152604490fd5b0390fd5b815160038110156115b65760010361143057611362606083015160208082518301019101611292565b9160208101906001600160a01b03926020816064601c82604089895116970151968a519760405198606052306040526bffffffffffffffffffffffff199060601b16602c526f23b872dd000000000000000000000000600c525af13d156001835114171615611423576060526040526113de3083835116612075565b92518093106113ef57505050600190565b511661133560405192839263cece04c560e01b845260048401602090939291936001600160a01b0360408201951681520152565b637939f42490526004601cfd5b90805160038110156115a25760020361159e57606081015161145c60209182808251830101910161119f565b818301906001600160a01b0392838351169184604080970151168151838301948551918985015193823b1561159a57908b809493926114b28d5197889687958694637921219560e11b865230906004870161125d565b03925af1801561159057611577575b50835190518651627eeac760e11b8152306004820152602481019190915291908190839087168180604481015b03915afa96871561156c579661153c575b5050518094106115125750505050600190565b51915163cece04c560e01b815291166001600160a01b031660048201526024810191909152604490fd5b9080929650813d8311611565575b6115548183611025565b8101031261019957519338806114ff565b503d61154a565b8651903d90823e3d90fd5b918091976115876114ee94611011565b979192506114c1565b87513d8a823e3d90fd5b8b80fd5b5090565b602483634e487b7160e01b81526021600452fd5b602482634e487b7160e01b81526021600452fd5b6115d6918101906110dd565b80516003811015611a1157158015611a27575b156117dc57611605606082015160208082518301019101611292565b906001600160a01b0360408160208401511692015116915180156000146117d6575061163081611fcb565b915b68929eee149b4bd2126892308454146117c85730845581156117985761165783611fcb565b8111611757578260005260016020526040600020611676828254611fbe565b9055826116e657600038818084865af1156116d8577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542915b604080516001600160a01b039092168252602082019290925290819081015b0390a2389055600190565b63b12d13eb6000526004601cfd5b81601452806034526fa9059cbb000000000000000000000000600052602060006044601082875af13d15600160005114171615611749577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429160006034526116ae565b6390b8ec186000526004601cfd5b8261133561176482611fcb565b92604051938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b6040516317e3057d60e31b81526001600160a01b0384811660048301529290921660248301526044820152606490fd5b63ab143c066000526004601cfd5b91611632565b80516003811015611a1157600203611a0b5760608101519061180860209283808251830101910161119f565b6001600160a01b0391828482015116926040809201511690825181868501518015600014611a05575051627eeac760e11b8152306004820152602481018290528681604481895afa9081156119fa579083916000916119c7575b50945b01519068929eee149b4bd2126896308854146117c85730885584156119985761188e8288611fe9565b861161195657866000526002815283600020908260005252826000206118b5868254611fbe565b9055853b1561019957846000916118e185519485938493637921219560e11b855289306004870161125d565b038183895af1801561194b57916116cd917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd4354295949361193c575b505192839283602090939291936001600160a01b0360408201951681520152565b61194590611011565b3861191b565b82513d6000823e3d90fd5b8387611335886119668684611fe9565b9351938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b83516317e3057d60e31b81526001600160a01b0388811660048301528616602482015260448101879052606490fd5b91508782813d83116119f3575b6119de8183611025565b810103126119f0575082905138611862565b80fd5b503d6119d4565b83513d6000823e3d90fd5b94611865565b50600090565b634e487b7160e01b600052602160045260246000fd5b5080516003811015611a11576001146115e9565b90611a4533611f87565b156106c9576110b5919060009160ff835460a01c16156106c957611a6b918101906110dd565b805160038110156115a2576001148015611ee3575b15611c6157611a9c606082015160208082518301019101611292565b602082016001600160a01b0390611ab582825116611fcb565b8351818111611c2f5750508160409151169301511690519068929eee149b4bd212689330855414611c22573085558115611bef57611af284611fcb565b8311611be157838152600160205260408120611b0f848254611fbe565b905583611b75578038818086865af115611b685750604080516001600160a01b03909216825260208201929092527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd4354291819081016116cd565b63b12d13eb90526004601cfd5b81601452826034526fa9059cbb00000000000000000000000081526020816044601082885af13d156001835114171615611bd4576034527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd4354291906116ae565b6390b8ec1890526004601cfd5b828461133561176482611fcb565b506040516317e3057d60e31b81526001600160a01b03848116600483015291909116602482015260448101829052606490fd5b63ab143c0690526004601cfd5b8251604051632e2a182f60e11b81529085166001600160a01b0316600482015260248101929092526044820152606490fd5b805160038110156115a25760020361159e57606081015191611c8d60209384808251830101910161119f565b908383016001600160a01b039182825116908451936040938885518095627eeac760e11b82528180611cda60049b308d8401602090939291936001600160a01b0360408201951681520152565b03915afa938415611ed9578394611eaa575b5088870193845190808211611e6f57505081859151169701511693838651935196015168929eee149b4bd2126898308a5414611e6357308a558615611e2e57611d35858a611fe9565b8811611dee57888452600281528584209085855252848320611d58888254611fbe565b9055873b15611dea578291611d8387928988519788958695637921219560e11b87523090870161125d565b0381838a5af1908115611ddf5750916116cd917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd4354295949361193c57505192839283602090939291936001600160a01b0360408201951681520152565b8351903d90823e3d90fd5b8280fd5b88836113358a89611dff8a86611fe9565b9051632e2a182f60e11b81526001600160a01b0390951693850193845260208401526040830152829160600190565b85516317e3057d60e31b81526001600160a01b03808b168286019081529089166020820152604081018a905281906060010390fd5b8263ab143c068552601cfd5b86945087936113359351169451948594632e2a182f60e11b865285016040919493926001600160a01b03606083019616825260208201520152565b9093508881813d8311611ed2575b611ec28183611025565b81010312611dea57519238611cec565b503d611eb8565b85513d85823e3d90fd5b50805160038110156115a25715611a80565b60005b828110611f0757505050600190565b8060051b820135601e198336030181121561019957820180359067ffffffffffffffff82116101995760200190803603821361019957611f4691611a3b565b15611f5957611f54906110b8565b611ef8565b505050600090565b9190811015611f715760051b0190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0380911680600052600360205260ff60406000205416918215611fb057505090565b638b78c6d819541614919050565b919082018092116110c757565b6001600160a01b038116611fde57504790565b6110b5903090612075565b604051627eeac760e11b81523060048201526024810192909252602090829060449082906001600160a01b03165afa9081156102bc5760009161202a575090565b906020823d8211612050575b8161204360209383611025565b810103126119f057505190565b3d9150612036565b638b78c6d81954330361206757565b6382b429006000526004601cfd5b602460106020939284936014526f70a082310000000000000000000000006000525afa601f3d1116602051029056fea26469706673582212201671d64ce18bab5189730607d017daac0475adf305c69e99745320c38cd9290364736f6c63430008130033", + "nonce": "0xad", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xdd038c03083cf34670d646d5c33673b72f4ffaace285935b6acc74513cd941bd", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x9A3A2044A5D73736be0fC1968af4D4BAF1b9b89D", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x13e46", + "value": "0x0", + "data": "0x602c3d8160093d39f33d3d3d3d363d3d37363d735d8aa745c4b35fb46af555a6fcd464946e9fd9d95af43d3d93803e602a57fd5bf3", + "nonce": "0xae", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x69f481a3294cdc44eba27dc68436d5ed8c45b76146f31be5f1c22fd206301360", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x9A3A2044A5D73736be0fC1968af4D4BAF1b9b89D", + "function": "initialize(bytes)", + "arguments": [ + "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c00000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c" + ], + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "to": "0x9a3a2044a5d73736be0fc1968af4d4baf1b9b89d", + "gas": "0x27e6e", + "value": "0x0", + "data": "0x439fab91000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c00000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c", + "nonce": "0xaf", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0xd287327909739b467e2a4e6af08abff214a9f1d3aaaa22843a53601bff794e4e", + "transactionIndex": "0x7", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x218440", + "gasUsed": "0x1d3c15", + "contractAddress": "0x5D8AA745C4b35Fb46AF555a6FcD464946e9FD9D9", + "logs": [ + { + "address": "0x5D8AA745C4b35Fb46AF555a6FcD464946e9FD9D9", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "transactionHash": "0xd287327909739b467e2a4e6af08abff214a9f1d3aaaa22843a53601bff794e4e", + "transactionIndex": "0x7", + "logIndex": "0x3", + "removed": false + }, + { + "address": "0x5D8AA745C4b35Fb46AF555a6FcD464946e9FD9D9", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "transactionHash": "0xd287327909739b467e2a4e6af08abff214a9f1d3aaaa22843a53601bff794e4e", + "transactionIndex": "0x7", + "logIndex": "0x4", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000100040000000000000000000000000000000000000001000000000000000000000000000000000004000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x1b8e58186" + }, + { + "transactionHash": "0xdd038c03083cf34670d646d5c33673b72f4ffaace285935b6acc74513cd941bd", + "transactionIndex": "0x8", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x227918", + "gasUsed": "0xf4d8", + "contractAddress": "0x9A3A2044A5D73736be0fC1968af4D4BAF1b9b89D", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x1b8e58186" + }, + { + "transactionHash": "0x69f481a3294cdc44eba27dc68436d5ed8c45b76146f31be5f1c22fd206301360", + "transactionIndex": "0x9", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": "0x9A3A2044A5D73736be0fC1968af4D4BAF1b9b89D", + "cumulativeGasUsed": "0x24474f", + "gasUsed": "0x1ce37", + "contractAddress": null, + "logs": [ + { + "address": "0x9A3A2044A5D73736be0fC1968af4D4BAF1b9b89D", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c" + ], + "data": "0x", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "transactionHash": "0x69f481a3294cdc44eba27dc68436d5ed8c45b76146f31be5f1c22fd206301360", + "transactionIndex": "0x9", + "logIndex": "0x5", + "removed": false + }, + { + "address": "0x9A3A2044A5D73736be0fC1968af4D4BAF1b9b89D", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0xca79f7b1448518685ab8464b17337378cc74abbf6e07e1cf5ec5da7f3bd2c417", + "blockNumber": "0x5c0e1e", + "transactionHash": "0x69f481a3294cdc44eba27dc68436d5ed8c45b76146f31be5f1c22fd206301360", + "transactionIndex": "0x9", + "logIndex": "0x6", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000001000000000000000000000000000000000000020200000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000200000000000000001000000000000000000000000000000100000004000000000000000020000000000000000000080000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x1b8e58186" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1717437866, + "chain": 11155111, + "commit": "6fd63bc" +} \ No newline at end of file diff --git a/broadcast/QuestBudget.s.sol/11155111/run-1717450347.json b/broadcast/QuestBudget.s.sol/11155111/run-1717450347.json new file mode 100644 index 00000000..5a9b0852 --- /dev/null +++ b/broadcast/QuestBudget.s.sol/11155111/run-1717450347.json @@ -0,0 +1,178 @@ +{ + "transactions": [ + { + "hash": "0xddd217f82ff48dbcbd6d290d0fab6b976ec8d3698a9dd665979510947b98fbb2", + "transactionType": "CREATE", + "contractName": "QuestBudget", + "contractAddress": "0xF18CA2b222c7E1c532dA4CA8eBC0c9f0fCBE9Fe8", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x27f5e8", + "value": "0x0", + "data": "0x608080604052346100b95733638b78c6d819553360007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a363409feecd19805490600182166100ab576001600160401b039160011c6002600160401b031901610071575b6122a483816100bf8239f35b6002600160411b03905560209081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29080a13880610065565b63f92ee8a96000526004601cfd5b600080fdfe608080604052600436101561001a575b50361561001857005b005b600090813560e01c90816301ffc9a714610fec5750806310098ad514610fc857806319cbad0614610fa35780631c9fd0c314610f595780632569296214610f0e5780634359d28a14610e1e578063439fab9114610bf2578063451cc19114610bb357806354d1f13d14610b6d578063578bcf3514610b355780635aef467a14610afd57806361400c9914610ac0578063627bbbaa14610a53578063715018a614610a0d578063774c33ab146109cb5780638da5cb5b146109a057806392f5e0eb1461097a578063bc197c81146108d5578063d2514e8414610891578063de0580dc14610569578063e15cfcf5146104a1578063f04e283e14610420578063f1c30ec0146103db578063f23a6e6114610367578063f2fde38b146102f9578063f8724aba146102d1578063f9a802c31461020d578063fa4ca9b1146101d0578063fe9fbb80146101a25763fee81cf40361000f573461019f57602036600319011261019f576101866110f2565b9063389a75e1600c5252602080600c2054604051908152f35b80fd5b503461019f57602036600319011261019f5760206101c66101c16110f2565b612152565b6040519015158152f35b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c66102073660048601611163565b90611c0a565b503461019f57604036600319011261019f576102276110f2565b604051627eeac760e11b81523060048201526024803590820181905260209390926001600160a01b03168483604481845afa9283156102c657829361028e575b5090610286936040928252600286528282209082528552205490611bfd565b604051908152f35b919092508482813d83116102bf575b6102a781836111d7565b810103126102ba57905191610286610267565b600080fd5b503d61029d565b6040513d84823e3d90fd5b503461019f57604036600319011261019f5760206102866102f06110f2565b602435906121a7565b50602036600319011261019f5761030e6110f2565b610316612222565b8060601b1561035a576001600160a01b0316638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35580f35b637448fbae82526004601cfd5b503461019f5760a036600319011261019f576103816110f2565b5061038a611108565b5060843567ffffffffffffffff81116103d7576103ab903690600401611163565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b5080fd5b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c66104123660048601611163565b9061041b612222565b61177c565b50602036600319011261019f576104356110f2565b61043d612222565b63389a75e1600c528082526020600c20805442116104945790826001600160a01b03925516638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35580f35b636f5e881883526004601cfd5b503461019f57602036600319011261019f578060043567ffffffffffffffff8111610566576104d4903690600401611163565b91906104de612222565b6001600160a01b03825416803b156105625783918360446040518097819682957fe15cfcf500000000000000000000000000000000000000000000000000000000845260206004850152816024850152848401378181018301849052601f01601f191681010301925af180156102c657610556575080f35b61055f906111c3565b80f35b8280fd5b50fd5b503461019f5761016036600319011261019f5760043563ffffffff811681036103d757610594611108565b9067ffffffffffffffff9060c43582811161088d576105b790369060040161124c565b9160e435818111610889576105d090369060040161124c565b9061010435818111610885576105ea90369060040161124c565b90610124359081116108855761060490369060040161124c565b9161060e33612152565b1561085b5761062160a435608435611bea565b6001600160a01b03885416906040517f67dfa3e7000000000000000000000000000000000000000000000000000000008152602081600481865afa908115610850578a9161080b575b509061271061068061ffff610687941683611bea565b0490611bfd565b906014526034526f095ea7b3000000000000000000000000875260208760446010828a5af13d1560018951141716156107fe576001600160a01b0395936107896020969461077663ffffffff956107638c96876034526107518d8954169a6040519e8f9d8e9c8d9b7fde0580dc000000000000000000000000000000000000000000000000000000008d521660048c01521660248a015260443560448a015260643560648a015260843560848a015260a43560a48a015261016060c48a01526101648901906113ea565b8781036003190160e4890152906113ea565b85810360031901610104870152906113ea565b83810360031901610124850152906113ea565b61014480359083015203925af19081156102c65782916107b8575b6020826001600160a01b0360405191168152f35b90506020813d6020116107f6575b816107d3602093836111d7565b810103126103d757516001600160a01b03811681036103d75760209150386107a4565b3d91506107c6565b633e3f8f7387526004601cfd5b90506020813d602011610848575b81610826602093836111d7565b8101031261084457519061ffff82168203610844579061271061066a565b8980fd5b3d9150610819565b6040513d8c823e3d90fd5b60046040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b8580fd5b8480fd5b503461019f57602036600319011261019f5761028660209160406108b36110f2565b916001600160a01b036108c584612189565b9316815260018552205490611bfd565b503461019f5760a036600319011261019f576108ef6110f2565b506108f8611108565b5067ffffffffffffffff6044358181116105625761091a903690600401611132565b505060643581811161056257610934903690600401611132565b50506084359081116103d75761094e903690600401611163565b505060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b503461019f578060031936011261019f576001600160a01b036020915416604051908152f35b503461019f578060031936011261019f576020638b78c6d819546001600160a01b0360405191168152f35b503461019f57604036600319011261019f5760406020916001600160a01b036109f26110f2565b16815260028352818120602435825283522054604051908152f35b508060031936011261019f57610a21612222565b80638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35580f35b503461019f57602036600319011261019f576004358015158091036103d757610a7a612222565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000083549260a01b16911617815580f35b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c6610af73660048601611132565b906120c0565b50602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c6610b2f3660048601611163565b90611473565b503461019f57602036600319011261019f5760406020916001600160a01b03610b5c6110f2565b168152600183522054604051908152f35b508060031936011261019f5763389a75e1600c52338152806020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c928280a280f35b503461019f57602036600319011261019f5760043567ffffffffffffffff81116103d75790610be86020923690600401611163565b5050604051908152f35b503461019f576020806003193601126103d75767ffffffffffffffff90600435828111610e1a57610c27903690600401611163565b63409feecd1980546003808355949392919080610df5575b5090820191838184031261088557803590868211610df157019160608382031261088557604051610c6f81611191565b610c788461111e565b8152610c8585850161111e565b9385820194855260408101359088821161084457019180601f84011215610ded578235978811610dd95760059288841b9060405199610cc68984018c6111d7565b8a5287808b0192820101928311610dd55787809101915b838310610dbd5750505050604081019687526001600160a01b0393848092511680638b78c6d81955897f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3511673ffffffffffffffffffffffffffffffffffffffff19885416178755865b86518051821015610d805781831b018501518416885285855260408820805460ff19166001179055610d7b9061126a565b610d4a565b88848781610d8c578280f35b60027fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d292556001815280a181808280f35b8190610dc88461111e565b8152019101908790610cdd565b8a80fd5b602489634e487b7160e01b81526041600452fd5b8880fd5b8780fd5b600181811c14303b1015610e0d5760ff1b1b38610c3f565b63f92ee8a988526004601cfd5b8380fd5b503461019f57604036600319011261019f5767ffffffffffffffff60043581811161056257610e51903690600401611132565b91602435908111610e1a57610e6a903690600401611132565b610e75939193612222565b808203610ee457845b828110610e89578580f35b610e9481838761212c565b359081151580920361088557610eab81858761212c565b35916001600160a01b038316809303610df157610edf9288526003602052604088209060ff8019835416911617905561126a565b610e7e565b60046040517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b508060031936011261019f5763389a75e1600c523381526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d8280a280f35b503461019f57602036600319011261019f576001600160a01b03610f7b6110f2565b610f83612222565b1673ffffffffffffffffffffffffffffffffffffffff1982541617815580f35b503461019f578060031936011261019f5760ff6020915460a01c166040519015158152f35b503461019f57602036600319011261019f576020610286610fe76110f2565b612189565b9050346103d75760203660031901126103d7576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361056257602092507f4e2312e0000000000000000000000000000000000000000000000000000000008114908115611062575b5015158152f35b7f5cd687ca00000000000000000000000000000000000000000000000000000000811491508115611095575b503861105b565b7f42606236000000000000000000000000000000000000000000000000000000008114915081156110c8575b503861108e565b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386110c1565b600435906001600160a01b03821682036102ba57565b602435906001600160a01b03821682036102ba57565b35906001600160a01b03821682036102ba57565b9181601f840112156102ba5782359167ffffffffffffffff83116102ba576020808501948460051b0101116102ba57565b9181601f840112156102ba5782359167ffffffffffffffff83116102ba57602083818601950101116102ba57565b6060810190811067ffffffffffffffff8211176111ad57604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116111ad57604052565b90601f8019910116810190811067ffffffffffffffff8211176111ad57604052565b67ffffffffffffffff81116111ad57601f01601f191660200190565b929192611221826111f9565b9161122f60405193846111d7565b8294818452818301116102ba578281602093846000960137010152565b9080601f830112156102ba5781602061126793359101611215565b90565b60001981146112795760010190565b634e487b7160e01b600052601160045260246000fd5b906020828203126102ba57813567ffffffffffffffff928382116102ba5701916080838303126102ba576040519260808401848110838211176111ad57604052803560038110156102ba5784526112e86020820161111e565b60208501526112f96040820161111e565b604085015260608101359182116102ba57019080601f830112156102ba5781602061132693359101611215565b606082015290565b60005b8381106113415750506000910152565b8181015183820152602001611331565b90602080838303126102ba57825167ffffffffffffffff938482116102ba5701926060848403126102ba576040519361138985611191565b80518552828101518386015260408101519182116102ba570182601f820112156102ba578051906113b9826111f9565b936113c760405195866111d7565b8285528383830101116102ba57826113e2938501910161132e565b604082015290565b906020916114038151809281855285808601910161132e565b601f01601f1916010190565b919261126795949160a0946001600160a01b0380921685521660208401526040830152606082015281608082015201906113ea565b908160209103126102ba57604051906020820182811067ffffffffffffffff8211176111ad5760405251815290565b61147f9181019061128f565b80516000906003811015611768576114eb57506114a9606082015160208082518301019101611444565b51908134036114b9575050600190565b6020015160405163cece04c560e01b81526001600160a01b0390911660048201526024810191909152604490fd5b0390fd5b81516003811015611768576001036115e257611514606083015160208082518301019101611444565b9160208101906001600160a01b03926020816064601c82604089895116970151968a519760405198606052306040526bffffffffffffffffffffffff199060601b16602c526f23b872dd000000000000000000000000600c525af13d1560018351141716156115d557606052604052611590308383511661223f565b92518093106115a157505050600190565b51166114e760405192839263cece04c560e01b845260048401602090939291936001600160a01b0360408201951681520152565b637939f42490526004601cfd5b90805160038110156117545760020361175057606081015161160e602091828082518301019101611351565b818301906001600160a01b0392838351169184604080970151168151838301948551918985015193823b1561174c57908b809493926116648d5197889687958694637921219560e11b865230906004870161140f565b03925af1801561174257611729575b50835190518651627eeac760e11b8152306004820152602481019190915291908190839087168180604481015b03915afa96871561171e57966116ee575b5050518094106116c45750505050600190565b51915163cece04c560e01b815291166001600160a01b031660048201526024810191909152604490fd5b9080929650813d8311611717575b61170681836111d7565b810103126102ba57519338806116b1565b503d6116fc565b8651903d90823e3d90fd5b918091976117396116a0946111c3565b97919250611673565b87513d8a823e3d90fd5b8b80fd5b5090565b602483634e487b7160e01b81526021600452fd5b602482634e487b7160e01b81526021600452fd5b6117889181019061128f565b80516003811015611bc057158015611bd6575b1561198e576117b7606082015160208082518301019101611444565b906001600160a01b03604081602084015116920151169151801560001461198857506117e281612189565b915b68929eee149b4bd21268923084541461197a57308455811561194a5761180983612189565b8111611909578260005260016020526040600020611828828254611bfd565b90558261189857600038818084865af11561188a577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542915b604080516001600160a01b039092168252602082019290925290819081015b0390a2389055600190565b63b12d13eb6000526004601cfd5b81601452806034526fa9059cbb000000000000000000000000600052602060006044601082875af13d156001600051141716156118fb577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542916000603452611860565b6390b8ec186000526004601cfd5b826114e761191682612189565b92604051938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b6040516317e3057d60e31b81526001600160a01b0384811660048301529290921660248301526044820152606490fd5b63ab143c066000526004601cfd5b916117e4565b80516003811015611bc057600203611bba576060810151906119ba602092838082518301019101611351565b6001600160a01b0391828482015116926040809201511690825181868501518015600014611bb4575051627eeac760e11b8152306004820152602481018290528681604481895afa908115611ba957908391600091611b79575b50945b01519068929eee149b4bd21268963088541461197a573088558415611b4a57611a4082886121a7565b8611611b085786600052600281528360002090826000525282600020611a67868254611bfd565b9055853b156102ba5784600091611a9385519485938493637921219560e11b855289306004870161140f565b038183895af18015611afd579161187f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542959493611aee575b505192839283602090939291936001600160a01b0360408201951681520152565b611af7906111c3565b38611acd565b82513d6000823e3d90fd5b83876114e788611b1886846121a7565b9351938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b83516317e3057d60e31b81526001600160a01b0388811660048301528616602482015260448101879052606490fd5b91508782813d8311611ba2575b611b9081836111d7565b8101031261019f575082905138611a14565b503d611b86565b83513d6000823e3d90fd5b94611a17565b50600090565b634e487b7160e01b600052602160045260246000fd5b5080516003811015611bc05760011461179b565b8181029291811591840414171561127957565b9190820180921161127957565b90611c1433612152565b1561085b57611267919060009160ff835460a01c161561085b57611c3a9181019061128f565b805160038110156117545760011480156120ae575b15611e3057611c6b606082015160208082518301019101611444565b602082016001600160a01b0390611c8482825116612189565b8351818111611dfe5750508160409151169301511690519068929eee149b4bd212689330855414611df1573085558115611dbe57611cc184612189565b8311611db057838152600160205260408120611cde848254611bfd565b905583611d44578038818086865af115611d375750604080516001600160a01b03909216825260208201929092527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542918190810161187f565b63b12d13eb90526004601cfd5b81601452826034526fa9059cbb00000000000000000000000081526020816044601082885af13d156001835114171615611da3576034527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429190611860565b6390b8ec1890526004601cfd5b82846114e761191682612189565b506040516317e3057d60e31b81526001600160a01b03848116600483015291909116602482015260448101829052606490fd5b63ab143c0690526004601cfd5b8251604051632e2a182f60e11b81529085166001600160a01b0316600482015260248101929092526044820152606490fd5b805160038110156117545760020361175057606081015191611e5c602093848082518301019101611351565b908383016001600160a01b039182825116908451936040938885518095627eeac760e11b82528180611ea960049b308d8401602090939291936001600160a01b0360408201951681520152565b03915afa9384156120a4578394612075575b508887019384519080821161203a57505081859151169701511693838651935196015168929eee149b4bd2126898308a541461202e57308a558615611ff957611f04858a6121a7565b8811611fb957888452600281528584209085855252848320611f27888254611bfd565b9055873b15610562578291611f5287928988519788958695637921219560e11b87523090870161140f565b0381838a5af1908115611fae57509161187f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542959493611aee57505192839283602090939291936001600160a01b0360408201951681520152565b8351903d90823e3d90fd5b88836114e78a89611fca8a866121a7565b9051632e2a182f60e11b81526001600160a01b0390951693850193845260208401526040830152829160600190565b85516317e3057d60e31b81526001600160a01b03808b168286019081529089166020820152604081018a905281906060010390fd5b8263ab143c068552601cfd5b86945087936114e79351169451948594632e2a182f60e11b865285016040919493926001600160a01b03606083019616825260208201520152565b9093508881813d831161209d575b61208d81836111d7565b8101031261056257519238611ebb565b503d612083565b85513d85823e3d90fd5b50805160038110156117545715611c4f565b60005b8281106120d257505050600190565b8060051b820135601e19833603018112156102ba57820180359067ffffffffffffffff82116102ba576020019080360382136102ba5761211191611c0a565b156121245761211f9061126a565b6120c3565b505050600090565b919081101561213c5760051b0190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0380911680600052600360205260ff6040600020541691821561217b57505090565b638b78c6d819541614919050565b6001600160a01b03811661219c57504790565b61126790309061223f565b604051627eeac760e11b81523060048201526024810192909252602090829060449082906001600160a01b03165afa908115612216576000916121e8575090565b906020823d821161220e575b81612201602093836111d7565b8101031261019f57505190565b3d91506121f4565b6040513d6000823e3d90fd5b638b78c6d81954330361223157565b6382b429006000526004601cfd5b602460106020939284936014526f70a082310000000000000000000000006000525afa601f3d1116602051029056fea2646970667358221220851c0fe8990ee113c483f74c36815620cb965826000e714f19fd3544f654599864736f6c63430008130033", + "nonce": "0xb8", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xa2c89750cd3938a1058837409ef38cbf744d3a09f648e96f6d7f0f496c62d863", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x4a761aa6726E8249cCE347058B23AC680a71865F", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x13e46", + "value": "0x0", + "data": "0x602c3d8160093d39f33d3d3d3d363d3d37363d73f18ca2b222c7e1c532da4ca8ebc0c9f0fcbe9fe85af43d3d93803e602a57fd5bf3", + "nonce": "0xb9", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x96cc37d32f4dc6b4083871f8822658883322bb8e538cb85bb84110537a1b5e75", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0x4a761aa6726E8249cCE347058B23AC680a71865F", + "function": "initialize(bytes)", + "arguments": [ + "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c00000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c" + ], + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "to": "0x4a761aa6726e8249cce347058b23ac680a71865f", + "gas": "0x27e8b", + "value": "0x0", + "data": "0x439fab91000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c00000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c", + "nonce": "0xba", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0xddd217f82ff48dbcbd6d290d0fab6b976ec8d3698a9dd665979510947b98fbb2", + "transactionIndex": "0xd", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x37debe", + "gasUsed": "0x1ebf61", + "contractAddress": "0xF18CA2b222c7E1c532dA4CA8eBC0c9f0fCBE9Fe8", + "logs": [ + { + "address": "0xF18CA2b222c7E1c532dA4CA8eBC0c9f0fCBE9Fe8", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "transactionHash": "0xddd217f82ff48dbcbd6d290d0fab6b976ec8d3698a9dd665979510947b98fbb2", + "transactionIndex": "0xd", + "logIndex": "0x31", + "removed": false + }, + { + "address": "0xF18CA2b222c7E1c532dA4CA8eBC0c9f0fCBE9Fe8", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "transactionHash": "0xddd217f82ff48dbcbd6d290d0fab6b976ec8d3698a9dd665979510947b98fbb2", + "transactionIndex": "0xd", + "logIndex": "0x32", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000800000000000804000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000004000000000000000020000000000000000000000000000200000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xf3f97d97" + }, + { + "transactionHash": "0xa2c89750cd3938a1058837409ef38cbf744d3a09f648e96f6d7f0f496c62d863", + "transactionIndex": "0xe", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x38d396", + "gasUsed": "0xf4d8", + "contractAddress": "0x4a761aa6726E8249cCE347058B23AC680a71865F", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xf3f97d97" + }, + { + "transactionHash": "0x96cc37d32f4dc6b4083871f8822658883322bb8e538cb85bb84110537a1b5e75", + "transactionIndex": "0xf", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": "0x4a761aa6726E8249cCE347058B23AC680a71865F", + "cumulativeGasUsed": "0x3aa1e2", + "gasUsed": "0x1ce4c", + "contractAddress": null, + "logs": [ + { + "address": "0x4a761aa6726E8249cCE347058B23AC680a71865F", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000017f8ad14a2e745ea0f756bd57cd4852400be78c" + ], + "data": "0x", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "transactionHash": "0x96cc37d32f4dc6b4083871f8822658883322bb8e538cb85bb84110537a1b5e75", + "transactionIndex": "0xf", + "logIndex": "0x33", + "removed": false + }, + { + "address": "0x4a761aa6726E8249cCE347058B23AC680a71865F", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0xe767cd8bc38c7b585f60a54b4581ede7145f4ac94b585d842511ec322b4ee6fb", + "blockNumber": "0x5c11a8", + "transactionHash": "0x96cc37d32f4dc6b4083871f8822658883322bb8e538cb85bb84110537a1b5e75", + "transactionIndex": "0xf", + "logIndex": "0x34", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000400000000000001000000000000000000000800000000000000020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000002000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000100000004000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xf3f97d97" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1717450347, + "chain": 11155111, + "commit": "4212f67" +} \ No newline at end of file diff --git a/broadcast/QuestBudget.s.sol/11155111/run-1717450764.json b/broadcast/QuestBudget.s.sol/11155111/run-1717450764.json new file mode 100644 index 00000000..6ace1b26 --- /dev/null +++ b/broadcast/QuestBudget.s.sol/11155111/run-1717450764.json @@ -0,0 +1,178 @@ +{ + "transactions": [ + { + "hash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionType": "CREATE", + "contractName": "QuestBudget", + "contractAddress": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x27f5e8", + "value": "0x0", + "data": "0x608080604052346100b95733638b78c6d819553360007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a363409feecd19805490600182166100ab576001600160401b039160011c6002600160401b031901610071575b6122a483816100bf8239f35b6002600160411b03905560209081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29080a13880610065565b63f92ee8a96000526004601cfd5b600080fdfe608080604052600436101561001a575b50361561001857005b005b600090813560e01c90816301ffc9a714610fec5750806310098ad514610fc857806319cbad0614610fa35780631c9fd0c314610f595780632569296214610f0e5780634359d28a14610e1e578063439fab9114610bf2578063451cc19114610bb357806354d1f13d14610b6d578063578bcf3514610b355780635aef467a14610afd57806361400c9914610ac0578063627bbbaa14610a53578063715018a614610a0d578063774c33ab146109cb5780638da5cb5b146109a057806392f5e0eb1461097a578063bc197c81146108d5578063d2514e8414610891578063de0580dc14610569578063e15cfcf5146104a1578063f04e283e14610420578063f1c30ec0146103db578063f23a6e6114610367578063f2fde38b146102f9578063f8724aba146102d1578063f9a802c31461020d578063fa4ca9b1146101d0578063fe9fbb80146101a25763fee81cf40361000f573461019f57602036600319011261019f576101866110f2565b9063389a75e1600c5252602080600c2054604051908152f35b80fd5b503461019f57602036600319011261019f5760206101c66101c16110f2565b612152565b6040519015158152f35b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c66102073660048601611163565b90611c0a565b503461019f57604036600319011261019f576102276110f2565b604051627eeac760e11b81523060048201526024803590820181905260209390926001600160a01b03168483604481845afa9283156102c657829361028e575b5090610286936040928252600286528282209082528552205490611bfd565b604051908152f35b919092508482813d83116102bf575b6102a781836111d7565b810103126102ba57905191610286610267565b600080fd5b503d61029d565b6040513d84823e3d90fd5b503461019f57604036600319011261019f5760206102866102f06110f2565b602435906121a7565b50602036600319011261019f5761030e6110f2565b610316612222565b8060601b1561035a576001600160a01b0316638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35580f35b637448fbae82526004601cfd5b503461019f5760a036600319011261019f576103816110f2565b5061038a611108565b5060843567ffffffffffffffff81116103d7576103ab903690600401611163565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b5080fd5b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c66104123660048601611163565b9061041b612222565b61177c565b50602036600319011261019f576104356110f2565b61043d612222565b63389a75e1600c528082526020600c20805442116104945790826001600160a01b03925516638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35580f35b636f5e881883526004601cfd5b503461019f57602036600319011261019f578060043567ffffffffffffffff8111610566576104d4903690600401611163565b91906104de612222565b6001600160a01b03825416803b156105625783918360446040518097819682957fe15cfcf500000000000000000000000000000000000000000000000000000000845260206004850152816024850152848401378181018301849052601f01601f191681010301925af180156102c657610556575080f35b61055f906111c3565b80f35b8280fd5b50fd5b503461019f5761016036600319011261019f5760043563ffffffff811681036103d757610594611108565b9067ffffffffffffffff9060c43582811161088d576105b790369060040161124c565b9160e435818111610889576105d090369060040161124c565b9061010435818111610885576105ea90369060040161124c565b90610124359081116108855761060490369060040161124c565b9161060e33612152565b1561085b5761062160a435608435611bea565b6001600160a01b03885416906040517f67dfa3e7000000000000000000000000000000000000000000000000000000008152602081600481865afa908115610850578a9161080b575b509061271061068061ffff610687941683611bea565b0490611bfd565b906014526034526f095ea7b3000000000000000000000000875260208760446010828a5af13d1560018951141716156107fe576001600160a01b0395936107896020969461077663ffffffff956107638c96876034526107518d8954169a6040519e8f9d8e9c8d9b7fde0580dc000000000000000000000000000000000000000000000000000000008d521660048c01521660248a015260443560448a015260643560648a015260843560848a015260a43560a48a015261016060c48a01526101648901906113ea565b8781036003190160e4890152906113ea565b85810360031901610104870152906113ea565b83810360031901610124850152906113ea565b61014480359083015203925af19081156102c65782916107b8575b6020826001600160a01b0360405191168152f35b90506020813d6020116107f6575b816107d3602093836111d7565b810103126103d757516001600160a01b03811681036103d75760209150386107a4565b3d91506107c6565b633e3f8f7387526004601cfd5b90506020813d602011610848575b81610826602093836111d7565b8101031261084457519061ffff82168203610844579061271061066a565b8980fd5b3d9150610819565b6040513d8c823e3d90fd5b60046040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b8580fd5b8480fd5b503461019f57602036600319011261019f5761028660209160406108b36110f2565b916001600160a01b036108c584612189565b9316815260018552205490611bfd565b503461019f5760a036600319011261019f576108ef6110f2565b506108f8611108565b5067ffffffffffffffff6044358181116105625761091a903690600401611132565b505060643581811161056257610934903690600401611132565b50506084359081116103d75761094e903690600401611163565b505060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b503461019f578060031936011261019f576001600160a01b036020915416604051908152f35b503461019f578060031936011261019f576020638b78c6d819546001600160a01b0360405191168152f35b503461019f57604036600319011261019f5760406020916001600160a01b036109f26110f2565b16815260028352818120602435825283522054604051908152f35b508060031936011261019f57610a21612222565b80638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35580f35b503461019f57602036600319011261019f576004358015158091036103d757610a7a612222565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000083549260a01b16911617815580f35b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c6610af73660048601611132565b906120c0565b50602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c6610b2f3660048601611163565b90611473565b503461019f57602036600319011261019f5760406020916001600160a01b03610b5c6110f2565b168152600183522054604051908152f35b508060031936011261019f5763389a75e1600c52338152806020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c928280a280f35b503461019f57602036600319011261019f5760043567ffffffffffffffff81116103d75790610be86020923690600401611163565b5050604051908152f35b503461019f576020806003193601126103d75767ffffffffffffffff90600435828111610e1a57610c27903690600401611163565b63409feecd1980546003808355949392919080610df5575b5090820191838184031261088557803590868211610df157019160608382031261088557604051610c6f81611191565b610c788461111e565b8152610c8585850161111e565b9385820194855260408101359088821161084457019180601f84011215610ded578235978811610dd95760059288841b9060405199610cc68984018c6111d7565b8a5287808b0192820101928311610dd55787809101915b838310610dbd5750505050604081019687526001600160a01b0393848092511680638b78c6d81955897f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3511673ffffffffffffffffffffffffffffffffffffffff19885416178755865b86518051821015610d805781831b018501518416885285855260408820805460ff19166001179055610d7b9061126a565b610d4a565b88848781610d8c578280f35b60027fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d292556001815280a181808280f35b8190610dc88461111e565b8152019101908790610cdd565b8a80fd5b602489634e487b7160e01b81526041600452fd5b8880fd5b8780fd5b600181811c14303b1015610e0d5760ff1b1b38610c3f565b63f92ee8a988526004601cfd5b8380fd5b503461019f57604036600319011261019f5767ffffffffffffffff60043581811161056257610e51903690600401611132565b91602435908111610e1a57610e6a903690600401611132565b610e75939193612222565b808203610ee457845b828110610e89578580f35b610e9481838761212c565b359081151580920361088557610eab81858761212c565b35916001600160a01b038316809303610df157610edf9288526003602052604088209060ff8019835416911617905561126a565b610e7e565b60046040517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b508060031936011261019f5763389a75e1600c523381526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d8280a280f35b503461019f57602036600319011261019f576001600160a01b03610f7b6110f2565b610f83612222565b1673ffffffffffffffffffffffffffffffffffffffff1982541617815580f35b503461019f578060031936011261019f5760ff6020915460a01c166040519015158152f35b503461019f57602036600319011261019f576020610286610fe76110f2565b612189565b9050346103d75760203660031901126103d7576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361056257602092507f4e2312e0000000000000000000000000000000000000000000000000000000008114908115611062575b5015158152f35b7f5cd687ca00000000000000000000000000000000000000000000000000000000811491508115611095575b503861105b565b7f42606236000000000000000000000000000000000000000000000000000000008114915081156110c8575b503861108e565b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386110c1565b600435906001600160a01b03821682036102ba57565b602435906001600160a01b03821682036102ba57565b35906001600160a01b03821682036102ba57565b9181601f840112156102ba5782359167ffffffffffffffff83116102ba576020808501948460051b0101116102ba57565b9181601f840112156102ba5782359167ffffffffffffffff83116102ba57602083818601950101116102ba57565b6060810190811067ffffffffffffffff8211176111ad57604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116111ad57604052565b90601f8019910116810190811067ffffffffffffffff8211176111ad57604052565b67ffffffffffffffff81116111ad57601f01601f191660200190565b929192611221826111f9565b9161122f60405193846111d7565b8294818452818301116102ba578281602093846000960137010152565b9080601f830112156102ba5781602061126793359101611215565b90565b60001981146112795760010190565b634e487b7160e01b600052601160045260246000fd5b906020828203126102ba57813567ffffffffffffffff928382116102ba5701916080838303126102ba576040519260808401848110838211176111ad57604052803560038110156102ba5784526112e86020820161111e565b60208501526112f96040820161111e565b604085015260608101359182116102ba57019080601f830112156102ba5781602061132693359101611215565b606082015290565b60005b8381106113415750506000910152565b8181015183820152602001611331565b90602080838303126102ba57825167ffffffffffffffff938482116102ba5701926060848403126102ba576040519361138985611191565b80518552828101518386015260408101519182116102ba570182601f820112156102ba578051906113b9826111f9565b936113c760405195866111d7565b8285528383830101116102ba57826113e2938501910161132e565b604082015290565b906020916114038151809281855285808601910161132e565b601f01601f1916010190565b919261126795949160a0946001600160a01b0380921685521660208401526040830152606082015281608082015201906113ea565b908160209103126102ba57604051906020820182811067ffffffffffffffff8211176111ad5760405251815290565b61147f9181019061128f565b80516000906003811015611768576114eb57506114a9606082015160208082518301019101611444565b51908134036114b9575050600190565b6020015160405163cece04c560e01b81526001600160a01b0390911660048201526024810191909152604490fd5b0390fd5b81516003811015611768576001036115e257611514606083015160208082518301019101611444565b9160208101906001600160a01b03926020816064601c82604089895116970151968a519760405198606052306040526bffffffffffffffffffffffff199060601b16602c526f23b872dd000000000000000000000000600c525af13d1560018351141716156115d557606052604052611590308383511661223f565b92518093106115a157505050600190565b51166114e760405192839263cece04c560e01b845260048401602090939291936001600160a01b0360408201951681520152565b637939f42490526004601cfd5b90805160038110156117545760020361175057606081015161160e602091828082518301019101611351565b818301906001600160a01b0392838351169184604080970151168151838301948551918985015193823b1561174c57908b809493926116648d5197889687958694637921219560e11b865230906004870161140f565b03925af1801561174257611729575b50835190518651627eeac760e11b8152306004820152602481019190915291908190839087168180604481015b03915afa96871561171e57966116ee575b5050518094106116c45750505050600190565b51915163cece04c560e01b815291166001600160a01b031660048201526024810191909152604490fd5b9080929650813d8311611717575b61170681836111d7565b810103126102ba57519338806116b1565b503d6116fc565b8651903d90823e3d90fd5b918091976117396116a0946111c3565b97919250611673565b87513d8a823e3d90fd5b8b80fd5b5090565b602483634e487b7160e01b81526021600452fd5b602482634e487b7160e01b81526021600452fd5b6117889181019061128f565b80516003811015611bc057158015611bd6575b1561198e576117b7606082015160208082518301019101611444565b906001600160a01b03604081602084015116920151169151801560001461198857506117e281612189565b915b68929eee149b4bd21268923084541461197a57308455811561194a5761180983612189565b8111611909578260005260016020526040600020611828828254611bfd565b90558261189857600038818084865af11561188a577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542915b604080516001600160a01b039092168252602082019290925290819081015b0390a2389055600190565b63b12d13eb6000526004601cfd5b81601452806034526fa9059cbb000000000000000000000000600052602060006044601082875af13d156001600051141716156118fb577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542916000603452611860565b6390b8ec186000526004601cfd5b826114e761191682612189565b92604051938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b6040516317e3057d60e31b81526001600160a01b0384811660048301529290921660248301526044820152606490fd5b63ab143c066000526004601cfd5b916117e4565b80516003811015611bc057600203611bba576060810151906119ba602092838082518301019101611351565b6001600160a01b0391828482015116926040809201511690825181868501518015600014611bb4575051627eeac760e11b8152306004820152602481018290528681604481895afa908115611ba957908391600091611b79575b50945b01519068929eee149b4bd21268963088541461197a573088558415611b4a57611a4082886121a7565b8611611b085786600052600281528360002090826000525282600020611a67868254611bfd565b9055853b156102ba5784600091611a9385519485938493637921219560e11b855289306004870161140f565b038183895af18015611afd579161187f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542959493611aee575b505192839283602090939291936001600160a01b0360408201951681520152565b611af7906111c3565b38611acd565b82513d6000823e3d90fd5b83876114e788611b1886846121a7565b9351938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b83516317e3057d60e31b81526001600160a01b0388811660048301528616602482015260448101879052606490fd5b91508782813d8311611ba2575b611b9081836111d7565b8101031261019f575082905138611a14565b503d611b86565b83513d6000823e3d90fd5b94611a17565b50600090565b634e487b7160e01b600052602160045260246000fd5b5080516003811015611bc05760011461179b565b8181029291811591840414171561127957565b9190820180921161127957565b90611c1433612152565b1561085b57611267919060009160ff835460a01c161561085b57611c3a9181019061128f565b805160038110156117545760011480156120ae575b15611e3057611c6b606082015160208082518301019101611444565b602082016001600160a01b0390611c8482825116612189565b8351818111611dfe5750508160409151169301511690519068929eee149b4bd212689330855414611df1573085558115611dbe57611cc184612189565b8311611db057838152600160205260408120611cde848254611bfd565b905583611d44578038818086865af115611d375750604080516001600160a01b03909216825260208201929092527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542918190810161187f565b63b12d13eb90526004601cfd5b81601452826034526fa9059cbb00000000000000000000000081526020816044601082885af13d156001835114171615611da3576034527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429190611860565b6390b8ec1890526004601cfd5b82846114e761191682612189565b506040516317e3057d60e31b81526001600160a01b03848116600483015291909116602482015260448101829052606490fd5b63ab143c0690526004601cfd5b8251604051632e2a182f60e11b81529085166001600160a01b0316600482015260248101929092526044820152606490fd5b805160038110156117545760020361175057606081015191611e5c602093848082518301019101611351565b908383016001600160a01b039182825116908451936040938885518095627eeac760e11b82528180611ea960049b308d8401602090939291936001600160a01b0360408201951681520152565b03915afa9384156120a4578394612075575b508887019384519080821161203a57505081859151169701511693838651935196015168929eee149b4bd2126898308a541461202e57308a558615611ff957611f04858a6121a7565b8811611fb957888452600281528584209085855252848320611f27888254611bfd565b9055873b15610562578291611f5287928988519788958695637921219560e11b87523090870161140f565b0381838a5af1908115611fae57509161187f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542959493611aee57505192839283602090939291936001600160a01b0360408201951681520152565b8351903d90823e3d90fd5b88836114e78a89611fca8a866121a7565b9051632e2a182f60e11b81526001600160a01b0390951693850193845260208401526040830152829160600190565b85516317e3057d60e31b81526001600160a01b03808b168286019081529089166020820152604081018a905281906060010390fd5b8263ab143c068552601cfd5b86945087936114e79351169451948594632e2a182f60e11b865285016040919493926001600160a01b03606083019616825260208201520152565b9093508881813d831161209d575b61208d81836111d7565b8101031261056257519238611ebb565b503d612083565b85513d85823e3d90fd5b50805160038110156117545715611c4f565b60005b8281106120d257505050600190565b8060051b820135601e19833603018112156102ba57820180359067ffffffffffffffff82116102ba576020019080360382136102ba5761211191611c0a565b156121245761211f9061126a565b6120c3565b505050600090565b919081101561213c5760051b0190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0380911680600052600360205260ff6040600020541691821561217b57505090565b638b78c6d819541614919050565b6001600160a01b03811661219c57504790565b61126790309061223f565b604051627eeac760e11b81523060048201526024810192909252602090829060449082906001600160a01b03165afa908115612216576000916121e8575090565b906020823d821161220e575b81612201602093836111d7565b8101031261019f57505190565b3d91506121f4565b6040513d6000823e3d90fd5b638b78c6d81954330361223157565b6382b429006000526004601cfd5b602460106020939284936014526f70a082310000000000000000000000006000525afa601f3d1116602051029056fea2646970667358221220851c0fe8990ee113c483f74c36815620cb965826000e714f19fd3544f654599864736f6c63430008130033", + "nonce": "0xbb", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe657220cb787c1d8aca775b83178866d8cf809f4970670cd0977274b9c626114", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x13e46", + "value": "0x0", + "data": "0x602c3d8160093d39f33d3d3d3d363d3d37363d732ae565e22c07b4d850a258bfce8ac3cdaeec1e325af43d3d93803e602a57fd5bf3", + "nonce": "0xbc", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "function": "initialize(bytes)", + "arguments": [ + "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f0000000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "to": "0xff28c11c38c5689242728a2da5217aeba1297cab", + "gas": "0x27e6a", + "value": "0x0", + "data": "0x439fab91000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f0000000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00", + "nonce": "0xbd", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionIndex": "0xc", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x25ed3f", + "gasUsed": "0x1ebf61", + "contractAddress": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "logs": [ + { + "address": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionIndex": "0xc", + "logIndex": "0xd", + "removed": false + }, + { + "address": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionIndex": "0xc", + "logIndex": "0xe", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000804000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000002000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000004000000000000000020000000000000000000000000000000000000000000000000000000000080000000", + "type": "0x2", + "effectiveGasPrice": "0x102bbdd6a" + }, + { + "transactionHash": "0xe657220cb787c1d8aca775b83178866d8cf809f4970670cd0977274b9c626114", + "transactionIndex": "0xd", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x26e217", + "gasUsed": "0xf4d8", + "contractAddress": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x102bbdd6a" + }, + { + "transactionHash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionIndex": "0xe", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "cumulativeGasUsed": "0x28b04b", + "gasUsed": "0x1ce34", + "contractAddress": null, + "logs": [ + { + "address": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionIndex": "0xe", + "logIndex": "0xf", + "removed": false + }, + { + "address": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionIndex": "0xe", + "logIndex": "0x10", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000004080000000000000020000000000000000000000000000000000000000000000000000000400000000800", + "type": "0x2", + "effectiveGasPrice": "0x102bbdd6a" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1717450764, + "chain": 11155111, + "commit": "4212f67" +} \ No newline at end of file diff --git a/broadcast/QuestBudget.s.sol/11155111/run-latest.json b/broadcast/QuestBudget.s.sol/11155111/run-latest.json new file mode 100644 index 00000000..6ace1b26 --- /dev/null +++ b/broadcast/QuestBudget.s.sol/11155111/run-latest.json @@ -0,0 +1,178 @@ +{ + "transactions": [ + { + "hash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionType": "CREATE", + "contractName": "QuestBudget", + "contractAddress": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x27f5e8", + "value": "0x0", + "data": "0x608080604052346100b95733638b78c6d819553360007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a363409feecd19805490600182166100ab576001600160401b039160011c6002600160401b031901610071575b6122a483816100bf8239f35b6002600160411b03905560209081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29080a13880610065565b63f92ee8a96000526004601cfd5b600080fdfe608080604052600436101561001a575b50361561001857005b005b600090813560e01c90816301ffc9a714610fec5750806310098ad514610fc857806319cbad0614610fa35780631c9fd0c314610f595780632569296214610f0e5780634359d28a14610e1e578063439fab9114610bf2578063451cc19114610bb357806354d1f13d14610b6d578063578bcf3514610b355780635aef467a14610afd57806361400c9914610ac0578063627bbbaa14610a53578063715018a614610a0d578063774c33ab146109cb5780638da5cb5b146109a057806392f5e0eb1461097a578063bc197c81146108d5578063d2514e8414610891578063de0580dc14610569578063e15cfcf5146104a1578063f04e283e14610420578063f1c30ec0146103db578063f23a6e6114610367578063f2fde38b146102f9578063f8724aba146102d1578063f9a802c31461020d578063fa4ca9b1146101d0578063fe9fbb80146101a25763fee81cf40361000f573461019f57602036600319011261019f576101866110f2565b9063389a75e1600c5252602080600c2054604051908152f35b80fd5b503461019f57602036600319011261019f5760206101c66101c16110f2565b612152565b6040519015158152f35b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c66102073660048601611163565b90611c0a565b503461019f57604036600319011261019f576102276110f2565b604051627eeac760e11b81523060048201526024803590820181905260209390926001600160a01b03168483604481845afa9283156102c657829361028e575b5090610286936040928252600286528282209082528552205490611bfd565b604051908152f35b919092508482813d83116102bf575b6102a781836111d7565b810103126102ba57905191610286610267565b600080fd5b503d61029d565b6040513d84823e3d90fd5b503461019f57604036600319011261019f5760206102866102f06110f2565b602435906121a7565b50602036600319011261019f5761030e6110f2565b610316612222565b8060601b1561035a576001600160a01b0316638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35580f35b637448fbae82526004601cfd5b503461019f5760a036600319011261019f576103816110f2565b5061038a611108565b5060843567ffffffffffffffff81116103d7576103ab903690600401611163565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b5080fd5b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c66104123660048601611163565b9061041b612222565b61177c565b50602036600319011261019f576104356110f2565b61043d612222565b63389a75e1600c528082526020600c20805442116104945790826001600160a01b03925516638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a35580f35b636f5e881883526004601cfd5b503461019f57602036600319011261019f578060043567ffffffffffffffff8111610566576104d4903690600401611163565b91906104de612222565b6001600160a01b03825416803b156105625783918360446040518097819682957fe15cfcf500000000000000000000000000000000000000000000000000000000845260206004850152816024850152848401378181018301849052601f01601f191681010301925af180156102c657610556575080f35b61055f906111c3565b80f35b8280fd5b50fd5b503461019f5761016036600319011261019f5760043563ffffffff811681036103d757610594611108565b9067ffffffffffffffff9060c43582811161088d576105b790369060040161124c565b9160e435818111610889576105d090369060040161124c565b9061010435818111610885576105ea90369060040161124c565b90610124359081116108855761060490369060040161124c565b9161060e33612152565b1561085b5761062160a435608435611bea565b6001600160a01b03885416906040517f67dfa3e7000000000000000000000000000000000000000000000000000000008152602081600481865afa908115610850578a9161080b575b509061271061068061ffff610687941683611bea565b0490611bfd565b906014526034526f095ea7b3000000000000000000000000875260208760446010828a5af13d1560018951141716156107fe576001600160a01b0395936107896020969461077663ffffffff956107638c96876034526107518d8954169a6040519e8f9d8e9c8d9b7fde0580dc000000000000000000000000000000000000000000000000000000008d521660048c01521660248a015260443560448a015260643560648a015260843560848a015260a43560a48a015261016060c48a01526101648901906113ea565b8781036003190160e4890152906113ea565b85810360031901610104870152906113ea565b83810360031901610124850152906113ea565b61014480359083015203925af19081156102c65782916107b8575b6020826001600160a01b0360405191168152f35b90506020813d6020116107f6575b816107d3602093836111d7565b810103126103d757516001600160a01b03811681036103d75760209150386107a4565b3d91506107c6565b633e3f8f7387526004601cfd5b90506020813d602011610848575b81610826602093836111d7565b8101031261084457519061ffff82168203610844579061271061066a565b8980fd5b3d9150610819565b6040513d8c823e3d90fd5b60046040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b8680fd5b8580fd5b8480fd5b503461019f57602036600319011261019f5761028660209160406108b36110f2565b916001600160a01b036108c584612189565b9316815260018552205490611bfd565b503461019f5760a036600319011261019f576108ef6110f2565b506108f8611108565b5067ffffffffffffffff6044358181116105625761091a903690600401611132565b505060643581811161056257610934903690600401611132565b50506084359081116103d75761094e903690600401611163565b505060206040517fbc197c81000000000000000000000000000000000000000000000000000000008152f35b503461019f578060031936011261019f576001600160a01b036020915416604051908152f35b503461019f578060031936011261019f576020638b78c6d819546001600160a01b0360405191168152f35b503461019f57604036600319011261019f5760406020916001600160a01b036109f26110f2565b16815260028352818120602435825283522054604051908152f35b508060031936011261019f57610a21612222565b80638b78c6d8198181547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35580f35b503461019f57602036600319011261019f576004358015158091036103d757610a7a612222565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff000000000000000000000000000000000000000083549260a01b16911617815580f35b503461019f57602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c6610af73660048601611132565b906120c0565b50602036600319011261019f576004359067ffffffffffffffff821161019f5760206101c6610b2f3660048601611163565b90611473565b503461019f57602036600319011261019f5760406020916001600160a01b03610b5c6110f2565b168152600183522054604051908152f35b508060031936011261019f5763389a75e1600c52338152806020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c928280a280f35b503461019f57602036600319011261019f5760043567ffffffffffffffff81116103d75790610be86020923690600401611163565b5050604051908152f35b503461019f576020806003193601126103d75767ffffffffffffffff90600435828111610e1a57610c27903690600401611163565b63409feecd1980546003808355949392919080610df5575b5090820191838184031261088557803590868211610df157019160608382031261088557604051610c6f81611191565b610c788461111e565b8152610c8585850161111e565b9385820194855260408101359088821161084457019180601f84011215610ded578235978811610dd95760059288841b9060405199610cc68984018c6111d7565b8a5287808b0192820101928311610dd55787809101915b838310610dbd5750505050604081019687526001600160a01b0393848092511680638b78c6d81955897f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3511673ffffffffffffffffffffffffffffffffffffffff19885416178755865b86518051821015610d805781831b018501518416885285855260408820805460ff19166001179055610d7b9061126a565b610d4a565b88848781610d8c578280f35b60027fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d292556001815280a181808280f35b8190610dc88461111e565b8152019101908790610cdd565b8a80fd5b602489634e487b7160e01b81526041600452fd5b8880fd5b8780fd5b600181811c14303b1015610e0d5760ff1b1b38610c3f565b63f92ee8a988526004601cfd5b8380fd5b503461019f57604036600319011261019f5767ffffffffffffffff60043581811161056257610e51903690600401611132565b91602435908111610e1a57610e6a903690600401611132565b610e75939193612222565b808203610ee457845b828110610e89578580f35b610e9481838761212c565b359081151580920361088557610eab81858761212c565b35916001600160a01b038316809303610df157610edf9288526003602052604088209060ff8019835416911617905561126a565b610e7e565b60046040517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b508060031936011261019f5763389a75e1600c523381526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d8280a280f35b503461019f57602036600319011261019f576001600160a01b03610f7b6110f2565b610f83612222565b1673ffffffffffffffffffffffffffffffffffffffff1982541617815580f35b503461019f578060031936011261019f5760ff6020915460a01c166040519015158152f35b503461019f57602036600319011261019f576020610286610fe76110f2565b612189565b9050346103d75760203660031901126103d7576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361056257602092507f4e2312e0000000000000000000000000000000000000000000000000000000008114908115611062575b5015158152f35b7f5cd687ca00000000000000000000000000000000000000000000000000000000811491508115611095575b503861105b565b7f42606236000000000000000000000000000000000000000000000000000000008114915081156110c8575b503861108e565b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386110c1565b600435906001600160a01b03821682036102ba57565b602435906001600160a01b03821682036102ba57565b35906001600160a01b03821682036102ba57565b9181601f840112156102ba5782359167ffffffffffffffff83116102ba576020808501948460051b0101116102ba57565b9181601f840112156102ba5782359167ffffffffffffffff83116102ba57602083818601950101116102ba57565b6060810190811067ffffffffffffffff8211176111ad57604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116111ad57604052565b90601f8019910116810190811067ffffffffffffffff8211176111ad57604052565b67ffffffffffffffff81116111ad57601f01601f191660200190565b929192611221826111f9565b9161122f60405193846111d7565b8294818452818301116102ba578281602093846000960137010152565b9080601f830112156102ba5781602061126793359101611215565b90565b60001981146112795760010190565b634e487b7160e01b600052601160045260246000fd5b906020828203126102ba57813567ffffffffffffffff928382116102ba5701916080838303126102ba576040519260808401848110838211176111ad57604052803560038110156102ba5784526112e86020820161111e565b60208501526112f96040820161111e565b604085015260608101359182116102ba57019080601f830112156102ba5781602061132693359101611215565b606082015290565b60005b8381106113415750506000910152565b8181015183820152602001611331565b90602080838303126102ba57825167ffffffffffffffff938482116102ba5701926060848403126102ba576040519361138985611191565b80518552828101518386015260408101519182116102ba570182601f820112156102ba578051906113b9826111f9565b936113c760405195866111d7565b8285528383830101116102ba57826113e2938501910161132e565b604082015290565b906020916114038151809281855285808601910161132e565b601f01601f1916010190565b919261126795949160a0946001600160a01b0380921685521660208401526040830152606082015281608082015201906113ea565b908160209103126102ba57604051906020820182811067ffffffffffffffff8211176111ad5760405251815290565b61147f9181019061128f565b80516000906003811015611768576114eb57506114a9606082015160208082518301019101611444565b51908134036114b9575050600190565b6020015160405163cece04c560e01b81526001600160a01b0390911660048201526024810191909152604490fd5b0390fd5b81516003811015611768576001036115e257611514606083015160208082518301019101611444565b9160208101906001600160a01b03926020816064601c82604089895116970151968a519760405198606052306040526bffffffffffffffffffffffff199060601b16602c526f23b872dd000000000000000000000000600c525af13d1560018351141716156115d557606052604052611590308383511661223f565b92518093106115a157505050600190565b51166114e760405192839263cece04c560e01b845260048401602090939291936001600160a01b0360408201951681520152565b637939f42490526004601cfd5b90805160038110156117545760020361175057606081015161160e602091828082518301019101611351565b818301906001600160a01b0392838351169184604080970151168151838301948551918985015193823b1561174c57908b809493926116648d5197889687958694637921219560e11b865230906004870161140f565b03925af1801561174257611729575b50835190518651627eeac760e11b8152306004820152602481019190915291908190839087168180604481015b03915afa96871561171e57966116ee575b5050518094106116c45750505050600190565b51915163cece04c560e01b815291166001600160a01b031660048201526024810191909152604490fd5b9080929650813d8311611717575b61170681836111d7565b810103126102ba57519338806116b1565b503d6116fc565b8651903d90823e3d90fd5b918091976117396116a0946111c3565b97919250611673565b87513d8a823e3d90fd5b8b80fd5b5090565b602483634e487b7160e01b81526021600452fd5b602482634e487b7160e01b81526021600452fd5b6117889181019061128f565b80516003811015611bc057158015611bd6575b1561198e576117b7606082015160208082518301019101611444565b906001600160a01b03604081602084015116920151169151801560001461198857506117e281612189565b915b68929eee149b4bd21268923084541461197a57308455811561194a5761180983612189565b8111611909578260005260016020526040600020611828828254611bfd565b90558261189857600038818084865af11561188a577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542915b604080516001600160a01b039092168252602082019290925290819081015b0390a2389055600190565b63b12d13eb6000526004601cfd5b81601452806034526fa9059cbb000000000000000000000000600052602060006044601082875af13d156001600051141716156118fb577fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542916000603452611860565b6390b8ec186000526004601cfd5b826114e761191682612189565b92604051938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b6040516317e3057d60e31b81526001600160a01b0384811660048301529290921660248301526044820152606490fd5b63ab143c066000526004601cfd5b916117e4565b80516003811015611bc057600203611bba576060810151906119ba602092838082518301019101611351565b6001600160a01b0391828482015116926040809201511690825181868501518015600014611bb4575051627eeac760e11b8152306004820152602481018290528681604481895afa908115611ba957908391600091611b79575b50945b01519068929eee149b4bd21268963088541461197a573088558415611b4a57611a4082886121a7565b8611611b085786600052600281528360002090826000525282600020611a67868254611bfd565b9055853b156102ba5784600091611a9385519485938493637921219560e11b855289306004870161140f565b038183895af18015611afd579161187f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542959493611aee575b505192839283602090939291936001600160a01b0360408201951681520152565b611af7906111c3565b38611acd565b82513d6000823e3d90fd5b83876114e788611b1886846121a7565b9351938493632e2a182f60e11b8552600485016040919493926001600160a01b03606083019616825260208201520152565b83516317e3057d60e31b81526001600160a01b0388811660048301528616602482015260448101879052606490fd5b91508782813d8311611ba2575b611b9081836111d7565b8101031261019f575082905138611a14565b503d611b86565b83513d6000823e3d90fd5b94611a17565b50600090565b634e487b7160e01b600052602160045260246000fd5b5080516003811015611bc05760011461179b565b8181029291811591840414171561127957565b9190820180921161127957565b90611c1433612152565b1561085b57611267919060009160ff835460a01c161561085b57611c3a9181019061128f565b805160038110156117545760011480156120ae575b15611e3057611c6b606082015160208082518301019101611444565b602082016001600160a01b0390611c8482825116612189565b8351818111611dfe5750508160409151169301511690519068929eee149b4bd212689330855414611df1573085558115611dbe57611cc184612189565b8311611db057838152600160205260408120611cde848254611bfd565b905583611d44578038818086865af115611d375750604080516001600160a01b03909216825260208201929092527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542918190810161187f565b63b12d13eb90526004601cfd5b81601452826034526fa9059cbb00000000000000000000000081526020816044601082885af13d156001835114171615611da3576034527fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd435429190611860565b6390b8ec1890526004601cfd5b82846114e761191682612189565b506040516317e3057d60e31b81526001600160a01b03848116600483015291909116602482015260448101829052606490fd5b63ab143c0690526004601cfd5b8251604051632e2a182f60e11b81529085166001600160a01b0316600482015260248101929092526044820152606490fd5b805160038110156117545760020361175057606081015191611e5c602093848082518301019101611351565b908383016001600160a01b039182825116908451936040938885518095627eeac760e11b82528180611ea960049b308d8401602090939291936001600160a01b0360408201951681520152565b03915afa9384156120a4578394612075575b508887019384519080821161203a57505081859151169701511693838651935196015168929eee149b4bd2126898308a541461202e57308a558615611ff957611f04858a6121a7565b8811611fb957888452600281528584209085855252848320611f27888254611bfd565b9055873b15610562578291611f5287928988519788958695637921219560e11b87523090870161140f565b0381838a5af1908115611fae57509161187f917fad4a9acf26d8bba7a8cf1a41160d59be042ee554578e256c98d2ab74cdd43542959493611aee57505192839283602090939291936001600160a01b0360408201951681520152565b8351903d90823e3d90fd5b88836114e78a89611fca8a866121a7565b9051632e2a182f60e11b81526001600160a01b0390951693850193845260208401526040830152829160600190565b85516317e3057d60e31b81526001600160a01b03808b168286019081529089166020820152604081018a905281906060010390fd5b8263ab143c068552601cfd5b86945087936114e79351169451948594632e2a182f60e11b865285016040919493926001600160a01b03606083019616825260208201520152565b9093508881813d831161209d575b61208d81836111d7565b8101031261056257519238611ebb565b503d612083565b85513d85823e3d90fd5b50805160038110156117545715611c4f565b60005b8281106120d257505050600190565b8060051b820135601e19833603018112156102ba57820180359067ffffffffffffffff82116102ba576020019080360382136102ba5761211191611c0a565b156121245761211f9061126a565b6120c3565b505050600090565b919081101561213c5760051b0190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0380911680600052600360205260ff6040600020541691821561217b57505090565b638b78c6d819541614919050565b6001600160a01b03811661219c57504790565b61126790309061223f565b604051627eeac760e11b81523060048201526024810192909252602090829060449082906001600160a01b03165afa908115612216576000916121e8575090565b906020823d821161220e575b81612201602093836111d7565b8101031261019f57505190565b3d91506121f4565b6040513d6000823e3d90fd5b638b78c6d81954330361223157565b6382b429006000526004601cfd5b602460106020939284936014526f70a082310000000000000000000000006000525afa601f3d1116602051029056fea2646970667358221220851c0fe8990ee113c483f74c36815620cb965826000e714f19fd3544f654599864736f6c63430008130033", + "nonce": "0xbb", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xe657220cb787c1d8aca775b83178866d8cf809f4970670cd0977274b9c626114", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "function": null, + "arguments": null, + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "gas": "0x13e46", + "value": "0x0", + "data": "0x602c3d8160093d39f33d3d3d3d363d3d37363d732ae565e22c07b4d850a258bfce8ac3cdaeec1e325af43d3d93803e602a57fd5bf3", + "nonce": "0xbc", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionType": "CALL", + "contractName": null, + "contractAddress": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "function": "initialize(bytes)", + "arguments": [ + "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f0000000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "transaction": { + "type": "0x02", + "from": "0xe662f9575634dbbca894b756d1a19a851c824f00", + "to": "0xff28c11c38c5689242728a2da5217aeba1297cab", + "gas": "0x27e6a", + "value": "0x0", + "data": "0x439fab91000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f0000000000000000000000000052629961f71c1c2564c5aa22372cb1b9fa9eba3e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00", + "nonce": "0xbd", + "accessList": [] + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "transactionHash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionIndex": "0xc", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x25ed3f", + "gasUsed": "0x1ebf61", + "contractAddress": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "logs": [ + { + "address": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionIndex": "0xc", + "logIndex": "0xd", + "removed": false + }, + { + "address": "0x2AE565e22c07B4D850a258bFce8aC3cDAeEc1E32", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0xc9d8cd65ca990df31dcb36b88b4732cf0f06f895ac6b1d378907407eeb86bdc8", + "transactionIndex": "0xc", + "logIndex": "0xe", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000804000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000002000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000004000000000000000020000000000000000000000000000000000000000000000000000000000080000000", + "type": "0x2", + "effectiveGasPrice": "0x102bbdd6a" + }, + { + "transactionHash": "0xe657220cb787c1d8aca775b83178866d8cf809f4970670cd0977274b9c626114", + "transactionIndex": "0xd", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": null, + "cumulativeGasUsed": "0x26e217", + "gasUsed": "0xf4d8", + "contractAddress": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "logs": [], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0x102bbdd6a" + }, + { + "transactionHash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionIndex": "0xe", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "from": "0xE662f9575634dbbca894B756d1A19A851c824f00", + "to": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "cumulativeGasUsed": "0x28b04b", + "gasUsed": "0x1ce34", + "contractAddress": null, + "logs": [ + { + "address": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e662f9575634dbbca894b756d1a19a851c824f00" + ], + "data": "0x", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionIndex": "0xe", + "logIndex": "0xf", + "removed": false + }, + { + "address": "0xfF28C11c38c5689242728A2da5217AEba1297Cab", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x64fff4b13eb0af33d1aba7cbc87ffc97ec67225248b4d7216c879459fe21eb4a", + "blockNumber": "0x5c11c4", + "transactionHash": "0x8e7a84200f6bd20407b61276b3eea75a595e9f5436661e2e349e3da3fcfe8114", + "transactionIndex": "0xe", + "logIndex": "0x10", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000804000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000004080000000000000020000000000000000000000000000000000000000000000000000000400000000800", + "type": "0x2", + "effectiveGasPrice": "0x102bbdd6a" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1717450764, + "chain": 11155111, + "commit": "4212f67" +} \ No newline at end of file diff --git a/contracts/QuestBudget.sol b/contracts/QuestBudget.sol new file mode 100644 index 00000000..3a6aa150 --- /dev/null +++ b/contracts/QuestBudget.sol @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import {IQuestFactory} from "contracts/interfaces/IQuestFactory.sol"; + +import {IERC1155Receiver} from "openzeppelin-contracts/token/ERC1155/IERC1155Receiver.sol"; +import {IERC1155} from "openzeppelin-contracts/token/ERC1155/IERC1155.sol"; +import {IERC165} from "openzeppelin-contracts/utils/introspection/IERC165.sol"; + +import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; +import {ReentrancyGuard} from "solady/utils/ReentrancyGuard.sol"; + +import {Budget} from "contracts/references/Budget.sol"; +import {Cloneable} from "contracts/references/Cloneable.sol"; + +/// @title Simple Budget +/// @notice A minimal budget implementation that simply holds and distributes tokens (ERC20-like and native) +/// @dev This type of budget supports ETH, ERC20, and ERC1155 assets only +contract QuestBudget is Budget, IERC1155Receiver, ReentrancyGuard { + using SafeTransferLib for address; + + /// @notice The payload for initializing a SimpleBudget + struct InitPayload { + address owner; + address questFactory; + address[] authorized; + } + + // @dev The address of the QuestFactory contract + address public questFactory; + + bool public disburseEnabled; + + /// @dev The total amount of each fungible asset distributed from the budget + mapping(address => uint256) private _distributedFungible; + + /// @dev The total amount of each ERC1155 asset and token ID distributed from the budget + mapping(address => mapping(uint256 => uint256)) private _distributedERC1155; + + /// @dev The mapping of authorized addresses + mapping(address => bool) private _isAuthorized; + + /// @notice A modifier that allows only authorized addresses to call the function + modifier onlyAuthorized() { + if (!isAuthorized(msg.sender)) revert Unauthorized(); + _; + } + + /// @notice Construct a new SimpleBudget + /// @dev Because this contract is a base implementation, it should not be initialized through the constructor. Instead, it should be cloned and initialized using the {initialize} function. + constructor() { + _disableInitializers(); + } + + /// @inheritdoc Cloneable + /// @param data_ The packed init data for the budget `(address owner, address[] authorized)` + function initialize(bytes calldata data_) public virtual override initializer { + InitPayload memory init_ = abi.decode(data_, (InitPayload)); + _initializeOwner(init_.owner); + questFactory = init_.questFactory; + for (uint256 i = 0; i < init_.authorized.length; i++) { + _isAuthorized[init_.authorized[i]] = true; + } + } + + /// @inheritdoc Budget + /// @notice Allocates assets to the budget + /// @param data_ The packed data for the {Transfer} request + /// @return True if the allocation was successful + /// @dev The caller must have already approved the contract to transfer the asset + /// @dev If the asset transfer fails, the allocation will revert + function allocate(bytes calldata data_) external payable virtual override returns (bool) { + Transfer memory request = abi.decode(data_, (Transfer)); + if (request.assetType == AssetType.ETH) { + FungiblePayload memory payload = abi.decode(request.data, (FungiblePayload)); + + // Ensure the value received is equal to the `payload.amount` + if (msg.value != payload.amount) { + revert InvalidAllocation(request.asset, payload.amount); + } + } else if (request.assetType == AssetType.ERC20) { + FungiblePayload memory payload = abi.decode(request.data, (FungiblePayload)); + + // Transfer `payload.amount` of the token to this contract + request.asset.safeTransferFrom(request.target, address(this), payload.amount); + if (request.asset.balanceOf(address(this)) < payload.amount) { + revert InvalidAllocation(request.asset, payload.amount); + } + } else if (request.assetType == AssetType.ERC1155) { + ERC1155Payload memory payload = abi.decode(request.data, (ERC1155Payload)); + + // Transfer `payload.amount` of `payload.tokenId` to this contract + IERC1155(request.asset).safeTransferFrom( + request.target, address(this), payload.tokenId, payload.amount, payload.data + ); + if (IERC1155(request.asset).balanceOf(address(this), payload.tokenId) < payload.amount) { + revert InvalidAllocation(request.asset, payload.amount); + } + } else { + // Unsupported asset type + return false; + } + + return true; + } + + /// @inheritdoc Budget + /// @notice Reclaims assets from the budget + /// @param data_ The packed {Transfer} request + /// @return True if the request was successful + /// @dev Only the owner can directly reclaim assets from the budget + /// @dev If the amount is zero, the entire balance of the asset will be transferred to the receiver + /// @dev If the asset transfer fails, the reclamation will revert + function reclaim(bytes calldata data_) external virtual override onlyOwner returns (bool) { + Transfer memory request = abi.decode(data_, (Transfer)); + if (request.assetType == AssetType.ETH || request.assetType == AssetType.ERC20) { + FungiblePayload memory payload = abi.decode(request.data, (FungiblePayload)); + _transferFungible( + request.asset, request.target, payload.amount == 0 ? available(request.asset) : payload.amount + ); + } else if (request.assetType == AssetType.ERC1155) { + ERC1155Payload memory payload = abi.decode(request.data, (ERC1155Payload)); + _transferERC1155( + request.asset, + request.target, + payload.tokenId, + payload.amount == 0 ? IERC1155(request.asset).balanceOf(address(this), payload.tokenId) : payload.amount, + payload.data + ); + } else { + return false; + } + + return true; + } + + /// @notice Create an erc20 quest and start it at the same time. The function will transfer the reward amount to the quest contract + /// @param txHashChainId_ The chain id of the chain the txHash is on + /// @param rewardTokenAddress_ The contract address of the reward token + /// @param endTime_ The end time of the quest + /// @param startTime_ The start time of the quest + /// @param totalParticipants_ The total amount of participants (accounts) the quest will have + /// @param rewardAmount_ The reward amount for an erc20 quest + /// @param questId_ The id of the quest + /// @param actionType_ The action type for the quest + /// @param questName_ The name of the quest + /// @param projectName_ The name of the project/protocol used for the quest + /// @param referralRewardFee_ The fee amount for referrals. The value is counted against the `rewardAmount` + /// @return address the quest contract address + function createERC20Quest( + uint32 txHashChainId_, + address rewardTokenAddress_, + uint256 endTime_, + uint256 startTime_, + uint256 totalParticipants_, + uint256 rewardAmount_, + string memory questId_, + string memory actionType_, + string memory questName_, + string memory projectName_, + uint256 referralRewardFee_ + ) public virtual onlyAuthorized returns (address) { + uint256 maxTotalRewards = totalParticipants_ * rewardAmount_; + uint256 questFee = uint256(IQuestFactory(questFactory).questFee()); + uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000; // Assuming questFee is 2000 + uint256 approvalAmount = maxTotalRewards + maxProtocolReward; + rewardTokenAddress_.safeApprove(address(questFactory), approvalAmount); + return IQuestFactory(questFactory).createERC20Quest( + txHashChainId_, + rewardTokenAddress_, + endTime_, + startTime_, + totalParticipants_, + rewardAmount_, + questId_, + actionType_, + questName_, + projectName_, + referralRewardFee_ + ); + } + + /// @notice Cancel a quest + /// @param questId_ The uuid of the quest + function cancelQuest(string calldata questId_) public virtual onlyOwner() { + IQuestFactory(questFactory).cancelQuest(questId_); + } + + /// @inheritdoc Budget + /// @notice Disburses assets from the budget to a single recipient + /// @param data_ The packed {Transfer} request + /// @return True if the disbursement was successful + /// @dev If the asset transfer fails, the disbursement will revert + function disburse(bytes calldata data_) public virtual override onlyAuthorized returns (bool) { + if(!disburseEnabled) { + revert Unauthorized(); + } + Transfer memory request = abi.decode(data_, (Transfer)); + if (request.assetType == AssetType.ERC20 || request.assetType == AssetType.ETH) { + FungiblePayload memory payload = abi.decode(request.data, (FungiblePayload)); + + uint256 avail = available(request.asset); + if (payload.amount > avail) { + revert InsufficientFunds(request.asset, avail, payload.amount); + } + + _transferFungible(request.asset, request.target, payload.amount); + } else if (request.assetType == AssetType.ERC1155) { + ERC1155Payload memory payload = abi.decode(request.data, (ERC1155Payload)); + + uint256 avail = IERC1155(request.asset).balanceOf(address(this), payload.tokenId); + if (payload.amount > avail) { + revert InsufficientFunds(request.asset, avail, payload.amount); + } + + _transferERC1155(request.asset, request.target, payload.tokenId, payload.amount, payload.data); + } else { + return false; + } + + return true; + } + + /// @inheritdoc Budget + /// @notice Disburses assets from the budget to multiple recipients + /// @param data_ The packed array of {Transfer} requests + /// @return True if all disbursements were successful + function disburseBatch(bytes[] calldata data_) external virtual override returns (bool) { + for (uint256 i = 0; i < data_.length; i++) { + if (!disburse(data_[i])) return false; + } + + return true; + } + + /// @inheritdoc Budget + function setAuthorized(address[] calldata account_, bool[] calldata authorized_) + external + virtual + override + onlyOwner + { + if (account_.length != authorized_.length) revert LengthMismatch(); + for (uint256 i = 0; i < account_.length; i++) { + _isAuthorized[account_[i]] = authorized_[i]; + } + } + + /// @inheritdoc Budget + function isAuthorized(address account_) public view virtual override returns (bool) { + return _isAuthorized[account_] || account_ == owner(); + } + + /// @notice Set the QuestFactory contract address + /// @param questFactory_ The address of the QuestFactory contract + function setQuestFactory(address questFactory_) external virtual onlyOwner { + questFactory = questFactory_; + } + + /// @notice Set the DisburseEnabled flag + /// @param enabled_ The flag to enable or disable disburse + function setDisburseEnabled(bool enabled_) external virtual onlyOwner { + disburseEnabled = enabled_; + } + + /// @inheritdoc Budget + /// @notice Get the total amount of assets allocated to the budget, including any that have been distributed + /// @param asset_ The address of the asset + /// @return The total amount of assets + /// @dev This is simply the sum of the current balance and the distributed amount + function total(address asset_) external view virtual override returns (uint256) { + return available(asset_) + _distributedFungible[asset_]; + } + + /// @notice Get the total amount of ERC1155 assets allocated to the budget, including any that have been distributed + /// @param asset_ The address of the asset + /// @param tokenId_ The ID of the token + /// @return The total amount of assets + function total(address asset_, uint256 tokenId_) external view virtual returns (uint256) { + return IERC1155(asset_).balanceOf(address(this), tokenId_) + _distributedERC1155[asset_][tokenId_]; + } + + /// @inheritdoc Budget + /// @notice Get the amount of assets available for distribution from the budget + /// @param asset_ The address of the asset (or the zero address for native assets) + /// @return The amount of assets available + /// @dev This is simply the current balance held by the budget + /// @dev If the zero address is passed, this function will return the native balance + function available(address asset_) public view virtual override returns (uint256) { + return asset_ == address(0) ? address(this).balance : asset_.balanceOf(address(this)); + } + + /// @notice Get the amount of ERC1155 assets available for distribution from the budget + /// @param asset_ The address of the asset + /// @param tokenId_ The ID of the token + /// @return The amount of assets available + function available(address asset_, uint256 tokenId_) public view virtual returns (uint256) { + return IERC1155(asset_).balanceOf(address(this), tokenId_); + } + + /// @inheritdoc Budget + /// @notice Get the amount of assets that have been distributed from the budget + /// @param asset_ The address of the asset + /// @return The amount of assets distributed + function distributed(address asset_) external view virtual override returns (uint256) { + return _distributedFungible[asset_]; + } + + /// @notice Get the amount of ERC1155 assets that have been distributed from the budget + /// @param asset_ The address of the asset + /// @param tokenId_ The ID of the token + /// @return The amount of assets distributed + function distributed(address asset_, uint256 tokenId_) external view virtual returns (uint256) { + return _distributedERC1155[asset_][tokenId_]; + } + + /// @inheritdoc Budget + /// @dev This is a no-op as there is no local balance to reconcile + function reconcile(bytes calldata) external virtual override returns (uint256) { + return 0; + } + + /// @notice Transfer assets to the recipient + /// @param asset_ The address of the asset + /// @param to_ The address of the recipient + /// @param amount_ The amount of the asset to transfer + /// @dev This function is used to transfer assets from the budget to a given recipient (typically an incentive contract) + /// @dev If the destination address is the zero address, or the transfer fails for any reason, this function will revert + function _transferFungible(address asset_, address to_, uint256 amount_) internal virtual nonReentrant { + // Increment the total amount of the asset distributed from the budget + if (to_ == address(0)) revert TransferFailed(asset_, to_, amount_); + if (amount_ > available(asset_)) { + revert InsufficientFunds(asset_, available(asset_), amount_); + } + + _distributedFungible[asset_] += amount_; + + // Transfer the asset to the recipient + if (asset_ == address(0)) { + SafeTransferLib.safeTransferETH(to_, amount_); + } else { + asset_.safeTransfer(to_, amount_); + } + + emit Distributed(asset_, to_, amount_); + } + + function _transferERC1155(address asset_, address to_, uint256 tokenId_, uint256 amount_, bytes memory data_) + internal + virtual + nonReentrant + { + // Increment the total amount of the asset distributed from the budget + if (to_ == address(0)) revert TransferFailed(asset_, to_, amount_); + if (amount_ > available(asset_, tokenId_)) { + revert InsufficientFunds(asset_, available(asset_, tokenId_), amount_); + } + + _distributedERC1155[asset_][tokenId_] += amount_; + + // Transfer the asset to the recipient + // wake-disable-next-line reentrancy (`nonReentrant` modifier is applied to the function) + IERC1155(asset_).safeTransferFrom(address(this), to_, tokenId_, amount_, data_); + + emit Distributed(asset_, to_, amount_); + } + + /// @inheritdoc IERC1155Receiver + /// @dev This contract does not care about the specifics of the inbound token, so we simply return the magic value (i.e. the selector for `onERC1155Received`) + function onERC1155Received(address, address, uint256, uint256, bytes calldata) + external + pure + override + returns (bytes4) + { + // We don't need to do anything here + return IERC1155Receiver.onERC1155Received.selector; + } + + /// @inheritdoc IERC1155Receiver + /// @dev This contract does not care about the specifics of the inbound token, so we simply return the magic value (i.e. the selector for `onERC1155Received`) + function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) + external + pure + override + returns (bytes4) + { + // We don't need to do anything here + return IERC1155Receiver.onERC1155BatchReceived.selector; + } + + /// @inheritdoc Cloneable + function supportsInterface(bytes4 interfaceId) public view virtual override(Budget, IERC165) returns (bool) { + return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); + } +} \ No newline at end of file diff --git a/contracts/interfaces/IQuestFactory.sol b/contracts/interfaces/IQuestFactory.sol index c7b8b7f2..359acf7c 100644 --- a/contracts/interfaces/IQuestFactory.sol +++ b/contracts/interfaces/IQuestFactory.sol @@ -194,7 +194,8 @@ interface IQuestFactory { string memory actionType, string memory questName ) external pure returns (string memory); - + function questFee() external view returns (uint16); + // Create function create1155QuestAndQueue( address rewardTokenAddress_, @@ -206,8 +207,25 @@ interface IQuestFactory { string memory ) external payable returns (address); + function createERC20Quest( + uint32 txHashChainId_, + address rewardTokenAddress_, + uint256 endTime_, + uint256 startTime_, + uint256 totalParticipants_, + uint256 rewardAmount_, + string calldata questId_, + string calldata actionType_, + string calldata questName_, + string calldata projectName_, + uint256 referralRewardFee_ + ) external returns (address); + + function claimOptimized(bytes calldata signature_, bytes calldata data_) external payable; + function cancelQuest(string calldata questId_) external; + // Set function setClaimSignerAddress(address claimSignerAddress_) external; function setErc1155QuestAddress(address erc1155QuestAddress_) external; diff --git a/contracts/references/BoostError.sol b/contracts/references/BoostError.sol new file mode 100644 index 00000000..6283c9db --- /dev/null +++ b/contracts/references/BoostError.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +/// @title BoostError +/// @notice Standardized errors for the Boost protocol +/// @dev Some of these errors are introduced by third-party libraries, rather than Boost contracts directly, and are copied here for clarity and ease of testing. +library BoostError { + /// @notice Thrown when a claim attempt fails + error ClaimFailed(address caller, bytes data); + + /// @notice Thrown when there are insufficient funds for an operation + error InsufficientFunds(address asset, uint256 available, uint256 required); + + /// @notice Thrown when a non-conforming instance for a given type is encountered + error InvalidInstance(bytes4 expectedInterface, address instance); + + /// @notice Thrown when an invalid initialization is attempted + error InvalidInitialization(); + + /// @notice Thrown when the length of two arrays are not equal + error LengthMismatch(); + + /// @notice Thrown when a method is not implemented + error NotImplemented(); + + /// @notice Thrown when a previously used signature is replayed + error Replayed(address signer, bytes32 hash, bytes signature); + + /// @notice Thrown when a transfer fails for an unknown reason + error TransferFailed(address asset, address to, uint256 amount); + + /// @notice Thrown when the requested action is unauthorized + error Unauthorized(); +} \ No newline at end of file diff --git a/contracts/references/Budget.sol b/contracts/references/Budget.sol new file mode 100644 index 00000000..430ce022 --- /dev/null +++ b/contracts/references/Budget.sol @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import {Ownable} from "solady/auth/Ownable.sol"; +import {Receiver} from "solady/accounts/Receiver.sol"; +import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; + +import {BoostError} from "contracts/references/BoostError.sol"; +import {Cloneable} from "contracts/references/Cloneable.sol"; + +/// @title Boost Budget +/// @notice Abstract contract for a generic Budget within the Boost protocol +/// @dev Budget classes are expected to implement the allocation, reclamation, and disbursement of assets. +/// @dev WARNING: Budgets currently support only ETH, ERC20, and ERC1155 assets. Other asset types may be added in the future. +abstract contract Budget is Ownable, Cloneable, Receiver { + using SafeTransferLib for address; + + enum AssetType { + ETH, + ERC20, + ERC1155 + } + + /// @notice A struct representing the inputs for an allocation + /// @param assetType The type of asset to allocate + /// @param asset The address of the asset to allocate + /// @param target The address of the payee or payer (from or to, depending on the operation) + /// @param data The implementation-specific data for the allocation (amount, token ID, etc.) + struct Transfer { + AssetType assetType; + address asset; + address target; + bytes data; + } + + /// @notice The payload for an ETH or ERC20 transfer + /// @param amount The amount of the asset to transfer + struct FungiblePayload { + uint256 amount; + } + + /// @notice The payload for an ERC1155 transfer + /// @param tokenId The ID of the token to transfer + /// @param amount The amount of the token to transfer + /// @param data Any additional data to forward to the ERC1155 contract + struct ERC1155Payload { + uint256 tokenId; + uint256 amount; + bytes data; + } + + /// @notice Emitted when an address's authorization status changes + event Authorized(address indexed account, bool isAuthorized); + + /// @notice Emitted when assets are distributed from the budget + event Distributed(address indexed asset, address to, uint256 amount); + + /// @notice Thrown when the allocation is invalid + error InvalidAllocation(address asset, uint256 amount); + + /// @notice Thrown when there are insufficient funds for an operation + error InsufficientFunds(address asset, uint256 available, uint256 required); + + /// @notice Thrown when the length of two arrays are not equal + error LengthMismatch(); + + /// @notice Thrown when a transfer fails for an unknown reason + error TransferFailed(address asset, address to, uint256 amount); + + /// @notice Initialize the budget and set the owner + /// @dev The owner is set to the contract deployer + constructor() { + _initializeOwner(msg.sender); + } + + /// @notice Allocate assets to the budget + /// @param data_ The compressed data for the allocation (amount, token address, token ID, etc.) + /// @return True if the allocation was successful + function allocate(bytes calldata data_) external payable virtual returns (bool); + + /// @notice Reclaim assets from the budget + /// @param data_ The compressed data for the reclamation (amount, token address, token ID, etc.) + /// @return True if the reclamation was successful + function reclaim(bytes calldata data_) external virtual returns (bool); + + /// @notice Disburse assets from the budget to a single recipient + /// @param data_ The compressed {Transfer} request + /// @return True if the disbursement was successful + function disburse(bytes calldata data_) external virtual returns (bool); + + /// @notice Disburse assets from the budget to multiple recipients + /// @param data_ The array of compressed {Transfer} requests + /// @return True if all disbursements were successful + function disburseBatch(bytes[] calldata data_) external virtual returns (bool); + + /// @notice Get the total amount of assets allocated to the budget, including any that have been distributed + /// @param asset_ The address of the asset + /// @return The total amount of assets + function total(address asset_) external view virtual returns (uint256); + + /// @notice Get the amount of assets available for distribution from the budget + /// @param asset_ The address of the asset + /// @return The amount of assets available + function available(address asset_) external view virtual returns (uint256); + + /// @notice Get the amount of assets that have been distributed from the budget + /// @param asset_ The address of the asset + /// @return The amount of assets distributed + function distributed(address asset_) external view virtual returns (uint256); + + /// @notice Reconcile the budget to ensure the known state matches the actual state + /// @param data_ The compressed data for the reconciliation (amount, token address, token ID, etc.) + /// @return The amount of assets reconciled + function reconcile(bytes calldata data_) external virtual returns (uint256); + + /// @inheritdoc Cloneable + function supportsInterface(bytes4 interfaceId) public view virtual override(Cloneable) returns (bool) { + return interfaceId == type(Budget).interfaceId || super.supportsInterface(interfaceId); + } + + /// @notice Set the authorized status of the given accounts + /// @param accounts_ The accounts to authorize or deauthorize + /// @param isAuthorized_ The authorization status for the given accounts + /// @dev The mechanism for managing authorization is left to the implementing contract + function setAuthorized(address[] calldata accounts_, bool[] calldata isAuthorized_) external virtual; + + /// @notice Check if the given account is authorized to use the budget + /// @param account_ The account to check + /// @return True if the account is authorized + /// @dev The mechanism for checking authorization is left to the implementing contract + function isAuthorized(address account_) external view virtual returns (bool); + + /// @inheritdoc Receiver + receive() external payable virtual override { + return; + } + + /// @inheritdoc Receiver + fallback() external payable virtual override { + return; + } +} \ No newline at end of file diff --git a/contracts/references/Cloneable.sol b/contracts/references/Cloneable.sol new file mode 100644 index 00000000..59da78dc --- /dev/null +++ b/contracts/references/Cloneable.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import {Initializable} from "solady/utils/Initializable.sol"; +import {ERC165} from "openzeppelin-contracts/utils/introspection/ERC165.sol"; + +/// @title Cloneable +/// @notice A contract that can be cloned and initialized only once +abstract contract Cloneable is Initializable, ERC165 { + /// @notice Thrown when an inheriting contract does not implement the initializer function + error InitializerNotImplemented(); + + /// @notice Thrown when the provided initialization data is invalid + /// @dev This error indicates that the given data is not valid for the implementation (i.e. does not decode to the expected types) + error InvalidInitializationData(); + + /// @notice Thrown when the contract has already been initialized + error CloneAlreadyInitialized(); + + /// @notice A modifier to restrict a function to only be called before initialization + /// @dev This is intended to enforce that a function can only be called before the contract has been initialized + modifier onlyBeforeInitialization() { + if (_getInitializedVersion() != 0) revert CloneAlreadyInitialized(); + _; + } + + /// @notice Initialize the clone with the given arbitrary data + /// @param - The compressed initialization data (if required) + /// @dev The data is expected to be ABI encoded bytes compressed using {LibZip-cdCompress} + /// @dev All implementations must override this function to initialize the contract + function initialize(bytes calldata) public virtual initializer { + revert InitializerNotImplemented(); + } + + /// @inheritdoc ERC165 + /// @notice Check if the contract supports the given interface + /// @param interfaceId The interface identifier + /// @return True if the contract supports the interface + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(Cloneable).interfaceId || super.supportsInterface(interfaceId); + } +} \ No newline at end of file diff --git a/contracts/references/Mocks.sol b/contracts/references/Mocks.sol new file mode 100644 index 00000000..ac07038e --- /dev/null +++ b/contracts/references/Mocks.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import {LibString} from "solady/utils/LibString.sol"; +import {ERC20} from "solady/tokens/ERC20.sol"; +import {ERC721} from "solady/tokens/ERC721.sol"; +import {ERC1155} from "openzeppelin-contracts/token/ERC1155/ERC1155.sol"; + +/** + * 🚨 WARNING: The mocks in this file are for testing purposes only. DO NOT use + * ANY of this code in production, ever, or you will lose all of your money, + * friends, and credibility. Also, your cat might run away for fear of being + * associated with someone who makes such poor life choices. + */ + +/// @title MockERC721 +/// @notice A mock ERC721 token (FOR TESTING PURPOSES ONLY) +contract MockERC721 is ERC721 { + uint256 public totalSupply; + uint256 public mintPrice = 0.1 ether; + + function name() public pure override returns (string memory) { + return "Mock ERC721"; + } + + function symbol() public pure override returns (string memory) { + return "MOCK"; + } + + function mint(address to) public payable { + require(msg.value >= mintPrice, "MockERC721: gimme more money!"); + // pre-increment so IDs start at 1 + _mint(to, ++totalSupply); + } + + function tokenURI(uint256 id) public view virtual override returns (string memory) { + return string(abi.encodePacked("https://example.com/token/", LibString.toString(id))); + } +} + +/// @title MockERC20 +/// @notice A mock ERC20 token (FOR TESTING PURPOSES ONLY) +contract MockERC20 is ERC20 { + function name() public pure override returns (string memory) { + return "Mock ERC20"; + } + + function symbol() public pure override returns (string memory) { + return "MOCK"; + } + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } + + function mintPayable(address to, uint256 amount) public payable { + require(msg.value >= amount / 100, "MockERC20: gimme more money!"); + _mint(to, amount); + } +} + +/// @title MockERC1155 +/// @notice A mock ERC1155 token (FOR TESTING PURPOSES ONLY) +contract MockERC1155 is ERC1155 { + constructor() ERC1155("https://example.com/token/{id}") {} + + function mint(address to, uint256 id, uint256 amount) public { + _mint(to, id, amount, ""); + } + + function burn(address from, uint256 id, uint256 amount) public { + _burn(from, id, amount); + } +} \ No newline at end of file diff --git a/lib/solady b/lib/solady index fad3f670..a6e41377 160000 --- a/lib/solady +++ b/lib/solady @@ -1 +1 @@ -Subproject commit fad3f6703c2cd4cfd185f9921790d117503f54c6 +Subproject commit a6e41377a77084d6dc3cc54c34eb09e98c9f8204 diff --git a/script/QuestBudget.s.sol b/script/QuestBudget.s.sol new file mode 100644 index 00000000..8b1921f4 --- /dev/null +++ b/script/QuestBudget.s.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {QuestBudget} from "../contracts/QuestBudget.sol"; +import {QuestContractConstants as C} from "../contracts/libraries/QuestContractConstants.sol"; +import {LibClone} from "solady/utils/LibClone.sol"; + +contract QuestBudgetDeploy is Script { + function run() external { + uint256 deployerPrivateKey = vm.envUint("TEST_CLAIM_SIGNER_PRIVATE_KEY"); + address operator = vm.envAddress("MAINNET_QUEST_BUDGET_OPERATOR"); + address owner = vm.envAddress("MAINNET_QUEST_BUDGET_OWNER"); + address[] memory authorized = new address[](1); + authorized[0] = operator; // Add more authorized addresses if needed + + vm.startBroadcast(deployerPrivateKey); + + // Deploy QuestBudget + QuestBudget questBudget = QuestBudget(payable(LibClone.clone(address(new QuestBudget())))); + questBudget.initialize( + abi.encode(QuestBudget.InitPayload({owner: owner, questFactory: C.QUEST_FACTORY_ADDRESS, authorized: authorized})) + ); + vm.stopBroadcast(); + } +} \ No newline at end of file diff --git a/test/QuestBudget.t.sol b/test/QuestBudget.t.sol new file mode 100644 index 00000000..7f90f61a --- /dev/null +++ b/test/QuestBudget.t.sol @@ -0,0 +1,1011 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import {Test, console} from "lib/forge-std/src/Test.sol"; + +import {IERC1155Receiver} from "openzeppelin-contracts/token/ERC1155/IERC1155Receiver.sol"; +import {Initializable} from "solady/utils/Initializable.sol"; +import {LibClone} from "solady/utils/LibClone.sol"; +import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; +import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; +import {MockERC20, MockERC1155} from "contracts/references/Mocks.sol"; +import {QuestFactoryMock} from "./mocks/QuestFactoryMock.sol"; +import {BoostError} from "contracts/references/BoostError.sol"; +import {Budget} from "contracts/references/Budget.sol"; +import {Cloneable} from "contracts/references/Cloneable.sol"; +import {QuestBudget} from "contracts/QuestBudget.sol"; +import {IQuestFactory} from "contracts/interfaces/IQuestFactory.sol"; +import {TestUtils} from "./helpers/TestUtils.sol"; +import "forge-std/console.sol"; + +contract QuestBudgetTest is Test, TestUtils, IERC1155Receiver { + MockERC20 mockERC20; + MockERC20 otherMockERC20; + MockERC1155 mockERC1155; + QuestFactoryMock mockQuestFactory; + QuestBudget questBudget; + + event QuestCancelled(address indexed questAddress, string questId, uint256 endsAt); + + function setUp() public { + address owner = address(this); + // Deploy a new ERC20 contract and mint 100 tokens + mockERC20 = new MockERC20(); + mockERC20.mint(address(this), 100 ether); + + // Deploy a new ERC1155 contract and mint 100 of token ID 42 + mockERC1155 = new MockERC1155(); + mockERC1155.mint(address(this), 42, 100); + + // Deploy a new QuestFactoryMock contract + mockQuestFactory = new QuestFactoryMock(); + + // Deploy a new QuestBudget contract + questBudget = QuestBudget(payable(LibClone.clone(address(new QuestBudget())))); + address[] memory authorized = new address[](1); + authorized[0] = owner; + questBudget.initialize( + abi.encode(QuestBudget.InitPayload({owner: owner, questFactory: address(mockQuestFactory), authorized: authorized})) + ); + questBudget.setDisburseEnabled(true); + } + + //////////////////////////////// + // QuestBudget initial state // + //////////////////////////////// + + function test_InitialOwner() public { + // Ensure the budget has the correct owner + assertEq(questBudget.owner(), address(this)); + } + + function test_InitialDistributed() public { + // Ensure the budget has 0 tokens distributed + assertEq(questBudget.total(address(mockERC20)), 0); + } + + function test_InitialDistributed1155() public { + // Ensure the budget has 0 of our 1155 tokens distributed + assertEq(questBudget.total(address(mockERC1155), 42), 0); + } + + function test_InitialTotal() public { + // Ensure the budget has 0 tokens allocated + assertEq(questBudget.total(address(mockERC20)), 0); + } + + function test_InitialTotal1155() public { + // Ensure the budget has 0 of our 1155 tokens allocated + assertEq(questBudget.total(address(mockERC1155), 42), 0); + } + + function test_InitialAvailable() public { + // Ensure the budget has 0 tokens available + assertEq(questBudget.available(address(mockERC20)), 0); + } + + function test_InitialAvailable1155() public { + // Ensure the budget has 0 of our 1155 tokens available + assertEq(questBudget.available(address(mockERC1155), 42), 0); + } + + function test_InitializerDisabled() public { + // Because the slot is private, we use `vm.load` to access it then parse out the bits: + // - [0] is the `initializing` flag (which should be 0 == false) + // - [1..64] hold the `initializedVersion` (which should be 1) + bytes32 slot = + vm.load(address(questBudget), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf601132); + + uint64 version; + assembly { + version := shr(1, slot) + } + + assertNotEq(version, 0, "Version should not be 0"); + } + + ///////////////////////////// + // QuestBudget.initialize // + ///////////////////////////// + + function testInitialize() public { + // Initializer can only be called on clones, not the base contract + bytes memory data = abi.encode(QuestBudget.InitPayload({owner: address(this), questFactory: address(mockQuestFactory) ,authorized: new address[](0)})); + QuestBudget clone = QuestBudget(payable(LibClone.clone(address(questBudget)))); + clone.initialize(data); + + // Ensure the budget has the correct authorities + assertEq(clone.owner(), address(this)); + assertEq(clone.questFactory(), address(mockQuestFactory)); + assertEq(clone.isAuthorized(address(this)), true); + } + + function testInitialize_ImproperData() public { + // with improperly encoded data + bytes memory data = abi.encodePacked(new address[](0), address(this)); + vm.expectRevert(); + questBudget.initialize(data); + } + + /////////////////////////// + // QuestBudget.allocate // + /////////////////////////// + + function testAllocate() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + assertTrue(questBudget.allocate(data)); + + // Ensure the budget has 100 tokens + assertEq(questBudget.available(address(mockERC20)), 100 ether); + } + + function testAllocate_NativeBalance() public { + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 100 ether); + questBudget.allocate{value: 100 ether}(data); + + // Ensure the budget has 100 tokens + assertEq(questBudget.available(address(0)), 100 ether); + } + + function testAllocate_ERC1155() public { + // Approve the budget to transfer tokens + mockERC1155.setApprovalForAll(address(questBudget), true); + + // Allocate 100 of token ID 42 to the budget + bytes memory data = abi.encode( + Budget.Transfer({ + assetType: Budget.AssetType.ERC1155, + asset: address(mockERC1155), + target: address(this), + data: abi.encode(Budget.ERC1155Payload({tokenId: 42, amount: 100, data: ""})) + }) + ); + assertTrue(questBudget.allocate(data)); + + // Ensure the budget has 100 of token ID 42 + assertEq(questBudget.available(address(mockERC1155), 42), 100); + } + + function testAllocate_NativeBalanceValueMismatch() public { + // Encode an allocation of 100 ETH + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 100 ether); + + // Expect a revert due to a value mismatch (too much ETH) + vm.expectRevert(abi.encodeWithSelector(Budget.InvalidAllocation.selector, address(0), uint256(100 ether))); + questBudget.allocate{value: 101 ether}(data); + + // Expect a revert due to a value mismatch (too little ETH) + vm.expectRevert(abi.encodeWithSelector(Budget.InvalidAllocation.selector, address(0), uint256(100 ether))); + questBudget.allocate{value: 99 ether}(data); + } + + function testAllocate_NoApproval() public { + // Allocate 100 tokens to the budget without approval + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + vm.expectRevert(SafeTransferLib.TransferFromFailed.selector); + questBudget.allocate(data); + } + + function testAllocate_InsufficientFunds() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 101 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 101 ether); + vm.expectRevert(SafeTransferLib.TransferFromFailed.selector); + questBudget.allocate(data); + } + + function testAllocate_ImproperData() public { + bytes memory data; + + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // with improperly encoded data + data = abi.encodePacked(mockERC20, uint256(100 ether)); + vm.expectRevert(); + questBudget.allocate(data); + } + + /////////////////////////// + // QuestBudget.reclaim // + /////////////////////////// + + function testReclaim() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.available(address(mockERC20)), 100 ether); + + // Reclaim 99 tokens from the budget + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 99 ether); + assertTrue(questBudget.reclaim(data)); + + // Ensure the budget has 1 token left + assertEq(questBudget.available(address(mockERC20)), 1 ether); + } + + function testReclaim_NativeBalance() public { + // Allocate 100 ETH to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 100 ether); + questBudget.allocate{value: 100 ether}(data); + assertEq(questBudget.available(address(0)), 100 ether); + + // Reclaim 99 ETH from the budget + data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(1), 99 ether); + assertTrue(questBudget.reclaim(data)); + + // Ensure the budget has 1 ETH left + assertEq(questBudget.available(address(0)), 1 ether); + } + + function testReclaim_ERC1155() public { + // Approve the budget to transfer tokens + mockERC1155.setApprovalForAll(address(questBudget), true); + + // Allocate 100 of token ID 42 to the budget + bytes memory data = abi.encode( + Budget.Transfer({ + assetType: Budget.AssetType.ERC1155, + asset: address(mockERC1155), + target: address(this), + data: abi.encode(Budget.ERC1155Payload({tokenId: 42, amount: 100, data: ""})) + }) + ); + questBudget.allocate(data); + assertEq(questBudget.available(address(mockERC1155), 42), 100); + + // Reclaim 99 of token ID 42 from the budget + data = abi.encode( + Budget.Transfer({ + assetType: Budget.AssetType.ERC1155, + asset: address(mockERC1155), + target: address(this), + data: abi.encode(Budget.ERC1155Payload({tokenId: 42, amount: 99, data: ""})) + }) + ); + assertTrue(questBudget.reclaim(data)); + + // Ensure the budget has 1 of token ID 42 left + assertEq(questBudget.available(address(mockERC1155), 42), 1); + } + + function testReclaim_ZeroAmount() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.available(address(mockERC20)), 100 ether); + + // Reclaim all tokens from the budget + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 0); + assertTrue(questBudget.reclaim(data)); + + // Ensure the budget has no tokens left + assertEq(questBudget.available(address(mockERC20)), 0 ether); + } + + function testReclaim_ZeroAddress() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.available(address(mockERC20)), 100 ether); + + // Reclaim 100 tokens from the budget to address(0) + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(0), 100 ether); + vm.expectRevert( + abi.encodeWithSelector(Budget.TransferFailed.selector, address(mockERC20), address(0), uint256(100 ether)) + ); + questBudget.reclaim(data); + + // Ensure the budget has 100 tokens + assertEq(questBudget.available(address(mockERC20)), 100 ether); + } + + function testReclaim_InsufficientFunds() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Reclaim 101 tokens from the budget + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 101 ether); + vm.expectRevert( + abi.encodeWithSelector( + Budget.InsufficientFunds.selector, address(mockERC20), uint256(100 ether), uint256(101 ether) + ) + ); + questBudget.reclaim(data); + } + + function testReclaim_ImproperData() public { + bytes memory data; + + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // with improperly encoded data + data = abi.encodePacked(mockERC20, uint256(100 ether)); + vm.expectRevert(); + questBudget.reclaim(data); + } + + function testReclaim_NotOwner() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Try to reclaim 100 tokens from the budget as a non-owner + // We can reuse the data from above because the target is `address(this)` in both cases + vm.prank(address(1)); + vm.expectRevert(); + questBudget.reclaim(data); + } + + /////////////////////////// + // QuestBudget.createERC20Quest // + /////////////////////////// + function testCreateERC20Quest() public { + // Define the parameters for the new quest + uint32 txHashChainId_ = 1; + address rewardTokenAddress_ = address(mockERC20); + uint256 endTime_ = block.timestamp + 1 days; + uint256 startTime_ = block.timestamp; + uint256 totalParticipants_ = 10; + uint256 rewardAmount_ = 1 ether; + string memory questId_ = "testQuest"; + string memory actionType_ = "testAction"; + string memory questName_ = "Test Quest"; + string memory projectName_ = "Test Project"; + uint256 referralRewardFee_ = 10 ether; + + uint256 maxTotalRewards = totalParticipants_ * rewardAmount_; + uint256 questFee = uint256(mockQuestFactory.questFee()); + uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000; // Assuming questFee is 2000 + uint256 approvalAmount = maxTotalRewards + maxProtocolReward; + mockERC20.mint(address(this), approvalAmount); + // Ensure the budget has enough tokens for the reward + mockERC20.approve(address(questBudget), approvalAmount); + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), approvalAmount) + ); + + // Create the new quest + address questAddress = questBudget.createERC20Quest( + txHashChainId_, + rewardTokenAddress_, + endTime_, + startTime_, + totalParticipants_, + rewardAmount_, + questId_, + actionType_, + questName_, + projectName_, + referralRewardFee_ + ); + + // Ensure the returned quest address is not the zero address + assertTrue(questAddress != address(0)); + + // Ensure the quest contract has the correct reward amount + assertEq(IERC20(rewardTokenAddress_).balanceOf(questAddress), approvalAmount); + } + + /////////////////////////// + // QuestBudget.cancel // + /////////////////////////// + + function test_cancel() public { + // Define the parameters for the new quest + uint32 txHashChainId_ = 1; + address rewardTokenAddress_ = address(mockERC20); + uint256 endTime_ = block.timestamp + 1 days; + uint256 startTime_ = block.timestamp; + uint256 totalParticipants_ = 10; + uint256 rewardAmount_ = 1 ether; + string memory questId_ = "testQuest"; + string memory actionType_ = "testAction"; + string memory questName_ = "Test Quest"; + string memory projectName_ = "Test Project"; + uint256 referralRewardFee_ = 10 ether; + + uint256 maxTotalRewards = totalParticipants_ * rewardAmount_; + uint256 questFee = uint256(mockQuestFactory.questFee()); + uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000; // Assuming questFee is 2000 + uint256 approvalAmount = maxTotalRewards + maxProtocolReward; + mockERC20.mint(address(this), approvalAmount); + // Ensure the budget has enough tokens for the reward + mockERC20.approve(address(questBudget), approvalAmount); + bytes memory allocateBytes = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), approvalAmount); + questBudget.allocate(allocateBytes); + console.logBytes(allocateBytes); + + // Create the new quest + address questAddress = questBudget.createERC20Quest( + txHashChainId_, + rewardTokenAddress_, + endTime_, + startTime_, + totalParticipants_, + rewardAmount_, + questId_, + actionType_, + questName_, + projectName_, + referralRewardFee_ + ); + + // Ensure the returned quest address is not the zero address + assertTrue(questAddress != address(0)); + + // Ensure the quest contract has the correct reward amount + assertEq(IERC20(rewardTokenAddress_).balanceOf(questAddress), approvalAmount); + + vm.expectEmit(); + + emit QuestCancelled(questAddress, '', 0); + + questBudget.cancelQuest(''); + + } + + /////////////////////////// + // QuestBudget.disburse // + /////////////////////////// + + function testDisburse() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Disburse 100 tokens from the budget to the recipient + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(1), 100 ether); + assertTrue(questBudget.disburse(data)); + assertEq(mockERC20.balanceOf(address(1)), 100 ether); + + // Ensure the budget was drained + assertEq(questBudget.available(address(mockERC20)), 0); + assertEq(questBudget.distributed(address(mockERC20)), 100 ether); + } + + function testDisburse_NativeBalance() public { + // Allocate 100 ETH to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 100 ether); + questBudget.allocate{value: 100 ether}(data); + + // Disburse 100 ETH from the budget to the recipient + data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(1), 100 ether); + assertTrue(questBudget.disburse(data)); + assertEq(address(1).balance, 100 ether); + + // Ensure the budget was drained + assertEq(questBudget.available(address(0)), 0); + assertEq(questBudget.distributed(address(0)), 100 ether); + } + + function testDisburse_ERC1155() public { + // Approve the budget to transfer tokens + mockERC1155.setApprovalForAll(address(questBudget), true); + + // Allocate 100 of token ID 42 to the budget + bytes memory data = abi.encode( + Budget.Transfer({ + assetType: Budget.AssetType.ERC1155, + asset: address(mockERC1155), + target: address(this), + data: abi.encode(Budget.ERC1155Payload({tokenId: 42, amount: 100, data: ""})) + }) + ); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC1155), 42), 100); + + // Disburse 100 of token ID 42 from the budget to the recipient + data = abi.encode( + Budget.Transfer({ + assetType: Budget.AssetType.ERC1155, + asset: address(mockERC1155), + target: address(1), + data: abi.encode(Budget.ERC1155Payload({tokenId: 42, amount: 100, data: ""})) + }) + ); + assertTrue(questBudget.disburse(data)); + assertEq(mockERC1155.balanceOf(address(1), 42), 100); + + // Ensure the budget was drained + assertEq(questBudget.available(address(mockERC1155), 42), 0); + assertEq(questBudget.distributed(address(mockERC1155), 42), 100); + } + + function testDisburseBatch() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 50 ether); + mockERC1155.setApprovalForAll(address(questBudget), true); + + // Allocate the assets to the budget + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 50 ether) + ); + questBudget.allocate{value: 25 ether}( + _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 25 ether) + ); + questBudget.allocate(_makeERC1155Transfer(address(mockERC1155), address(this), 42, 50, bytes(""))); + assertEq(questBudget.total(address(mockERC20)), 50 ether); + assertEq(questBudget.total(address(0)), 25 ether); + assertEq(questBudget.total(address(mockERC1155), 42), 50); + + // Prepare the disbursement requests + bytes[] memory requests = new bytes[](3); + requests[0] = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(1), 25 ether); + requests[1] = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(2), 25 ether); + requests[2] = _makeERC1155Transfer(address(mockERC1155), address(3), 42, 10, bytes("")); + + // Disburse: + // 25 tokens to address(1); and + // 25 ETH to address(2); and + // 50 of token ID 42 to address(3) + assertTrue(questBudget.disburseBatch(requests)); + + // Ensure the budget sent 25 tokens to address(1) and has 25 left + assertEq(questBudget.available(address(mockERC20)), 25 ether); + assertEq(questBudget.distributed(address(mockERC20)), 25 ether); + assertEq(mockERC20.balanceOf(address(1)), 25 ether); + + // Ensure the budget sent 25 ETH to address(2) and has 0 left + assertEq(address(2).balance, 25 ether); + assertEq(questBudget.available(address(0)), 0 ether); + + // Ensure the budget sent 10 of token ID 42 to address(3) and has 40 left + assertEq(questBudget.available(address(mockERC1155), 42), 40); + } + + function testDisburse_InsufficientFunds() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Disburse 101 tokens from the budget to the recipient + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(1), 101 ether); + vm.expectRevert( + abi.encodeWithSelector( + Budget.InsufficientFunds.selector, address(mockERC20), uint256(100 ether), uint256(101 ether) + ) + ); + questBudget.disburse(data); + } + + function testDisburse_ImproperData() public { + bytes memory data; + + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // with improperly encoded data + data = abi.encode(1, mockERC20, uint256(100 ether)); + vm.expectRevert(); + questBudget.disburse(data); + } + + function testDisburse_NotOwner() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Try to disburse 100 tokens from the budget as a non-owner + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(0xdeadbeef), 100 ether); + vm.prank(address(0xc0ffee)); + vm.expectRevert(); + questBudget.disburse(data); + } + + function testDisburse_FailedTransfer() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Mock the ERC20 transfer to fail in an unexpected way + vm.mockCallRevert( + address(mockERC20), + abi.encodeWithSelector(bytes4(keccak256("transfer(address,uint256)")), address(1), 100 ether), + unicode"WeïrdÊrrör(ツ)" + ); + + // Try to disburse 100 tokens from the budget + data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(1), 100 ether); + vm.expectRevert(SafeTransferLib.TransferFailed.selector); + questBudget.disburse(data); + } + + function testDisburse_FailedTransferInBatch() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether); + questBudget.allocate(data); + assertEq(questBudget.total(address(mockERC20)), 100 ether); + + // Prepare the disbursement data + bytes[] memory requests = new bytes[](3); + requests[0] = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(1), 25 ether); + requests[1] = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(2), 50 ether); + requests[2] = _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(3), 10 ether); + + // Mock the second ERC20 transfer to fail in an unexpected way + vm.mockCallRevert( + address(mockERC20), + abi.encodeWithSelector(bytes4(keccak256("transfer(address,uint256)")), address(2), 50 ether), + unicode"WeïrdÊrrör(ツ)" + ); + + // Try to disburse 25 tokens to address(1) and 50 tokens to address(2) + vm.expectRevert(SafeTransferLib.TransferFailed.selector); + questBudget.disburseBatch(requests); + } + + //////////////////////// + // QuestBudget.total // + //////////////////////// + + function testTotal() public { + // Ensure the budget has 0 tokens + assertEq(questBudget.total(address(mockERC20)), 0); + + // Allocate 100 tokens to the budget + mockERC20.approve(address(questBudget), 100 ether); + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether) + ); + + // Ensure the budget has 100 tokens + assertEq(questBudget.total(address(mockERC20)), 100 ether); + } + + function testTotal_NativeBalance() public { + // Ensure the budget has 0 tokens + assertEq(questBudget.total(address(0)), 0); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 100 ether); + questBudget.allocate{value: 100 ether}(data); + + // Ensure the budget has 100 tokens + assertEq(questBudget.total(address(0)), 100 ether); + } + + function testTotal_SumOfAvailAndDistributed() public { + // We'll send two allocations of 100 tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 50 tokens to the budget + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 50 ether) + ); + + // Disburse 25 tokens from the budget to the recipient + questBudget.disburse(_makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(1), 25 ether)); + + // Allocate another 50 tokens to the budget + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 50 ether) + ); + + // Ensure the budget has 50 - 25 + 50 = 75 tokens + assertEq(questBudget.available(address(mockERC20)), 75 ether); + + // Ensure the budget has 25 tokens distributed + assertEq(questBudget.distributed(address(mockERC20)), 25 ether); + + // Ensure the total is 75 available + 25 distributed = 100 tokens + assertEq(questBudget.total(address(mockERC20)), 100 ether); + } + + + + //////////////////////////// + // QuestBudget.available // + //////////////////////////// + + function testAvailable() public { + // Ensure the budget has 0 tokens available + assertEq(questBudget.available(address(mockERC20)), 0); + + // Allocate 100 tokens to the budget + mockERC20.approve(address(questBudget), 100 ether); + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether) + ); + + // Ensure the budget has 100 tokens available + assertEq(questBudget.available(address(mockERC20)), 100 ether); + } + + function testAvailable_NativeBalance() public { + // Ensure the budget has 0 tokens available + assertEq(questBudget.available(address(0)), 0); + + // Allocate 100 tokens to the budget + bytes memory data = _makeFungibleTransfer(Budget.AssetType.ETH, address(0), address(this), 100 ether); + questBudget.allocate{value: 100 ether}(data); + + // Ensure the budget has 100 tokens available + assertEq(questBudget.available(address(0)), 100 ether); + } + + function testAvailable_NeverAllocated() public { + // Ensure the budget has 0 tokens available + assertEq(questBudget.available(address(otherMockERC20)), 0); + } + + ////////////////////////////// + // QuestBudget.distributed // + ////////////////////////////// + + function testDistributed() public { + // Ensure the budget has 0 tokens distributed + assertEq(questBudget.distributed(address(mockERC20)), 0); + + // Allocate 100 tokens to the budget + mockERC20.approve(address(questBudget), 100 ether); + questBudget.allocate( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether) + ); + + // Disburse 50 tokens from the budget to the recipient + questBudget.disburse( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 50 ether) + ); + + // Ensure the budget has 50 tokens distributed + assertEq(questBudget.distributed(address(mockERC20)), 50 ether); + + // Disburse 25 more tokens from the budget to the recipient + questBudget.disburse( + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 25 ether) + ); + + // Ensure the budget has 75 tokens distributed + assertEq(questBudget.distributed(address(mockERC20)), 75 ether); + } + + //////////////////////////// + // QuestBudget.reconcile // + //////////////////////////// + + function testReconcile() public { + // QuestBudget does not implement reconcile + assertEq(questBudget.reconcile(""), 0); + } + + //////////////////////////////// + // QuestBudget.setAuthorized // + //////////////////////////////// + + function testSetAuthorized() public { + // Ensure the budget authorizes an account + address[] memory accounts = new address[](1); + bool[] memory authorized = new bool[](1); + accounts[0] = address(0xc0ffee); + authorized[0] = true; + questBudget.setAuthorized(accounts, authorized); + assertTrue(questBudget.isAuthorized(address(0xc0ffee))); + assertFalse(questBudget.isAuthorized(address(0xdeadbeef))); + } + + function testSetAuthorized_NotOwner() public { + // Ensure the budget does not authorize an account if not called by the owner + vm.prank(address(0xdeadbeef)); + + address[] memory accounts = new address[](1); + bool[] memory authorized = new bool[](1); + accounts[0] = address(0xc0ffee); + authorized[0] = true; + + vm.expectRevert(BoostError.Unauthorized.selector); + questBudget.setAuthorized(accounts, authorized); + } + + function testSetAuthorized_LengthMismatch() public { + address[] memory accounts = new address[](1); + bool[] memory authorized = new bool[](2); + + vm.expectRevert(Budget.LengthMismatch.selector); + questBudget.setAuthorized(accounts, authorized); + } + + /////////////////////////////// + // QuestBudget.isAuthorized // + /////////////////////////////// + + function testIsAuthorized() public { + address[] memory accounts = new address[](1); + bool[] memory authorized = new bool[](1); + accounts[0] = address(0xc0ffee); + authorized[0] = true; + questBudget.setAuthorized(accounts, authorized); + + assertTrue(questBudget.isAuthorized(address(0xc0ffee))); + assertFalse(questBudget.isAuthorized(address(0xdeadbeef))); + } + + function testIsAuthorized_Owner() public { + assertTrue(questBudget.isAuthorized(address(this))); + } + + //////////////////////////////////// + // QuestBudget.supportsInterface // + //////////////////////////////////// + + function testSupportsInterface() public { + // Ensure the contract supports the Budget interface + assertTrue(questBudget.supportsInterface(type(Budget).interfaceId)); + } + + function testSupportsInterface_NotSupported() public { + // Ensure the contract does not support an unsupported interface + assertFalse(questBudget.supportsInterface(type(Test).interfaceId)); + } + + //////////////////////////// + // QuestBudget.fallback // + //////////////////////////// + + function testFallback() public { + // Ensure the fallback is payable + (bool success,) = payable(questBudget).call{value: 1 ether}(""); + assertTrue(success); + } + + function testFallback_CompressedFunctionCall() public { + // Approve the budget to transfer tokens + mockERC20.approve(address(questBudget), 100 ether); + + // Allocate 100 tokens to the budget + bytes memory data = abi.encodeWithSelector( + QuestBudget.allocate.selector, + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether) + ); + + (bool success,) = payable(questBudget).call(data); + assertTrue(success, "Fallback function failed"); + + // Ensure the budget has 100 tokens + assertEq(questBudget.total(address(mockERC20)), 100 ether); + } + + function testFallback_NoSuchFunction() public { + // This test is weirdly slow and burns the entire block gas limit, so + // I'm skipping it for now to avoid slowing down the test suite. Maybe + // we can revisit this later... or maybe the case is irrelevant. + vm.skip(true); + + // Ensure the call is not successful due to a non-existent function + // Note that the function itself will revert, but because we're issuing + // a low-level call, the revert won't bubble up. Instead, we are just + // checking that the low-level call was not successful. + (bool success,) = payable(questBudget).call{value: 1 ether}( + abi.encodeWithSelector( + bytes4(0xdeadbeef), + _makeFungibleTransfer(Budget.AssetType.ERC20, address(mockERC20), address(this), 100 ether) + ) + ); + assertFalse(success); + } + + /////////////////////////// + // QuestBudget.receive // + /////////////////////////// + + function testReceive() public { + // Ensure the receive function catches non-fallback ETH transfers + (bool success,) = payable(questBudget).call{value: 1 ether}(""); + assertTrue(success); + assertEq(questBudget.available(address(0)), 1 ether); + } + + /////////////////////////// + // Test Helper Functions // + /////////////////////////// + + function _makeFungibleTransfer(Budget.AssetType assetType, address asset, address target, uint256 value) + internal + pure + returns (bytes memory) + { + Budget.Transfer memory transfer; + transfer.assetType = assetType; + transfer.asset = asset; + transfer.target = target; + if (assetType == Budget.AssetType.ETH || assetType == Budget.AssetType.ERC20) { + transfer.data = abi.encode(Budget.FungiblePayload({amount: value})); + } else if (assetType == Budget.AssetType.ERC1155) { + // we're not actually handling this case yet, so hardcoded token ID of 1 is fine + transfer.data = abi.encode(Budget.ERC1155Payload({tokenId: 1, amount: value, data: ""})); + } + + return abi.encode(transfer); + } + + function _makeERC1155Transfer(address asset, address target, uint256 tokenId, uint256 value, bytes memory data) + internal + pure + returns (bytes memory) + { + Budget.Transfer memory transfer; + transfer.assetType = Budget.AssetType.ERC1155; + transfer.asset = asset; + transfer.target = target; + transfer.data = abi.encode(Budget.ERC1155Payload({tokenId: tokenId, amount: value, data: data})); + + return abi.encode(transfer); + } + + function onERC1155Received(address, address, uint256, uint256, bytes calldata) + external + pure + override + returns (bytes4) + { + return IERC1155Receiver.onERC1155Received.selector; + } + + function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) + external + pure + override + returns (bytes4) + { + return IERC1155Receiver.onERC1155BatchReceived.selector; + } + + function supportsInterface(bytes4 interfaceId) external pure returns (bool) { + return interfaceId == type(IERC1155Receiver).interfaceId; + } +} \ No newline at end of file diff --git a/test/mocks/QuestFactoryMock.sol b/test/mocks/QuestFactoryMock.sol index 659f1727..0d6c5bdf 100644 --- a/test/mocks/QuestFactoryMock.sol +++ b/test/mocks/QuestFactoryMock.sol @@ -1,10 +1,29 @@ // SPDX-License-Identifier: Unlicense pragma solidity 0.8.19; +import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; + contract QuestFactoryMock { uint256 numberMinted; uint256 public mintFee; + struct QuestData { + uint32 txHashChainId; + address rewardTokenAddress; + uint256 endTime; + uint256 startTime; + uint256 totalParticipants; + uint256 rewardAmount; + string questId; + string actionType; + string questName; + string questType; + string projectName; + uint256 referralRewardFee; + } + + QuestData public questData; + event MintFeePaid( string questId, address protocolFeeRecipient, @@ -15,6 +34,9 @@ contract QuestFactoryMock { uint256 tokenId ); + event QuestCancelled(address indexed questAddress, string questId, uint256 endsAt); + + function setNumberMinted(uint256 numberminted_) external { numberMinted = numberminted_; } @@ -34,4 +56,52 @@ contract QuestFactoryMock { function getAddressMinted(string memory, address) external pure returns (bool) { return false; } + + function questFee() external view returns (uint16) { + return 2000; + } + + + function createERC20Quest( + uint32 txHashChainId_, + address rewardTokenAddress_, + uint256 endTime_, + uint256 startTime_, + uint256 totalParticipants_, + uint256 rewardAmount_, + string memory questId_, + string memory actionType_, + string memory questName_, + string memory projectName_, + uint256 referralRewardFee_ + ) external returns (address) { + uint256 maxTotalRewards = totalParticipants_ * rewardAmount_; + uint256 maxProtocolReward = (maxTotalRewards * 2000) / 10_000; // Assuming questFee is 2000 + uint256 approvalAmount = maxTotalRewards + maxProtocolReward; + questData = QuestData({ + txHashChainId: txHashChainId_, + rewardTokenAddress: rewardTokenAddress_, + endTime: endTime_, + startTime: startTime_, + totalParticipants: totalParticipants_, + rewardAmount: rewardAmount_, + questId: questId_, + actionType: actionType_, + questName: questName_, + questType: "erc20", + projectName: projectName_, + referralRewardFee: referralRewardFee_ + }); + + // Transfer rewardAmount_ tokens from the caller to this contract + require(IERC20(rewardTokenAddress_).transferFrom(msg.sender, address(this), approvalAmount), "Transfer failed"); + + // Return this contract's address as the "created" quest contract + return address(this); + } + + function cancelQuest(string calldata questId_) external { + emit QuestCancelled(address(this), '', 0); + } + }