Address Contract Verified
Address
0xe66d89731986F0647bC0367C3cd1aA23368527A1
Balance
0 ETH
Nonce
1
Code Size
9347 bytes
Creator
0x90933cd3...DdDE at tx 0xed346d02...c6fe58
Indexed Transactions
0
Contract Bytecode
9347 bytes
0x60806040526004361015610011575f80fd5b5f3560e01c80630d35b4151461021f578063111ecdad1461021a57806313137d6514610215578063134d4f2514610210578063156a0d0f1461020b57806317442b70146102065780631f5e1334146101c05780633400288b146102015780633b6f743b146101fc57806352ae2879146101f75780635535d461146101f25780635a0dfe4d146101ed5780635e280f11146101e85780636fc1b31e146101e3578063715018a6146101de5780637d25a05e146101d957806382413eac146101d4578063857749b0146101cf5780638da5cb5b146101ca578063963efcaa146101c55780639f68b964146101c0578063b731ea0a146101bb578063b98bd070146101b6578063bb0b6a53146101b1578063bc70b354146101ac578063bd815db0146101a7578063c7c7f5b3146101a2578063ca5eb5e11461019d578063d045a0dc14610198578063d424388514610193578063f2fde38b1461018e578063fc0c546a146101895763ff7bd03d14610184575f80fd5b61162b565b6115e7565b611559565b6114e9565b611390565b6112ff565b611173565b610fd6565b610f82565b610f49565b610e6c565b610df8565b6106ff565b610dbe565b610d97565b610d7c565b610d1e565b610cf8565b610ca1565b610c31565b610bed565b610ba7565b610b3d565b610979565b6107b7565b610728565b6106de565b6106b8565b61069d565b6104b4565b6103d7565b610325565b908160e09103126102325790565b5f80fd5b5f5b8381106102475750505f910152565b8181015183820152602001610238565b9060209161027081518092818552858086019101610236565b601f01601f1916010190565b9392916102978560a081019360208091805184520151910152565b60409160a06040870152815180915260c086019160c08260051b880101936020809201935f915b8483106102e6575050505050509060606102e49294019060208091805184520151910152565b565b90919293949584806103156001938d60bf1990820301875285838c518051845201519181858201520190610257565b98019301930191949392906102be565b34610232576020366003190112610232576001600160401b0360043581811161023257610356903690600401610224565b9061035f61169b565b5061036861169b565b5060405190610376826109ff565b5f825260208201526103c96103ad6040519361039185610a4d565b5f855261039d816116ca565b50604060608201359101356119e7565b6103b561166f565b91825260208201526040519384938461027c565b0390f35b5f91031261023257565b34610232575f366003190112610232576004546040516001600160a01b039091168152602090f35b606090600319011261023257600490565b9181601f84011215610232578235916001600160401b038311610232576020838186019501011161023257565b6001600160a01b0381160361023257565b600319810160e081126102325760601361023257600491606435916001600160401b0390608435828111610232578161048991600401610410565b9390939260a4356104998161043d565b9260c435918211610232576104b091600401610410565b9091565b6104bd3661044e565b50929492506001600160a01b039190507f0000000000000000000000001a44076050125825900e736c501f859c50fe728c82163381036106855783356105028161071a565b61050b81611a41565b90602086013580920361065057505061053361052783886120ef565b6001600160a01b031690565b91610559610549610544838a6120fb565b61210d565b610552876116ca565b5084612141565b8097602883116105a9575b505050506105a46105825f8051602061242e833981519152946116ca565b956040519384931696836020909392919363ffffffff60408201951681520152565b0390a3005b906105d492916105ce6105be60408a01611a77565b936105c88a6116ca565b926121eb565b92612207565b90803b1561023257604051633e5ac80960e11b8152915f918391829084908290610603908c8a60048501611a81565b03925af1801561064b575f8051602061242e833981519152946105a49261058292610632575b88919650610564565b8061063f61064592610a3a565b806103cd565b5f610629565b611930565b6106598161071a565b60405163309afaf360e21b815263ffffffff9190911660048201526024810191909152604490fd5b0390fd5b6040516391ac5e4f60e01b8152336004820152602490fd5b34610232575f36600319011261023257602060405160028152f35b34610232575f366003190112610232576040805162b9270b60e21b815260016020820152f35b34610232575f36600319011261023257604080516001815260026020820152f35b34610232575f36600319011261023257602060405160018152f35b63ffffffff81160361023257565b34610232576040366003190112610232577f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b6004356107668161071a565b60243590610772611aab565b63ffffffff81165f5260016020528160405f20556107a8604051928392836020909392919363ffffffff60408201951681520152565b0390a1005b8015150361023257565b3461023257604080600319360112610232576004356001600160401b038111610232576107e8903690600401610224565b906024356107f5816107ad565b6107fd61169b565b50606083013583359361080f8561071a565b6108457f000000000000000000000000000000000000000000000000000000e8d4a5100061084081878501356120aa565b6120c8565b9180831061095c575083926108616108d096936108b593611b10565b9061086b8561071a565b61087361169b565b5061087d85611a41565b5061088785611a41565b61089e61089261167c565b63ffffffff9097168752565b602086015285850152606084015215156080830152565b815180948192631bb8518b60e31b8352309060048401611c5a565b03817f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03165afa90811561064b576103c9925f9261092d575b505191829182815181526020918201519181019190915260400190565b8161094e9293503d8411610955575b6109468183610a68565b810190611c46565b905f610910565b503d61093c565b826044918651916371c4efed60e01b835260048301526024820152fd5b34610232575f366003190112610232576020604051308152f35b6024359061ffff8216820361023257565b359061ffff8216820361023257565b90600182811c921680156109e1575b60208310146109cd57565b634e487b7160e01b5f52602260045260245ffd5b91607f16916109c2565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b03821117610a1a57604052565b6109eb565b606081019081106001600160401b03821117610a1a57604052565b6001600160401b038111610a1a57604052565b602081019081106001600160401b03821117610a1a57604052565b90601f801991011681019081106001600160401b03821117610a1a57604052565b9060405191825f8254610a9b816109b3565b908184526020946001916001811690815f14610b075750600114610ac9575b5050506102e492500383610a68565b5f90815285812095935091905b818310610aef5750506102e493508201015f8080610aba565b85548884018501529485019487945091830191610ad6565b925050506102e494925060ff191682840152151560051b8201015f8080610aba565b906020610b3a928181520190610257565b90565b34610232576040366003190112610232576103c9610b93610b8e600435610b638161071a565b63ffffffff610b70610993565b91165f52600360205260405f209061ffff165f5260205260405f2090565b610a89565b604051918291602083526020830190610257565b34610232576040366003190112610232576020610be3600435610bc98161071a565b6024359063ffffffff165f52600160205260405f20541490565b6040519015158152f35b34610232575f366003190112610232576040517f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03168152602090f35b34610232576020366003190112610232577ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d44141976020600435610c718161043d565b610c79611aab565b600480546001600160a01b0319166001600160a01b03929092169182179055604051908152a1005b34610232575f36600319011261023257610cb9611aab565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461023257604036600319011261023257610d1460043561071a565b60206040515f8152f35b346102325760a036600319011261023257610d38366103ff565b506064356001600160401b03811161023257610d58903690600401610410565b50506020608435610d688161043d565b6040516001600160a01b0390911630148152f35b34610232575f36600319011261023257602060405160068152f35b34610232575f366003190112610232575f546040516001600160a01b039091168152602090f35b34610232575f3660031901126102325760206040517f000000000000000000000000000000000000000000000000000000e8d4a510008152f35b34610232575f366003190112610232576002546040516001600160a01b039091168152602090f35b906020600319830112610232576004356001600160401b039283821161023257806023830112156102325781600401359384116102325760248460051b83010111610232576024019190565b3461023257610e7a36610e20565b90610e83611aab565b610e8c826116b3565b906040610e9c6040519384610a68565b8383526020938484019060051b8301923684116102325780915b848310610ec857610ec686611e84565b005b6001600160401b039083358281116102325783019160608336031261023257855192610ef384610a1f565b8035610efe8161071a565b8452610f0b8a82016109a4565b8a8501528681013591821161023257019036601f83011215610232578892610f3a8493369085813591016116ef565b87820152815201920191610eb6565b346102325760203660031901126102325763ffffffff600435610f6b8161071a565b165f526001602052602060405f2054604051908152f35b3461023257606036600319011261023257600435610f9f8161071a565b610fa7610993565b604435906001600160401b038211610232576103c992610fce610b93933690600401610410565b929091611791565b610fdf36610e20565b5f5b81811061104a57604051638e9e709960e01b81525f81600481335afa801561064b57610681915f91611028575b50604051638351eea760e01b815291829160048301610b29565b61104491503d805f833e61103c8183610a68565b81019061193b565b8261100e565b611055818385611841565b90611085611081611065846116ca565b60208501359063ffffffff165f52600160205260405f20541490565b1590565b61111957611097610100830183611869565b926110a460e0820161189b565b906110b3610120820182611869565b959095303b15610232575f946110e860c092604051998a9788968795633411683760e21b875260a08a01358a600489016118b6565b03920135305af191821561064b57600192611106575b505b01610fe1565b8061063f61111392610a3a565b5f6110fe565b60019150611100565b9160806102e4929493611162604060c0830197805184526001600160401b0360208201511660208501520151604083019060208091805184520151910152565b019060208091805184520151910152565b6080366003190112610232576004356001600160401b0381116102325761119e903690600401610224565b6040366023190112610232576064356111b68161043d565b6111be611999565b506111c761169b565b506060820135906111d8833561071a565b61120a7f000000000000000000000000000000000000000000000000000000e8d4a510006108408160408701356120aa565b918083106112e15750611266906112438330337f000000000000000000000000767fe9edc9e0df98e07454847909b5e959d7ca0e6122ef565b61124d8385611b10565b611256866116ca565b91611260366119bf565b92611fba565b9061126f61166f565b928184528160208501527f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a6112cf6112a88551936116ca565b936040519181839233978460409194939263ffffffff606083019616825260208201520152565b0390a36103c960405192839283611122565b82604491604051916371c4efed60e01b835260048301526024820152fd5b34610232575f60203660031901126102325760043561131d8161043d565b611325611aab565b6001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81169190823b156102325760245f9283604051958694859363ca5eb5e160e01b85521660048401525af1801561064b57611386575080f35b610ec69150610a3a565b6113993661044e565b50505092903033036114d7576113b261052785836120ef565b936113d36113c361054483856120fb565b6113cc856116ca565b5086612141565b9160288211611422575b50506113f65f8051602061242e833981519152926116ca565b6040805163ffffffff909216825260208201929092526001600160a01b039094169390819081016105a4565b9082611441926105ce61143760408801611a77565b936105c8886116ca565b917f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316803b1561023257604051633e5ac80960e11b8152935f91859182908490829061149a908b8d60048501611a81565b03925af190811561064b575f8051602061242e833981519152936113f6926114c4575b50926113dd565b8061063f6114d192610a3a565b5f6114bd565b60405163029a949d60e31b8152600490fd5b34610232576020366003190112610232577fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776060206004356115298161043d565b611531611aab565b600280546001600160a01b0319166001600160a01b03929092169182179055604051908152a1005b34610232576020366003190112610232576004356115768161043d565b61157e611aab565b6001600160a01b039081169081156115cf575f54826bffffffffffffffffffffffff60a01b8216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b604051631e4fbdf760e01b81525f6004820152602490fd5b34610232575f366003190112610232576040517f000000000000000000000000767fe9edc9e0df98e07454847909b5e959d7ca0e6001600160a01b03168152602090f35b34610232576060366003190112610232576020611647366103ff565b63ffffffff81356116578161071a565b165f526001825260405f205482604051920135148152f35b604051906102e4826109ff565b6040519060a082018281106001600160401b03821117610a1a57604052565b604051906116a8826109ff565b5f6020838281520152565b6001600160401b038111610a1a5760051b60200190565b35610b3a8161071a565b6001600160401b038111610a1a57601f01601f191660200190565b9291926116fb826116d4565b916117096040519384610a68565b829481845281830111610232578281602093845f960137010152565b602090836102e49395949560405196836117488995518092888089019101610236565b84019185830137015f83820152038085520183610a68565b908060209392818452848401375f828201840152601f01601f1916010190565b916020610b3a938181520191611760565b6117bb9163ffffffff610b8e92165f52600360205260405f209061ffff165f5260205260405f2090565b80511561182157821561181b5760028310156117ee5750610681604051928392639a6d49cd60e01b845260048401611780565b6118016117fc3685856116ef565b611f40565b8260021161023257610b3a92600119019160020190611725565b91505090565b50610b3a9136916116ef565b634e487b7160e01b5f52603260045260245ffd5b91908110156118645760051b8101359061013e1981360301821215610232570190565b61182d565b903590601e198136030182121561023257018035906001600160401b0382116102325760200191813603831361023257565b35610b3a8161043d565b6001600160401b0381160361023257565b929093611912926001600160401b036040610b3a9a98999763ffffffff81356118de8161071a565b1688526020810135602089015201356118f6816118a5565b166040860152606085015260e0608085015260e0840191611760565b6001600160a01b0390941660a082015280840360c090910152611760565b6040513d5f823e3d90fd5b602081830312610232578051906001600160401b038211610232570181601f8201121561023257805161196d816116d4565b9261197b6040519485610a68565b8184526020828401011161023257610b3a9160208085019101610236565b604051906119a682610a1f565b815f81525f602082015260406119ba61169b565b910152565b604090602319011261023257604051906119d8826109ff565b60243582526044356020830152565b611a16906108407f000000000000000000000000000000000000000000000000000000e8d4a5100080926120aa565b918291808410611a235750565b83604491604051916371c4efed60e01b835260048301526024820152fd5b63ffffffff16805f52600160205260405f2054908115611a5f575090565b6024906040519063f6ff4fb760e01b82526004820152fd5b35610b3a816118a5565b610b3a939260809260018060a01b0316825260208201525f60408201528160608201520190610257565b5f546001600160a01b03163303611abe57565b60405163118cdaa760e01b8152336004820152602490fd5b908160209103126102325751610b3a816107ad565b9091611b02610b3a93604084526040840190610257565b916020818403910152610257565b9091611b74611b52611b46611b9a957f000000000000000000000000000000000000000000000000000000e8d4a51000906120aa565b6001600160401b031690565b611b69611b6260a0860186611869565b36916116ef565b906020850135612264565b93909283945f14611c16576002905b610fce611b8f826116ca565b916080810190611869565b60045490926001600160a01b03909116908382611bb657505050565b60405163043a78eb60e01b815292602092849283918291611bda9160048401611aeb565b03915afa801561064b57611beb5750565b611c0c9060203d602011611c0f575b611c048183610a68565b810190611ad6565b50565b503d611bfa565b600190611b83565b919082604091031261023257604051611c36816109ff565b6020808294805184520151910152565b9060408282031261023257610b3a91611c1e565b906020909392936040835263ffffffff81511660408401528181015160608401526080611cae611c98604084015160a08488015260e0870190610257565b6060840151868203603f190160a0880152610257565b910151151560c08401526001600160a01b03909416910152565b80518210156118645760209160051b010190565b601f8211611ce957505050565b5f5260205f20906020601f840160051c83019310611d21575b601f0160051c01905b818110611d16575050565b5f8155600101611d0b565b9091508190611d02565b91909182516001600160401b038111610a1a57611d5281611d4c84546109b3565b84611cdc565b602080601f8311600114611d9357508190611d849394955f92611d88575b50508160011b915f199060031b1c19161790565b9055565b015190505f80611d70565b90601f19831695611da7855f5260205f2090565b925f905b888210611de257505083600195969710611dca575b505050811b019055565b01515f1960f88460031b161c191690555f8080611dc0565b80600185968294968601518155019501930190611dab565b6020808201908083528351809252604092604081018260408560051b8401019601945f925b858410611e30575050505050505090565b909192939495968580611e73600193603f198682030188528b518760609163ffffffff815116845261ffff86820151168685015201519181898201520190610257565b990194019401929594939190611e1f565b5f5b8151811015611f0957600190611f036040611ead81611ea58588611cc8565b510151611f40565b611efe81611ebb8588611cc8565b5101519163ffffffff611ece8689611cc8565b5151165f5261ffff602091600383525f2091611eea878a611cc8565b5101511661ffff165f5260205260405f2090565b611d2b565b01611e86565b50611f3b7fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6749160405191829182611dfa565b0390a1565b600361ffff60028301511603611f535750565b604051639a6d49cd60e01b815260206004820152908190610681906024830190610257565b9060808282031261023257611fb2906040805193611f9585610a1f565b805185526020810151611fa7816118a5565b602086015201611c1e565b604082015290565b612017608094926120339694611fce611999565b506020611fdb8651612359565b95019182518061209b575b50611ff085611a41565b925115159261200061089261167c565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b845260048401611c5a565b03917f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b03165af190811561064b575f91612072575090565b610b3a915060803d608011612094575b61208c8183610a68565b810190611f78565b503d612082565b6120a49061237b565b5f611fe6565b81156120b4570490565b634e487b7160e01b5f52601260045260245ffd5b818102929181159184041417156120db57565b634e487b7160e01b5f52601160045260245ffd5b90602011610232573590565b90602811610232576020013560c01c90565b610b3a906001600160401b037f000000000000000000000000000000000000000000000000000000e8d4a5100091166120c8565b60405163a9059cbb60e01b5f9081526001600160a01b0392831660045260248490529091907f000000000000000000000000767fe9edc9e0df98e07454847909b5e959d7ca0e9060209060448180855af160015f51148116156121cc575b83604052156121ae5750505090565b635274afe760e01b8352166001600160a01b03166004820152602490fd5b60018115166121e257813b15153d15161661219f565b833d5f823e3d90fd5b908060281161023257610b3a91369160271901906028016116ef565b604c9193610b3a936040519586936001600160401b0360c01b9060c01b16602085015263ffffffff60e01b9060e01b166028840152602c8301526122548151809260208686019101610236565b810103602c810184520182610a68565b825115801593906122c2576122bf9160689160405194859260208401526001600160401b0360c01b9060c01b1660408301523360488301526122af8151809260208686019101610236565b8101036048810184520182610a68565b91565b50906040519160208301526001600160401b0360c01b9060c01b166040820152602881526122bf81610a1f565b6040516323b872dd60e01b5f9081526001600160a01b03938416600452938316602452604494909452909160209060648180855af160015f5114811615612343575b836040525f606052156121ae57505050565b60018115166121e257813b15153d151616612331565b8034036123635790565b6040516304fb820960e51b8152346004820152602490fd5b60405163393f876560e21b81526001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81169291602081600481875afa90811561064b575f916123f2575b50169182156123e0576102e49233906122ef565b6040516329b99a9560e11b8152600490fd5b90506020813d602011612425575b8161240d60209383610a68565b81010312610232575161241f8161043d565b5f6123cc565b3d915061240056feefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9ca264697066735822122038c6f54941bd5459d053fe23d98f252fea6672bfd0fa78415e7613d45c4af41c64736f6c63430008160033
Verified Source Code Full Match
Compiler: v0.8.22+commit.4fc1097e
EVM: shanghai
Optimization: Yes (200 runs)
Base.sol 35 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
import {StdStorage} from "./StdStorage.sol";
import {Vm, VmSafe} from "./Vm.sol";
abstract contract CommonBase {
// Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
// console.sol and console2.sol work by executing a staticcall to this address.
address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
// Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
// Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.
address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller"))));
// Address of the test contract, deployed by the DEFAULT_SENDER.
address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
// Deterministic deployment address of the Multicall3 contract.
address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
// The order of the secp256k1 curve.
uint256 internal constant SECP256K1_ORDER =
115792089237316195423570985008687907852837564279074904382605163141518161494337;
uint256 internal constant UINT256_MAX =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
Vm internal constant vm = Vm(VM_ADDRESS);
StdStorage internal stdstore;
}
abstract contract TestBase is CommonBase {}
abstract contract ScriptBase is CommonBase {
VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
}
Script.sol 27 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
// 💬 ABOUT
// Forge Std's default Script.
// 🧩 MODULES
import {console} from "./console.sol";
import {console2} from "./console2.sol";
import {safeconsole} from "./safeconsole.sol";
import {StdChains} from "./StdChains.sol";
import {StdCheatsSafe} from "./StdCheats.sol";
import {stdJson} from "./StdJson.sol";
import {stdMath} from "./StdMath.sol";
import {StdStorage, stdStorageSafe} from "./StdStorage.sol";
import {StdStyle} from "./StdStyle.sol";
import {StdUtils} from "./StdUtils.sol";
import {VmSafe} from "./Vm.sol";
// 📦 BOILERPLATE
import {ScriptBase} from "./Base.sol";
// ⭐️ SCRIPT
abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils {
// Note: IS_SCRIPT() must return true.
bool public IS_SCRIPT = true;
}
StdChains.sol 244 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
import {VmSafe} from "./Vm.sol";
/**
* StdChains provides information about EVM compatible chains that can be used in scripts/tests.
* For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
* identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
* the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
* alias used in this contract, which can be found as the first argument to the
* `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
*
* There are two main ways to use this contract:
* 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
* `setChain(string memory chainAlias, Chain memory chain)`
* 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
*
* The first time either of those are used, chains are initialized with the default set of RPC URLs.
* This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
* `defaultRpcUrls`.
*
* The `setChain` function is straightforward, and it simply saves off the given chain data.
*
* The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
* we want to retrieve the RPC URL for `mainnet`:
* - If you have specified data with `setChain`, it will return that.
* - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
* is valid (e.g. a URL is specified, or an environment variable is given and exists).
* - If neither of the above conditions is met, the default data is returned.
*
* Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
*/
abstract contract StdChains {
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
bool private stdChainsInitialized;
struct ChainData {
string name;
uint256 chainId;
string rpcUrl;
}
struct Chain {
// The chain name.
string name;
// The chain's Chain ID.
uint256 chainId;
// The chain's alias. (i.e. what gets specified in `foundry.toml`).
string chainAlias;
// A default RPC endpoint for this chain.
// NOTE: This default RPC URL is included for convenience to facilitate quick tests and
// experimentation. Do not use this RPC URL for production test suites, CI, or other heavy
// usage as you will be throttled and this is a disservice to others who need this endpoint.
string rpcUrl;
}
// Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.
mapping(string => Chain) private chains;
// Maps from the chain's alias to it's default RPC URL.
mapping(string => string) private defaultRpcUrls;
// Maps from a chain ID to it's alias.
mapping(uint256 => string) private idToAlias;
bool private fallbackToDefaultRpcUrls = true;
// The RPC URL will be fetched from config or defaultRpcUrls if possible.
function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");
initializeStdChains();
chain = chains[chainAlias];
require(
chain.chainId != 0,
string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
);
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}
function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
initializeStdChains();
string memory chainAlias = idToAlias[chainId];
chain = chains[chainAlias];
require(
chain.chainId != 0,
string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
);
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}
// set chain info, with priority to argument's rpcUrl field.
function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
require(
bytes(chainAlias).length != 0,
"StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
);
require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
initializeStdChains();
string memory foundAlias = idToAlias[chain.chainId];
require(
bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),
string(
abi.encodePacked(
"StdChains setChain(string,ChainData): Chain ID ",
vm.toString(chain.chainId),
" already used by \"",
foundAlias,
"\"."
)
)
);
uint256 oldChainId = chains[chainAlias].chainId;
delete idToAlias[oldChainId];
chains[chainAlias] =
Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
idToAlias[chain.chainId] = chainAlias;
}
// set chain info, with priority to argument's rpcUrl field.
function setChain(string memory chainAlias, Chain memory chain) internal virtual {
setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
}
function _toUpper(string memory str) private pure returns (string memory) {
bytes memory strb = bytes(str);
bytes memory copy = new bytes(strb.length);
for (uint256 i = 0; i < strb.length; i++) {
bytes1 b = strb[i];
if (b >= 0x61 && b <= 0x7A) {
copy[i] = bytes1(uint8(b) - 32);
} else {
copy[i] = b;
}
}
return string(copy);
}
// lookup rpcUrl, in descending order of priority:
// current -> config (foundry.toml) -> environment variable -> default
function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {
if (bytes(chain.rpcUrl).length == 0) {
try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
chain.rpcUrl = configRpcUrl;
} catch (bytes memory err) {
string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
if (fallbackToDefaultRpcUrls) {
chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
} else {
chain.rpcUrl = vm.envString(envName);
}
// Distinguish 'not found' from 'cannot read'
// The upstream error thrown by forge for failing cheats changed so we check both the old and new versions
bytes memory oldNotFoundError =
abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
bytes memory newNotFoundError = abi.encodeWithSignature(
"CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
);
bytes32 errHash = keccak256(err);
if (
(errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError))
|| bytes(chain.rpcUrl).length == 0
) {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, err), mload(err))
}
}
}
}
return chain;
}
function setFallbackToDefaultRpcUrls(bool useDefault) internal {
fallbackToDefaultRpcUrls = useDefault;
}
function initializeStdChains() private {
if (stdChainsInitialized) return;
stdChainsInitialized = true;
// If adding an RPC here, make sure to test the default RPC URL in `testRpcs`
setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
setChainWithDefaultRpcUrl(
"mainnet", ChainData("Mainnet", 1, "https://mainnet.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl(
"goerli", ChainData("Goerli", 5, "https://goerli.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl(
"sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
setChainWithDefaultRpcUrl("optimism_goerli", ChainData("Optimism Goerli", 420, "https://goerli.optimism.io"));
setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl(
"arbitrum_one_goerli", ChainData("Arbitrum One Goerli", 421613, "https://goerli-rollup.arbitrum.io/rpc")
);
setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
setChainWithDefaultRpcUrl(
"polygon_mumbai", ChainData("Polygon Mumbai", 80001, "https://rpc-mumbai.maticvigil.com")
);
setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
setChainWithDefaultRpcUrl(
"avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
);
setChainWithDefaultRpcUrl(
"bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
);
setChainWithDefaultRpcUrl(
"bnb_smart_chain_testnet",
ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
);
setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
setChainWithDefaultRpcUrl(
"moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
);
setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
setChainWithDefaultRpcUrl("base_goerli", ChainData("Base Goerli", 84531, "https://goerli.base.org"));
setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
}
// set chain info, with priority to chainAlias' rpc url in foundry.toml
function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
string memory rpcUrl = chain.rpcUrl;
defaultRpcUrls[chainAlias] = rpcUrl;
chain.rpcUrl = "";
setChain(chainAlias, chain);
chain.rpcUrl = rpcUrl; // restore argument
}
}
StdCheats.sol 817 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
import {StdStorage, stdStorage} from "./StdStorage.sol";
import {console2} from "./console2.sol";
import {Vm} from "./Vm.sol";
abstract contract StdCheatsSafe {
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
uint256 private constant UINT256_MAX =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
bool private gasMeteringOff;
// Data structures to parse Transaction objects from the broadcast artifact
// that conform to EIP1559. The Raw structs is what is parsed from the JSON
// and then converted to the one that is used by the user for better UX.
struct RawTx1559 {
string[] arguments;
address contractAddress;
string contractName;
// json value name = function
string functionSig;
bytes32 hash;
// json value name = tx
RawTx1559Detail txDetail;
// json value name = type
string opcode;
}
struct RawTx1559Detail {
AccessList[] accessList;
bytes data;
address from;
bytes gas;
bytes nonce;
address to;
bytes txType;
bytes value;
}
struct Tx1559 {
string[] arguments;
address contractAddress;
string contractName;
string functionSig;
bytes32 hash;
Tx1559Detail txDetail;
string opcode;
}
struct Tx1559Detail {
AccessList[] accessList;
bytes data;
address from;
uint256 gas;
uint256 nonce;
address to;
uint256 txType;
uint256 value;
}
// Data structures to parse Transaction objects from the broadcast artifact
// that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
// and then converted to the one that is used by the user for better UX.
struct TxLegacy {
string[] arguments;
address contractAddress;
string contractName;
string functionSig;
string hash;
string opcode;
TxDetailLegacy transaction;
}
struct TxDetailLegacy {
AccessList[] accessList;
uint256 chainId;
bytes data;
address from;
uint256 gas;
uint256 gasPrice;
bytes32 hash;
uint256 nonce;
bytes1 opcode;
bytes32 r;
bytes32 s;
uint256 txType;
address to;
uint8 v;
uint256 value;
}
struct AccessList {
address accessAddress;
bytes32[] storageKeys;
}
// Data structures to parse Receipt objects from the broadcast artifact.
// The Raw structs is what is parsed from the JSON
// and then converted to the one that is used by the user for better UX.
struct RawReceipt {
bytes32 blockHash;
bytes blockNumber;
address contractAddress;
bytes cumulativeGasUsed;
bytes effectiveGasPrice;
address from;
bytes gasUsed;
RawReceiptLog[] logs;
bytes logsBloom;
bytes status;
address to;
bytes32 transactionHash;
bytes transactionIndex;
}
struct Receipt {
bytes32 blockHash;
uint256 blockNumber;
address contractAddress;
uint256 cumulativeGasUsed;
uint256 effectiveGasPrice;
address from;
uint256 gasUsed;
ReceiptLog[] logs;
bytes logsBloom;
uint256 status;
address to;
bytes32 transactionHash;
uint256 transactionIndex;
}
// Data structures to parse the entire broadcast artifact, assuming the
// transactions conform to EIP1559.
struct EIP1559ScriptArtifact {
string[] libraries;
string path;
string[] pending;
Receipt[] receipts;
uint256 timestamp;
Tx1559[] transactions;
TxReturn[] txReturns;
}
struct RawEIP1559ScriptArtifact {
string[] libraries;
string path;
string[] pending;
RawReceipt[] receipts;
TxReturn[] txReturns;
uint256 timestamp;
RawTx1559[] transactions;
}
struct RawReceiptLog {
// json value = address
address logAddress;
bytes32 blockHash;
bytes blockNumber;
bytes data;
bytes logIndex;
bool removed;
bytes32[] topics;
bytes32 transactionHash;
bytes transactionIndex;
bytes transactionLogIndex;
}
struct ReceiptLog {
// json value = address
address logAddress;
bytes32 blockHash;
uint256 blockNumber;
bytes data;
uint256 logIndex;
bytes32[] topics;
uint256 transactionIndex;
uint256 transactionLogIndex;
bool removed;
}
struct TxReturn {
string internalType;
string value;
}
struct Account {
address addr;
uint256 key;
}
enum AddressType {
Payable,
NonPayable,
ZeroAddress,
Precompile,
ForgeAddress
}
// Checks that `addr` is not blacklisted by token contracts that have a blacklist.
function assumeNotBlacklisted(address token, address addr) internal view virtual {
// Nothing to check if `token` is not a contract.
uint256 tokenCodeSize;
assembly {
tokenCodeSize := extcodesize(token)
}
require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
bool success;
bytes memory returnData;
// 4-byte selector for `isBlacklisted(address)`, used by USDC.
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
vm.assume(!success || abi.decode(returnData, (bool)) == false);
// 4-byte selector for `isBlackListed(address)`, used by USDT.
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
vm.assume(!success || abi.decode(returnData, (bool)) == false);
}
// Checks that `addr` is not blacklisted by token contracts that have a blacklist.
// This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
// backwards compatibility, since this name was used in the original PR which has already has
// a release. This function can be removed in a future release once we want a breaking change.
function assumeNoBlacklisted(address token, address addr) internal view virtual {
assumeNotBlacklisted(token, addr);
}
function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
if (addressType == AddressType.Payable) {
assumeNotPayable(addr);
} else if (addressType == AddressType.NonPayable) {
assumePayable(addr);
} else if (addressType == AddressType.ZeroAddress) {
assumeNotZeroAddress(addr);
} else if (addressType == AddressType.Precompile) {
assumeNotPrecompile(addr);
} else if (addressType == AddressType.ForgeAddress) {
assumeNotForgeAddress(addr);
}
}
function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
}
function assumeAddressIsNot(
address addr,
AddressType addressType1,
AddressType addressType2,
AddressType addressType3
) internal virtual {
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
assumeAddressIsNot(addr, addressType3);
}
function assumeAddressIsNot(
address addr,
AddressType addressType1,
AddressType addressType2,
AddressType addressType3,
AddressType addressType4
) internal virtual {
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
assumeAddressIsNot(addr, addressType3);
assumeAddressIsNot(addr, addressType4);
}
// This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
// `addr` and checking the `success` return value.
// NOTE: This function may result in state changes depending on the fallback/receive logic
// implemented by `addr`, which should be taken into account when this function is used.
function _isPayable(address addr) private returns (bool) {
require(
addr.balance < UINT256_MAX,
"StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
);
uint256 origBalanceTest = address(this).balance;
uint256 origBalanceAddr = address(addr).balance;
vm.deal(address(this), 1);
(bool success,) = payable(addr).call{value: 1}("");
// reset balances
vm.deal(address(this), origBalanceTest);
vm.deal(addr, origBalanceAddr);
return success;
}
// NOTE: This function may result in state changes depending on the fallback/receive logic
// implemented by `addr`, which should be taken into account when this function is used. See the
// `_isPayable` method for more information.
function assumePayable(address addr) internal virtual {
vm.assume(_isPayable(addr));
}
function assumeNotPayable(address addr) internal virtual {
vm.assume(!_isPayable(addr));
}
function assumeNotZeroAddress(address addr) internal pure virtual {
vm.assume(addr != address(0));
}
function assumeNotPrecompile(address addr) internal pure virtual {
assumeNotPrecompile(addr, _pureChainId());
}
function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
// Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
// address), but the same rationale for excluding them applies so we include those too.
// These should be present on all EVM-compatible chains.
vm.assume(addr < address(0x1) || addr > address(0x9));
// forgefmt: disable-start
if (chainId == 10 || chainId == 420) {
// https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
} else if (chainId == 42161 || chainId == 421613) {
// https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
} else if (chainId == 43114 || chainId == 43113) {
// https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
}
// forgefmt: disable-end
}
function assumeNotForgeAddress(address addr) internal pure virtual {
// vm, console, and Create2Deployer addresses
vm.assume(
addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
&& addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
);
}
function readEIP1559ScriptArtifact(string memory path)
internal
view
virtual
returns (EIP1559ScriptArtifact memory)
{
string memory data = vm.readFile(path);
bytes memory parsedData = vm.parseJson(data);
RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
EIP1559ScriptArtifact memory artifact;
artifact.libraries = rawArtifact.libraries;
artifact.path = rawArtifact.path;
artifact.timestamp = rawArtifact.timestamp;
artifact.pending = rawArtifact.pending;
artifact.txReturns = rawArtifact.txReturns;
artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
return artifact;
}
function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
Tx1559[] memory txs = new Tx1559[](rawTxs.length);
for (uint256 i; i < rawTxs.length; i++) {
txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
}
return txs;
}
function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
Tx1559 memory transaction;
transaction.arguments = rawTx.arguments;
transaction.contractName = rawTx.contractName;
transaction.functionSig = rawTx.functionSig;
transaction.hash = rawTx.hash;
transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
transaction.opcode = rawTx.opcode;
return transaction;
}
function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
internal
pure
virtual
returns (Tx1559Detail memory)
{
Tx1559Detail memory txDetail;
txDetail.data = rawDetail.data;
txDetail.from = rawDetail.from;
txDetail.to = rawDetail.to;
txDetail.nonce = _bytesToUint(rawDetail.nonce);
txDetail.txType = _bytesToUint(rawDetail.txType);
txDetail.value = _bytesToUint(rawDetail.value);
txDetail.gas = _bytesToUint(rawDetail.gas);
txDetail.accessList = rawDetail.accessList;
return txDetail;
}
function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
string memory deployData = vm.readFile(path);
bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
return rawToConvertedEIPTx1559s(rawTxs);
}
function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
string memory deployData = vm.readFile(path);
string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
bytes memory parsedDeployData = vm.parseJson(deployData, key);
RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
return rawToConvertedEIPTx1559(rawTx);
}
// Analogous to readTransactions, but for receipts.
function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
string memory deployData = vm.readFile(path);
bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
return rawToConvertedReceipts(rawReceipts);
}
function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
string memory deployData = vm.readFile(path);
string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
bytes memory parsedDeployData = vm.parseJson(deployData, key);
RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
return rawToConvertedReceipt(rawReceipt);
}
function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
Receipt[] memory receipts = new Receipt[](rawReceipts.length);
for (uint256 i; i < rawReceipts.length; i++) {
receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
}
return receipts;
}
function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
Receipt memory receipt;
receipt.blockHash = rawReceipt.blockHash;
receipt.to = rawReceipt.to;
receipt.from = rawReceipt.from;
receipt.contractAddress = rawReceipt.contractAddress;
receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
receipt.status = _bytesToUint(rawReceipt.status);
receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
receipt.logsBloom = rawReceipt.logsBloom;
receipt.transactionHash = rawReceipt.transactionHash;
return receipt;
}
function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
internal
pure
virtual
returns (ReceiptLog[] memory)
{
ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
for (uint256 i; i < rawLogs.length; i++) {
logs[i].logAddress = rawLogs[i].logAddress;
logs[i].blockHash = rawLogs[i].blockHash;
logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
logs[i].data = rawLogs[i].data;
logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
logs[i].topics = rawLogs[i].topics;
logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
logs[i].removed = rawLogs[i].removed;
}
return logs;
}
// Deploy a contract by fetching the contract bytecode from
// the artifacts directory
// e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
/// @solidity memory-safe-assembly
assembly {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
}
function deployCode(string memory what) internal virtual returns (address addr) {
bytes memory bytecode = vm.getCode(what);
/// @solidity memory-safe-assembly
assembly {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
}
/// @dev deploy contract with value on construction
function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
/// @solidity memory-safe-assembly
assembly {
addr := create(val, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
}
function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
bytes memory bytecode = vm.getCode(what);
/// @solidity memory-safe-assembly
assembly {
addr := create(val, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
}
// creates a labeled address and the corresponding private key
function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
privateKey = uint256(keccak256(abi.encodePacked(name)));
addr = vm.addr(privateKey);
vm.label(addr, name);
}
// creates a labeled address
function makeAddr(string memory name) internal virtual returns (address addr) {
(addr,) = makeAddrAndKey(name);
}
// Destroys an account immediately, sending the balance to beneficiary.
// Destroying means: balance will be zero, code will be empty, and nonce will be 0
// This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
// only after tx ends, this will run immediately.
function destroyAccount(address who, address beneficiary) internal virtual {
uint256 currBalance = who.balance;
vm.etch(who, abi.encode());
vm.deal(who, 0);
vm.resetNonce(who);
uint256 beneficiaryBalance = beneficiary.balance;
vm.deal(beneficiary, currBalance + beneficiaryBalance);
}
// creates a struct containing both a labeled address and the corresponding private key
function makeAccount(string memory name) internal virtual returns (Account memory account) {
(account.addr, account.key) = makeAddrAndKey(name);
}
function deriveRememberKey(string memory mnemonic, uint32 index)
internal
virtual
returns (address who, uint256 privateKey)
{
privateKey = vm.deriveKey(mnemonic, index);
who = vm.rememberKey(privateKey);
}
function _bytesToUint(bytes memory b) private pure returns (uint256) {
require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
}
function isFork() internal view virtual returns (bool status) {
try vm.activeFork() {
status = true;
} catch (bytes memory) {}
}
modifier skipWhenForking() {
if (!isFork()) {
_;
}
}
modifier skipWhenNotForking() {
if (isFork()) {
_;
}
}
modifier noGasMetering() {
vm.pauseGasMetering();
// To prevent turning gas monitoring back on with nested functions that use this modifier,
// we check if gasMetering started in the off position. If it did, we don't want to turn
// it back on until we exit the top level function that used the modifier
//
// i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
// funcA will have `gasStartedOff` as false, funcB will have it as true,
// so we only turn metering back on at the end of the funcA
bool gasStartedOff = gasMeteringOff;
gasMeteringOff = true;
_;
// if gas metering was on when this modifier was called, turn it back on at the end
if (!gasStartedOff) {
gasMeteringOff = false;
vm.resumeGasMetering();
}
}
// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
// can't simply access the chain ID in a normal view or pure function because the solc View Pure
// Checker changed `chainid` from pure to view in 0.8.0.
function _viewChainId() private view returns (uint256 chainId) {
// Assembly required since `block.chainid` was introduced in 0.8.0.
assembly {
chainId := chainid()
}
address(this); // Silence warnings in older Solc versions.
}
function _pureChainId() private pure returns (uint256 chainId) {
function() internal view returns (uint256) fnIn = _viewChainId;
function() internal pure returns (uint256) pureChainId;
assembly {
pureChainId := fnIn
}
chainId = pureChainId();
}
}
// Wrappers around cheatcodes to avoid footguns
abstract contract StdCheats is StdCheatsSafe {
using stdStorage for StdStorage;
StdStorage private stdstore;
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
// Skip forward or rewind time by the specified number of seconds
function skip(uint256 time) internal virtual {
vm.warp(block.timestamp + time);
}
function rewind(uint256 time) internal virtual {
vm.warp(block.timestamp - time);
}
// Setup a prank from an address that has some ether
function hoax(address msgSender) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.prank(msgSender);
}
function hoax(address msgSender, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.prank(msgSender);
}
function hoax(address msgSender, address origin) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.prank(msgSender, origin);
}
function hoax(address msgSender, address origin, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.prank(msgSender, origin);
}
// Start perpetual prank from an address that has some ether
function startHoax(address msgSender) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.startPrank(msgSender);
}
function startHoax(address msgSender, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.startPrank(msgSender);
}
// Start perpetual prank from an address that has some ether
// tx.origin is set to the origin parameter
function startHoax(address msgSender, address origin) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.startPrank(msgSender, origin);
}
function startHoax(address msgSender, address origin, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.startPrank(msgSender, origin);
}
function changePrank(address msgSender) internal virtual {
console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
vm.stopPrank();
vm.startPrank(msgSender);
}
function changePrank(address msgSender, address txOrigin) internal virtual {
vm.stopPrank();
vm.startPrank(msgSender, txOrigin);
}
// The same as Vm's `deal`
// Use the alternative signature for ERC20 tokens
function deal(address to, uint256 give) internal virtual {
vm.deal(to, give);
}
// Set the balance of an account for any ERC20 token
// Use the alternative signature to update `totalSupply`
function deal(address token, address to, uint256 give) internal virtual {
deal(token, to, give, false);
}
// Set the balance of an account for any ERC1155 token
// Use the alternative signature to update `totalSupply`
function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
dealERC1155(token, to, id, give, false);
}
function deal(address token, address to, uint256 give, bool adjust) internal virtual {
// get current balance
(, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
uint256 prevBal = abi.decode(balData, (uint256));
// update balance
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
// update total supply
if (adjust) {
(, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
uint256 totSup = abi.decode(totSupData, (uint256));
if (give < prevBal) {
totSup -= (prevBal - give);
} else {
totSup += (give - prevBal);
}
stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
}
}
function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
// get current balance
(, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
uint256 prevBal = abi.decode(balData, (uint256));
// update balance
stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
// update total supply
if (adjust) {
(, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
require(
totSupData.length != 0,
"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
);
uint256 totSup = abi.decode(totSupData, (uint256));
if (give < prevBal) {
totSup -= (prevBal - give);
} else {
totSup += (give - prevBal);
}
stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
}
}
function dealERC721(address token, address to, uint256 id) internal virtual {
// check if token id is already minted and the actual owner.
(bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
// get owner current balance
(, bytes memory fromBalData) =
token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
// get new user current balance
(, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
uint256 toPrevBal = abi.decode(toBalData, (uint256));
// update balances
stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
// update owner
stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
}
function deployCodeTo(string memory what, address where) internal virtual {
deployCodeTo(what, "", 0, where);
}
function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
deployCodeTo(what, args, 0, where);
}
function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
bytes memory creationCode = vm.getCode(what);
vm.etch(where, abi.encodePacked(creationCode, args));
(bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
vm.etch(where, runtimeBytecode);
}
// Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
function console2_log_StdCheats(string memory p0) private view {
(bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
status;
}
}
StdJson.sol 183 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;
import {VmSafe} from "./Vm.sol";
// Helpers for parsing and writing JSON files
// To parse:
// ```
// using stdJson for string;
// string memory json = vm.readFile("some_peth");
// json.parseUint("<json_path>");
// ```
// To write:
// ```
// using stdJson for string;
// string memory json = "deploymentArtifact";
// Contract contract = new Contract();
// json.serialize("contractAddress", address(contract));
// json = json.serialize("deploymentTimes", uint(1));
// // store the stringified JSON to the 'json' variable we have been using as a key
// // as we won't need it any longer
// string memory json2 = "finalArtifact";
// string memory final = json2.serialize("depArtifact", json);
// final.write("<some_path>");
// ```
library stdJson {
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
return vm.parseJson(json, key);
}
function readUint(string memory json, string memory key) internal pure returns (uint256) {
return vm.parseJsonUint(json, key);
}
function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
return vm.parseJsonUintArray(json, key);
}
function readInt(string memory json, string memory key) internal pure returns (int256) {
return vm.parseJsonInt(json, key);
}
function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
return vm.parseJsonIntArray(json, key);
}
function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
return vm.parseJsonBytes32(json, key);
}
function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
return vm.parseJsonBytes32Array(json, key);
}
function readString(string memory json, string memory key) internal pure returns (string memory) {
return vm.parseJsonString(json, key);
}
function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
return vm.parseJsonStringArray(json, key);
}
function readAddress(string memory json, string memory key) internal pure returns (address) {
return vm.parseJsonAddress(json, key);
}
function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
return vm.parseJsonAddressArray(json, key);
}
function readBool(string memory json, string memory key) internal pure returns (bool) {
return vm.parseJsonBool(json, key);
}
function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
return vm.parseJsonBoolArray(json, key);
}
function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
return vm.parseJsonBytes(json, key);
}
function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
return vm.parseJsonBytesArray(json, key);
}
function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
return vm.serializeJson(jsonKey, rootObject);
}
function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
return vm.serializeBool(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bool[] memory value)
internal
returns (string memory)
{
return vm.serializeBool(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
return vm.serializeUint(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, uint256[] memory value)
internal
returns (string memory)
{
return vm.serializeUint(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
return vm.serializeInt(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, int256[] memory value)
internal
returns (string memory)
{
return vm.serializeInt(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
return vm.serializeAddress(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, address[] memory value)
internal
returns (string memory)
{
return vm.serializeAddress(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
return vm.serializeBytes32(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
internal
returns (string memory)
{
return vm.serializeBytes32(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
return vm.serializeBytes(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes[] memory value)
internal
returns (string memory)
{
return vm.serializeBytes(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, string memory value)
internal
returns (string memory)
{
return vm.serializeString(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, string[] memory value)
internal
returns (string memory)
{
return vm.serializeString(jsonKey, key, value);
}
function write(string memory jsonKey, string memory path) internal {
vm.writeJson(jsonKey, path);
}
function write(string memory jsonKey, string memory path, string memory valueKey) internal {
vm.writeJson(jsonKey, path, valueKey);
}
}
StdMath.sol 43 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
library stdMath {
int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;
function abs(int256 a) internal pure returns (uint256) {
// Required or it will fail when `a = type(int256).min`
if (a == INT256_MIN) {
return 57896044618658097711785492504343953926634992332820282019728792003956564819968;
}
return uint256(a > 0 ? a : -a);
}
function delta(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a - b : b - a;
}
function delta(int256 a, int256 b) internal pure returns (uint256) {
// a and b are of the same sign
// this works thanks to two's complement, the left-most bit is the sign bit
if ((a ^ b) > -1) {
return delta(abs(a), abs(b));
}
// a and b are of opposite signs
return abs(a) + abs(b);
}
function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 absDelta = delta(a, b);
return absDelta * 1e18 / b;
}
function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
uint256 absDelta = delta(a, b);
uint256 absB = abs(b);
return absDelta * 1e18 / absB;
}
}
StdStorage.sol 378 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
import {Vm} from "./Vm.sol";
struct StdStorage {
mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;
mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;
bytes32[] _keys;
bytes4 _sig;
uint256 _depth;
address _target;
bytes32 _set;
}
library stdStorageSafe {
event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
event WARNING_UninitedSlot(address who, uint256 slot);
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
function sigs(string memory sigStr) internal pure returns (bytes4) {
return bytes4(keccak256(bytes(sigStr)));
}
/// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
// slot complexity:
// if flat, will be bytes32(uint256(uint));
// if map, will be keccak256(abi.encode(key, uint(slot)));
// if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
// if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
function find(StdStorage storage self) internal returns (uint256) {
address who = self._target;
bytes4 fsig = self._sig;
uint256 field_depth = self._depth;
bytes32[] memory ins = self._keys;
// calldata to test against
if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {
return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];
}
bytes memory cald = abi.encodePacked(fsig, flatten(ins));
vm.record();
bytes32 fdat;
{
(, bytes memory rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32 * field_depth);
}
(bytes32[] memory reads,) = vm.accesses(address(who));
if (reads.length == 1) {
bytes32 curr = vm.load(who, reads[0]);
if (curr == bytes32(0)) {
emit WARNING_UninitedSlot(who, uint256(reads[0]));
}
if (fdat != curr) {
require(
false,
"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported."
);
}
emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));
self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);
self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;
} else if (reads.length > 1) {
for (uint256 i = 0; i < reads.length; i++) {
bytes32 prev = vm.load(who, reads[i]);
if (prev == bytes32(0)) {
emit WARNING_UninitedSlot(who, uint256(reads[i]));
}
if (prev != fdat) {
continue;
}
bytes32 new_val = ~prev;
// store
vm.store(who, reads[i], new_val);
bool success;
{
bytes memory rdat;
(success, rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32 * field_depth);
}
if (success && fdat == new_val) {
// we found which of the slots is the actual one
emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));
self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);
self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;
vm.store(who, reads[i], prev);
break;
}
vm.store(who, reads[i], prev);
}
} else {
revert("stdStorage find(StdStorage): No storage use detected for target.");
}
require(
self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],
"stdStorage find(StdStorage): Slot(s) not found."
);
delete self._target;
delete self._sig;
delete self._keys;
delete self._depth;
return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];
}
function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
self._target = _target;
return self;
}
function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
self._sig = _sig;
return self;
}
function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
self._sig = sigs(_sig);
return self;
}
function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
self._keys.push(bytes32(uint256(uint160(who))));
return self;
}
function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
self._keys.push(bytes32(amt));
return self;
}
function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
self._keys.push(key);
return self;
}
function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
self._depth = _depth;
return self;
}
function read(StdStorage storage self) private returns (bytes memory) {
address t = self._target;
uint256 s = find(self);
return abi.encode(vm.load(t, bytes32(s)));
}
function read_bytes32(StdStorage storage self) internal returns (bytes32) {
return abi.decode(read(self), (bytes32));
}
function read_bool(StdStorage storage self) internal returns (bool) {
int256 v = read_int(self);
if (v == 0) return false;
if (v == 1) return true;
revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
}
function read_address(StdStorage storage self) internal returns (address) {
return abi.decode(read(self), (address));
}
function read_uint(StdStorage storage self) internal returns (uint256) {
return abi.decode(read(self), (uint256));
}
function read_int(StdStorage storage self) internal returns (int256) {
return abi.decode(read(self), (int256));
}
function parent(StdStorage storage self) internal returns (uint256, bytes32) {
address who = self._target;
uint256 field_depth = self._depth;
vm.startMappingRecording();
uint256 child = find(self) - field_depth;
(bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
if (!found) {
revert(
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
);
}
return (uint256(parent_slot), key);
}
function root(StdStorage storage self) internal returns (uint256) {
address who = self._target;
uint256 field_depth = self._depth;
vm.startMappingRecording();
uint256 child = find(self) - field_depth;
bool found;
bytes32 root_slot;
bytes32 parent_slot;
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
if (!found) {
revert(
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
);
}
while (found) {
root_slot = parent_slot;
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
}
return uint256(root_slot);
}
function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
bytes32 out;
uint256 max = b.length > 32 ? 32 : b.length;
for (uint256 i = 0; i < max; i++) {
out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
}
return out;
}
function flatten(bytes32[] memory b) private pure returns (bytes memory) {
bytes memory result = new bytes(b.length * 32);
for (uint256 i = 0; i < b.length; i++) {
bytes32 k = b[i];
/// @solidity memory-safe-assembly
assembly {
mstore(add(result, add(32, mul(32, i))), k)
}
}
return result;
}
}
library stdStorage {
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
function sigs(string memory sigStr) internal pure returns (bytes4) {
return stdStorageSafe.sigs(sigStr);
}
function find(StdStorage storage self) internal returns (uint256) {
return stdStorageSafe.find(self);
}
function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
return stdStorageSafe.target(self, _target);
}
function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
return stdStorageSafe.sig(self, _sig);
}
function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
return stdStorageSafe.sig(self, _sig);
}
function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
return stdStorageSafe.with_key(self, who);
}
function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
return stdStorageSafe.with_key(self, amt);
}
function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
return stdStorageSafe.with_key(self, key);
}
function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
return stdStorageSafe.depth(self, _depth);
}
function checked_write(StdStorage storage self, address who) internal {
checked_write(self, bytes32(uint256(uint160(who))));
}
function checked_write(StdStorage storage self, uint256 amt) internal {
checked_write(self, bytes32(amt));
}
function checked_write_int(StdStorage storage self, int256 val) internal {
checked_write(self, bytes32(uint256(val)));
}
function checked_write(StdStorage storage self, bool write) internal {
bytes32 t;
/// @solidity memory-safe-assembly
assembly {
t := write
}
checked_write(self, t);
}
function checked_write(StdStorage storage self, bytes32 set) internal {
address who = self._target;
bytes4 fsig = self._sig;
uint256 field_depth = self._depth;
bytes32[] memory ins = self._keys;
bytes memory cald = abi.encodePacked(fsig, flatten(ins));
if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {
find(self);
}
bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);
bytes32 fdat;
{
(, bytes memory rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32 * field_depth);
}
bytes32 curr = vm.load(who, slot);
if (fdat != curr) {
require(
false,
"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported."
);
}
vm.store(who, slot, set);
delete self._target;
delete self._sig;
delete self._keys;
delete self._depth;
}
function read_bytes32(StdStorage storage self) internal returns (bytes32) {
return stdStorageSafe.read_bytes32(self);
}
function read_bool(StdStorage storage self) internal returns (bool) {
return stdStorageSafe.read_bool(self);
}
function read_address(StdStorage storage self) internal returns (address) {
return stdStorageSafe.read_address(self);
}
function read_uint(StdStorage storage self) internal returns (uint256) {
return stdStorageSafe.read_uint(self);
}
function read_int(StdStorage storage self) internal returns (int256) {
return stdStorageSafe.read_int(self);
}
function parent(StdStorage storage self) internal returns (uint256, bytes32) {
return stdStorageSafe.parent(self);
}
function root(StdStorage storage self) internal returns (uint256) {
return stdStorageSafe.root(self);
}
// Private function so needs to be copied over
function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
bytes32 out;
uint256 max = b.length > 32 ? 32 : b.length;
for (uint256 i = 0; i < max; i++) {
out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
}
return out;
}
// Private function so needs to be copied over
function flatten(bytes32[] memory b) private pure returns (bytes memory) {
bytes memory result = new bytes(b.length * 32);
for (uint256 i = 0; i < b.length; i++) {
bytes32 k = b[i];
/// @solidity memory-safe-assembly
assembly {
mstore(add(result, add(32, mul(32, i))), k)
}
}
return result;
}
}
StdStyle.sol 333 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import {VmSafe} from "./Vm.sol";
library StdStyle {
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
string constant RED = "\u001b[91m";
string constant GREEN = "\u001b[92m";
string constant YELLOW = "\u001b[93m";
string constant BLUE = "\u001b[94m";
string constant MAGENTA = "\u001b[95m";
string constant CYAN = "\u001b[96m";
string constant BOLD = "\u001b[1m";
string constant DIM = "\u001b[2m";
string constant ITALIC = "\u001b[3m";
string constant UNDERLINE = "\u001b[4m";
string constant INVERSE = "\u001b[7m";
string constant RESET = "\u001b[0m";
function styleConcat(string memory style, string memory self) private pure returns (string memory) {
return string(abi.encodePacked(style, self, RESET));
}
function red(string memory self) internal pure returns (string memory) {
return styleConcat(RED, self);
}
function red(uint256 self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function red(int256 self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function red(address self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function red(bool self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function redBytes(bytes memory self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function redBytes32(bytes32 self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function green(string memory self) internal pure returns (string memory) {
return styleConcat(GREEN, self);
}
function green(uint256 self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function green(int256 self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function green(address self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function green(bool self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function greenBytes(bytes memory self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function greenBytes32(bytes32 self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function yellow(string memory self) internal pure returns (string memory) {
return styleConcat(YELLOW, self);
}
function yellow(uint256 self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellow(int256 self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellow(address self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellow(bool self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellowBytes(bytes memory self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellowBytes32(bytes32 self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function blue(string memory self) internal pure returns (string memory) {
return styleConcat(BLUE, self);
}
function blue(uint256 self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blue(int256 self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blue(address self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blue(bool self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blueBytes(bytes memory self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blueBytes32(bytes32 self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function magenta(string memory self) internal pure returns (string memory) {
return styleConcat(MAGENTA, self);
}
function magenta(uint256 self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magenta(int256 self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magenta(address self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magenta(bool self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magentaBytes(bytes memory self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magentaBytes32(bytes32 self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function cyan(string memory self) internal pure returns (string memory) {
return styleConcat(CYAN, self);
}
function cyan(uint256 self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyan(int256 self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyan(address self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyan(bool self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyanBytes(bytes memory self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyanBytes32(bytes32 self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function bold(string memory self) internal pure returns (string memory) {
return styleConcat(BOLD, self);
}
function bold(uint256 self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function bold(int256 self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function bold(address self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function bold(bool self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function boldBytes(bytes memory self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function boldBytes32(bytes32 self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function dim(string memory self) internal pure returns (string memory) {
return styleConcat(DIM, self);
}
function dim(uint256 self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dim(int256 self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dim(address self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dim(bool self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dimBytes(bytes memory self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dimBytes32(bytes32 self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function italic(string memory self) internal pure returns (string memory) {
return styleConcat(ITALIC, self);
}
function italic(uint256 self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italic(int256 self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italic(address self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italic(bool self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italicBytes(bytes memory self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italicBytes32(bytes32 self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function underline(string memory self) internal pure returns (string memory) {
return styleConcat(UNDERLINE, self);
}
function underline(uint256 self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underline(int256 self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underline(address self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underline(bool self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underlineBytes(bytes memory self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underlineBytes32(bytes32 self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function inverse(string memory self) internal pure returns (string memory) {
return styleConcat(INVERSE, self);
}
function inverse(uint256 self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverse(int256 self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverse(address self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverse(bool self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverseBytes(bytes memory self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverseBytes32(bytes32 self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
}
StdUtils.sol 226 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
import {IMulticall3} from "./interfaces/IMulticall3.sol";
import {MockERC20} from "./mocks/MockERC20.sol";
import {MockERC721} from "./mocks/MockERC721.sol";
import {VmSafe} from "./Vm.sol";
abstract contract StdUtils {
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/
IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
uint256 private constant INT256_MIN_ABS =
57896044618658097711785492504343953926634992332820282019728792003956564819968;
uint256 private constant SECP256K1_ORDER =
115792089237316195423570985008687907852837564279074904382605163141518161494337;
uint256 private constant UINT256_MAX =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
// Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
/*//////////////////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
// If x is between min and max, return x directly. This is to ensure that dictionary values
// do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
if (x >= min && x <= max) return x;
uint256 size = max - min + 1;
// If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
// This helps ensure coverage of the min/max values.
if (x <= 3 && size > x) return min + x;
if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
// Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
if (x > max) {
uint256 diff = x - max;
uint256 rem = diff % size;
if (rem == 0) return max;
result = min + rem - 1;
} else if (x < min) {
uint256 diff = min - x;
uint256 rem = diff % size;
if (rem == 0) return min;
result = max - rem + 1;
}
}
function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
result = _bound(x, min, max);
console2_log_StdUtils("Bound Result", result);
}
function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
// Shifting all int256 values to uint256 to use _bound function. The range of two types are:
// int256 : -(2**255) ~ (2**255 - 1)
// uint256: 0 ~ (2**256 - 1)
// So, add 2**255, INT256_MIN_ABS to the integer values.
//
// If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
// So, use `~uint256(x) + 1` instead.
uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
uint256 y = _bound(_x, _min, _max);
// To move it back to int256 value, subtract INT256_MIN_ABS at here.
result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
}
function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
result = _bound(x, min, max);
console2_log_StdUtils("Bound result", vm.toString(result));
}
function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
}
function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
}
/// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
/// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)
function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
return vm.computeCreateAddress(deployer, nonce);
}
function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
internal
pure
virtual
returns (address)
{
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
return vm.computeCreate2Address(salt, initcodeHash, deployer);
}
/// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
return vm.computeCreate2Address(salt, initCodeHash);
}
/// @dev returns an initialized mock ERC20 contract
function deployMockERC20(string memory name, string memory symbol, uint8 decimals)
internal
returns (MockERC20 mock)
{
mock = new MockERC20();
mock.initialize(name, symbol, decimals);
}
/// @dev returns an initialized mock ERC721 contract
function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) {
mock = new MockERC721();
mock.initialize(name, symbol);
}
/// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
return hashInitCode(creationCode, "");
}
/// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
/// @param args the ABI-encoded arguments to the constructor of C
function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(creationCode, args));
}
// Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
function getTokenBalances(address token, address[] memory addresses)
internal
virtual
returns (uint256[] memory balances)
{
uint256 tokenCodeSize;
assembly {
tokenCodeSize := extcodesize(token)
}
require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
// ABI encode the aggregate call to Multicall3.
uint256 length = addresses.length;
IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
for (uint256 i = 0; i < length; ++i) {
// 0x70a08231 = bytes4("balanceOf(address)"))
calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
}
// Make the aggregate call.
(, bytes[] memory returnData) = multicall.aggregate(calls);
// ABI decode the return data and return the balances.
balances = new uint256[](length);
for (uint256 i = 0; i < length; ++i) {
balances[i] = abi.decode(returnData[i], (uint256));
}
}
/*//////////////////////////////////////////////////////////////////////////
PRIVATE FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
return address(uint160(uint256(bytesValue)));
}
// This section is used to prevent the compilation of console, which shortens the compilation time when console is
// not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
// any breaking changes to function signatures.
function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
internal
pure
returns (function(bytes memory) internal pure fnOut)
{
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castLogPayloadViewToPure(_sendLogPayloadView)(payload);
}
function _sendLogPayloadView(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE2_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function console2_log_StdUtils(string memory p0) private pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function console2_log_StdUtils(string memory p0, string memory p1) private pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
}
Vm.sol 827 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
// Cheatcodes are marked as view/pure/none using the following rules:
// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,
// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),
// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,
// 3. Otherwise you're `pure`.
// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
// result in Script simulations differing from on-chain execution. It is recommended to only use
// these cheats in scripts.
interface VmSafe {
// ======== Types ========
enum CallerMode {
None,
Broadcast,
RecurrentBroadcast,
Prank,
RecurrentPrank
}
enum AccountAccessKind {
Call,
DelegateCall,
CallCode,
StaticCall,
Create,
SelfDestruct,
Resume
}
struct Log {
bytes32[] topics;
bytes data;
address emitter;
}
struct Rpc {
string key;
string url;
}
struct EthGetLogs {
address emitter;
bytes32[] topics;
bytes data;
bytes32 blockHash;
uint64 blockNumber;
bytes32 transactionHash;
uint64 transactionIndex;
uint256 logIndex;
bool removed;
}
struct DirEntry {
string errorMessage;
string path;
uint64 depth;
bool isDir;
bool isSymlink;
}
struct FsMetadata {
bool isDir;
bool isSymlink;
uint256 length;
bool readOnly;
uint256 modified;
uint256 accessed;
uint256 created;
}
struct Wallet {
address addr;
uint256 publicKeyX;
uint256 publicKeyY;
uint256 privateKey;
}
struct FfiResult {
int32 exitCode;
bytes stdout;
bytes stderr;
}
struct ChainInfo {
uint256 forkId;
uint256 chainId;
}
struct AccountAccess {
ChainInfo chainInfo;
AccountAccessKind kind;
address account;
address accessor;
bool initialized;
uint256 oldBalance;
uint256 newBalance;
bytes deployedCode;
uint256 value;
bytes data;
bool reverted;
StorageAccess[] storageAccesses;
}
struct StorageAccess {
address account;
bytes32 slot;
bool isWrite;
bytes32 previousValue;
bytes32 newValue;
bool reverted;
}
// ======== EVM ========
// Gets the address for a given private key
function addr(uint256 privateKey) external pure returns (address keyAddr);
// Gets the nonce of an account.
// See `getNonce(Wallet memory wallet)` for an alternative way to manage users and get their nonces.
function getNonce(address account) external view returns (uint64 nonce);
// Loads a storage slot from an address
function load(address target, bytes32 slot) external view returns (bytes32 data);
// Signs data
function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
// -------- Record Storage --------
// Records all storage reads and writes
function record() external;
// Gets all accessed reads and write slot from a `vm.record` session, for a given address
function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
// along with the context of the calls.
function startStateDiffRecording() external;
// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);
// -------- Recording Map Writes --------
// Starts recording all map SSTOREs for later retrieval.
function startMappingRecording() external;
// Stops recording all map SSTOREs for later retrieval and clears the recorded data.
function stopMappingRecording() external;
// Gets the number of elements in the mapping at the given slot, for a given address.
function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length);
// Gets the elements at index idx of the mapping at the given slot, for a given address. The
// index must be less than the length of the mapping (i.e. the number of keys in the mapping).
function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value);
// Gets the map key and parent of a mapping at a given slot, for a given address.
function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
external
returns (bool found, bytes32 key, bytes32 parent);
// -------- Record Logs --------
// Record all the transaction logs
function recordLogs() external;
// Gets all the recorded logs
function getRecordedLogs() external returns (Log[] memory logs);
// -------- Gas Metering --------
// It's recommend to use the `noGasMetering` modifier included with forge-std, instead of
// using these functions directly.
// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
function pauseGasMetering() external;
// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
function resumeGasMetering() external;
// -------- RPC Methods --------
/// Gets all the logs according to specified filter.
function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
external
returns (EthGetLogs[] memory logs);
// Performs an Ethereum JSON-RPC request to the current fork URL.
function rpc(string calldata method, string calldata params) external returns (bytes memory data);
// ======== Test Configuration ========
// If the condition is false, discard this run's fuzz inputs and generate new ones.
function assume(bool condition) external pure;
// Writes a breakpoint to jump to in the debugger
function breakpoint(string calldata char) external;
// Writes a conditional breakpoint to jump to in the debugger
function breakpoint(string calldata char, bool value) external;
// Returns the RPC url for the given alias
function rpcUrl(string calldata rpcAlias) external view returns (string memory json);
// Returns all rpc urls and their aliases `[alias, url][]`
function rpcUrls() external view returns (string[2][] memory urls);
// Returns all rpc urls and their aliases as structs.
function rpcUrlStructs() external view returns (Rpc[] memory urls);
// Suspends execution of the main thread for `duration` milliseconds
function sleep(uint256 duration) external;
// ======== OS and Filesystem ========
// -------- Metadata --------
// Returns true if the given path points to an existing entity, else returns false
function exists(string calldata path) external returns (bool result);
// Given a path, query the file system to get information about a file, directory, etc.
function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);
// Returns true if the path exists on disk and is pointing at a directory, else returns false
function isDir(string calldata path) external returns (bool result);
// Returns true if the path exists on disk and is pointing at a regular file, else returns false
function isFile(string calldata path) external returns (bool result);
// Get the path of the current project root.
function projectRoot() external view returns (string memory path);
// Returns the time since unix epoch in milliseconds
function unixTime() external returns (uint256 milliseconds);
// -------- Reading and writing --------
// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
// `path` is relative to the project root.
function closeFile(string calldata path) external;
// Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
// Both `from` and `to` are relative to the project root.
function copyFile(string calldata from, string calldata to) external returns (uint64 copied);
// Creates a new, empty directory at the provided path.
// This cheatcode will revert in the following situations, but is not limited to just these cases:
// - User lacks permissions to modify `path`.
// - A parent of the given path doesn't exist and `recursive` is false.
// - `path` already exists and `recursive` is false.
// `path` is relative to the project root.
function createDir(string calldata path, bool recursive) external;
// Reads the directory at the given path recursively, up to `max_depth`.
// `max_depth` defaults to 1, meaning only the direct children of the given directory will be returned.
// Follows symbolic links if `follow_links` is true.
function readDir(string calldata path) external view returns (DirEntry[] memory entries);
function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
function readDir(string calldata path, uint64 maxDepth, bool followLinks)
external
view
returns (DirEntry[] memory entries);
// Reads the entire content of file to string. `path` is relative to the project root.
function readFile(string calldata path) external view returns (string memory data);
// Reads the entire content of file as binary. `path` is relative to the project root.
function readFileBinary(string calldata path) external view returns (bytes memory data);
// Reads next line of file to string.
function readLine(string calldata path) external view returns (string memory line);
// Reads a symbolic link, returning the path that the link points to.
// This cheatcode will revert in the following situations, but is not limited to just these cases:
// - `path` is not a symbolic link.
// - `path` does not exist.
function readLink(string calldata linkPath) external view returns (string memory targetPath);
// Removes a directory at the provided path.
// This cheatcode will revert in the following situations, but is not limited to just these cases:
// - `path` doesn't exist.
// - `path` isn't a directory.
// - User lacks permissions to modify `path`.
// - The directory is not empty and `recursive` is false.
// `path` is relative to the project root.
function removeDir(string calldata path, bool recursive) external;
// Removes a file from the filesystem.
// This cheatcode will revert in the following situations, but is not limited to just these cases:
// - `path` points to a directory.
// - The file doesn't exist.
// - The user lacks permissions to remove the file.
// `path` is relative to the project root.
function removeFile(string calldata path) external;
// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
// `path` is relative to the project root.
function writeFile(string calldata path, string calldata data) external;
// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
// `path` is relative to the project root.
function writeFileBinary(string calldata path, bytes calldata data) external;
// Writes line to file, creating a file if it does not exist.
// `path` is relative to the project root.
function writeLine(string calldata path, string calldata data) external;
// -------- Foreign Function Interface --------
// Performs a foreign function call via the terminal
function ffi(string[] calldata commandInput) external returns (bytes memory result);
// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr
function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);
// ======== Environment Variables ========
// Sets environment variables
function setEnv(string calldata name, string calldata value) external;
// Reads environment variables, (name) => (value)
function envBool(string calldata name) external view returns (bool value);
function envUint(string calldata name) external view returns (uint256 value);
function envInt(string calldata name) external view returns (int256 value);
function envAddress(string calldata name) external view returns (address value);
function envBytes32(string calldata name) external view returns (bytes32 value);
function envString(string calldata name) external view returns (string memory value);
function envBytes(string calldata name) external view returns (bytes memory value);
// Reads environment variables as arrays
function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
// Read environment variables with default value
function envOr(string calldata name, bool defaultValue) external returns (bool value);
function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);
function envOr(string calldata name, int256 defaultValue) external returns (int256 value);
function envOr(string calldata name, address defaultValue) external returns (address value);
function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);
function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);
function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);
// Read environment variables as arrays with default value
function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
external
returns (bool[] memory value);
function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
external
returns (uint256[] memory value);
function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
external
returns (int256[] memory value);
function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
external
returns (address[] memory value);
function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
external
returns (bytes32[] memory value);
function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
external
returns (string[] memory value);
function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
external
returns (bytes[] memory value);
// ======== User Management ========
// Derives a private key from the name, labels the account with that name, and returns the wallet
function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);
// Generates a wallet from the private key and returns the wallet
function createWallet(uint256 privateKey) external returns (Wallet memory wallet);
// Generates a wallet from the private key, labels the account with that name, and returns the wallet
function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);
// Gets the label for the specified address
function getLabel(address account) external returns (string memory currentLabel);
// Get nonce for a Wallet.
// See `getNonce(address account)` for an alternative way to get a nonce.
function getNonce(Wallet calldata wallet) external returns (uint64 nonce);
// Labels an address in call traces
function label(address account, string calldata newLabel) external;
// Signs data, (Wallet, digest) => (v, r, s)
function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
// ======== Scripts ========
// -------- Broadcasting Transactions --------
// Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain
function broadcast() external;
// Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain
function broadcast(address signer) external;
// Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain
function broadcast(uint256 privateKey) external;
// Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
function startBroadcast() external;
// Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain
function startBroadcast(address signer) external;
// Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain
function startBroadcast(uint256 privateKey) external;
// Stops collecting onchain transactions
function stopBroadcast() external;
// -------- Key Management --------
// Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}
function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
// Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}
function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
external
pure
returns (uint256 privateKey);
// Adds a private key to the local forge wallet and returns the address
function rememberKey(uint256 privateKey) external returns (address keyAddr);
// ======== Utilities ========
// Convert values to a string
function toString(address value) external pure returns (string memory stringifiedValue);
function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
function toString(bytes32 value) external pure returns (string memory stringifiedValue);
function toString(bool value) external pure returns (string memory stringifiedValue);
function toString(uint256 value) external pure returns (string memory stringifiedValue);
function toString(int256 value) external pure returns (string memory stringifiedValue);
// Convert values from a string
function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);
// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file
function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file
function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
// Compute the address a contract will be deployed at for a given deployer address and nonce.
function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address);
// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
external
pure
returns (address);
// Compute the address of a contract created with CREATE2 using foundry's default CREATE2
// deployer: 0x4e59b44847b379578588920cA78FbF26c0B4956C, https://github.com/Arachnid/deterministic-deployment-proxy
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);
// ======== JSON Parsing and Manipulation ========
// -------- Reading --------
// NOTE: Please read https://book.getfoundry.sh/cheatcodes/parse-json to understand the
// limitations and caveats of the JSON parsing cheats.
// Checks if a key exists in a JSON object.
function keyExists(string calldata json, string calldata key) external view returns (bool);
// Given a string of JSON, return it as ABI-encoded
function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);
// The following parseJson cheatcodes will do type coercion, for the type that they indicate.
// For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'
// and hex numbers '0xEF'.
// Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not
// a JSON object.
function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);
function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);
function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
function parseJsonAddressArray(string calldata json, string calldata key)
external
pure
returns (address[] memory);
function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
function parseJsonBytes32Array(string calldata json, string calldata key)
external
pure
returns (bytes32[] memory);
// Returns array of keys for a JSON object
function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);
// -------- Writing --------
// NOTE: Please read https://book.getfoundry.sh/cheatcodes/serialize-json to understand how
// to use the serialization cheats.
// Serialize a key and value to a JSON object stored in-memory that can be later written to a file
// It returns the stringified version of the specific JSON file up to that moment.
function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json);
function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
external
returns (string memory json);
function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
external
returns (string memory json);
function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
external
returns (string memory json);
function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
external
returns (string memory json);
function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
external
returns (string memory json);
function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
external
returns (string memory json);
function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
external
returns (string memory json);
function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
external
returns (string memory json);
function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
external
returns (string memory json);
function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
external
returns (string memory json);
function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
external
returns (string memory json);
function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
external
returns (string memory json);
function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
external
returns (string memory json);
function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
external
returns (string memory json);
// NOTE: Please read https://book.getfoundry.sh/cheatcodes/write-json to understand how
// to use the JSON writing cheats.
// Write a serialized JSON object to a file. If the file exists, it will be overwritten.
function writeJson(string calldata json, string calldata path) external;
// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key>
// This is useful to replace a specific value of a JSON file, without having to parse the entire thing
function writeJson(string calldata json, string calldata path, string calldata valueKey) external;
}
// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
// in tests, but it is not recommended to use these cheats in scripts.
interface Vm is VmSafe {
// ======== EVM ========
// -------- Block and Transaction Properties --------
// Sets block.chainid
function chainId(uint256 newChainId) external;
// Sets block.coinbase
function coinbase(address newCoinbase) external;
// Sets block.difficulty
// Not available on EVM versions from Paris onwards. Use `prevrandao` instead.
// If used on unsupported EVM versions it will revert.
function difficulty(uint256 newDifficulty) external;
// Sets block.basefee
function fee(uint256 newBasefee) external;
// Sets block.prevrandao
// Not available on EVM versions before Paris. Use `difficulty` instead.
// If used on unsupported EVM versions it will revert.
function prevrandao(bytes32 newPrevrandao) external;
// Sets block.height
function roll(uint256 newHeight) external;
// Sets tx.gasprice
function txGasPrice(uint256 newGasPrice) external;
// Sets block.timestamp
function warp(uint256 newTimestamp) external;
// -------- Account State --------
// Sets an address' balance
function deal(address account, uint256 newBalance) external;
// Sets an address' code
function etch(address target, bytes calldata newRuntimeBytecode) external;
// Load a genesis JSON file's `allocs` into the in-memory state.
function loadAllocs(string calldata pathToAllocsJson) external;
// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts
function resetNonce(address account) external;
// Sets the nonce of an account; must be higher than the current nonce of the account
function setNonce(address account, uint64 newNonce) external;
// Sets the nonce of an account to an arbitrary value
function setNonceUnsafe(address account, uint64 newNonce) external;
// Stores a value to an address' storage slot.
function store(address target, bytes32 slot, bytes32 value) external;
// -------- Call Manipulation --------
// --- Mocks ---
// Clears all mocked calls
function clearMockedCalls() external;
// Mocks a call to an address, returning specified data.
// Calldata can either be strict or a partial match, e.g. if you only
// pass a Solidity selector to the expected calldata, then the entire Solidity
// function will be mocked.
function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;
// Mocks a call to an address with a specific msg.value, returning specified data.
// Calldata match takes precedence over msg.value in case of ambiguity.
function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;
// Reverts a call to an address with specified revert data.
function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external;
// Reverts a call to an address with a specific msg.value, with specified revert data.
function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData)
external;
// --- Impersonation (pranks) ---
// Sets the *next* call's msg.sender to be the input address
function prank(address msgSender) external;
// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
function startPrank(address msgSender) external;
// Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input
function prank(address msgSender, address txOrigin) external;
// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
function startPrank(address msgSender, address txOrigin) external;
// Resets subsequent calls' msg.sender to be `address(this)`
function stopPrank() external;
// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification
function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin);
// -------- State Snapshots --------
// Snapshot the current state of the evm.
// Returns the id of the snapshot that was created.
// To revert a snapshot use `revertTo`
function snapshot() external returns (uint256 snapshotId);
// Revert the state of the EVM to a previous snapshot
// Takes the snapshot id to revert to.
// This deletes the snapshot and all snapshots taken after the given snapshot id.
function revertTo(uint256 snapshotId) external returns (bool success);
// -------- Forking --------
// --- Creation and Selection ---
// Returns the identifier of the currently active fork. Reverts if no fork is currently active.
function activeFork() external view returns (uint256 forkId);
// Creates a new fork with the given endpoint and block and returns the identifier of the fork
function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork
function createFork(string calldata urlOrAlias) external returns (uint256 forkId);
// Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,
// and returns the identifier of the fork
function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork
function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before
// the transaction, returns the identifier of the fork
function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork
function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);
// Updates the currently active fork to given block number
// This is similar to `roll` but for the currently active fork
function rollFork(uint256 blockNumber) external;
// Updates the currently active fork to given transaction
// this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block
function rollFork(bytes32 txHash) external;
// Updates the given fork to given block number
function rollFork(uint256 forkId, uint256 blockNumber) external;
// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block
function rollFork(uint256 forkId, bytes32 txHash) external;
// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
function selectFork(uint256 forkId) external;
// Fetches the given transaction from the active fork and executes it on the current state
function transact(bytes32 txHash) external;
// Fetches the given transaction from the given fork and executes it on the current state
function transact(uint256 forkId, bytes32 txHash) external;
// --- Behavior ---
// In forking mode, explicitly grant the given address cheatcode access
function allowCheatcodes(address account) external;
// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
// Meaning, changes made to the state of this account will be kept when switching forks
function makePersistent(address account) external;
function makePersistent(address account0, address account1) external;
function makePersistent(address account0, address account1, address account2) external;
function makePersistent(address[] calldata accounts) external;
// Revokes persistent status from the address, previously added via `makePersistent`
function revokePersistent(address account) external;
function revokePersistent(address[] calldata accounts) external;
// Returns true if the account is marked as persistent
function isPersistent(address account) external view returns (bool persistent);
// ======== Test Assertions and Utilities ========
// Expects a call to an address with the specified calldata.
// Calldata can either be a strict or a partial match
function expectCall(address callee, bytes calldata data) external;
// Expects given number of calls to an address with the specified calldata.
function expectCall(address callee, bytes calldata data, uint64 count) external;
// Expects a call to an address with the specified msg.value and calldata
function expectCall(address callee, uint256 msgValue, bytes calldata data) external;
// Expects given number of calls to an address with the specified msg.value and calldata
function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external;
// Expect a call to an address with the specified msg.value, gas, and calldata.
function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;
// Expects given number of calls to an address with the specified msg.value, gas, and calldata.
function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external;
// Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.
function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;
// Expect given number of calls to an address with the specified msg.value and calldata, and a *minimum* amount of gas.
function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count)
external;
// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).
// Call this function, then emit an event, then call a function. Internally after the call, we check if
// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;
// Same as the previous method, but also checks supplied address against emitting contract.
function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
external;
// Prepare an expected log with all topic and data checks enabled.
// Call this function, then emit an event, then call a function. Internally after the call, we check if
// logs were emitted in the expected order with the expected topics and data.
function expectEmit() external;
// Same as the previous method, but also checks supplied address against emitting contract.
function expectEmit(address emitter) external;
// Expects an error on next call that exactly matches the revert data.
function expectRevert(bytes calldata revertData) external;
// Expects an error on next call that starts with the revert data.
function expectRevert(bytes4 revertData) external;
// Expects an error on next call with any revert data.
function expectRevert() external;
// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other
// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.
function expectSafeMemory(uint64 min, uint64 max) external;
// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.
// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges
// to the set.
function expectSafeMemoryCall(uint64 min, uint64 max) external;
// Marks a test as skipped. Must be called at the top of the test.
function skip(bool skipTest) external;
}
console.sol 1533 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
}
function logUint(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
}
function log(uint p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
}
function log(uint p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
}
function log(uint p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
}
function log(string memory p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
}
function log(uint p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
}
function log(uint p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
}
function log(uint p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
}
function log(uint p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
}
function log(uint p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
}
function log(uint p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
}
function log(uint p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
}
function log(uint p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
}
function log(uint p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
}
function log(uint p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
}
function log(uint p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
}
function log(uint p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
}
function log(uint p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
}
function log(uint p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
}
function log(uint p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
}
function log(string memory p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
}
function log(string memory p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
}
function log(string memory p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
}
function log(string memory p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
}
function log(bool p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
}
function log(bool p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
}
function log(bool p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
}
function log(address p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
}
function log(address p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
}
function log(address p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(...
// [truncated — 66688 bytes total]
console2.sol 1558 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should
/// use `int256` and `uint256`. This modified version fixes that. This version is recommended
/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in
/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.
/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178
library console2 {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _castLogPayloadViewToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) internal pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castLogPayloadViewToPure(_sendLogPayloadView)(payload);
}
function _sendLogPayloadView(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, int256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encod...
// [truncated — 69677 bytes total]
IMulticall3.sol 73 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
interface IMulticall3 {
struct Call {
address target;
bytes callData;
}
struct Call3 {
address target;
bool allowFailure;
bytes callData;
}
struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
function aggregate(Call[] calldata calls)
external
payable
returns (uint256 blockNumber, bytes[] memory returnData);
function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
function blockAndAggregate(Call[] calldata calls)
external
payable
returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
function getBasefee() external view returns (uint256 basefee);
function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);
function getBlockNumber() external view returns (uint256 blockNumber);
function getChainId() external view returns (uint256 chainid);
function getCurrentBlockCoinbase() external view returns (address coinbase);
function getCurrentBlockDifficulty() external view returns (uint256 difficulty);
function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);
function getCurrentBlockTimestamp() external view returns (uint256 timestamp);
function getEthBalance(address addr) external view returns (uint256 balance);
function getLastBlockHash() external view returns (bytes32 blockHash);
function tryAggregate(bool requireSuccess, Call[] calldata calls)
external
payable
returns (Result[] memory returnData);
function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
external
payable
returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
}
MockERC20.sol 216 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production.
/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol
contract MockERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal INITIAL_CHAIN_ID;
bytes32 internal INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
INITIALIZE
//////////////////////////////////////////////////////////////*/
/// @dev A bool to track whether the contract has been initialized.
bool private initialized;
/// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
/// syntaxes, we add an initialization function that can be called only once.
function initialize(string memory _name, string memory _symbol, uint8 _decimals) public {
require(!initialized, "ALREADY_INITIALIZED");
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = _pureChainId();
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
initialized = true;
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] = _sub(balanceOf[msg.sender], amount);
balanceOf[to] = _add(balanceOf[to], amount);
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != ~uint256(0)) allowance[from][msg.sender] = _sub(allowed, amount);
balanceOf[from] = _sub(balanceOf[from], amount);
balanceOf[to] = _add(balanceOf[to], amount);
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
public
virtual
{
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
_pureChainId(),
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply = _add(totalSupply, amount);
balanceOf[to] = _add(balanceOf[to], amount);
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] = _sub(balanceOf[from], amount);
totalSupply = _sub(totalSupply, amount);
emit Transfer(from, address(0), amount);
}
/*//////////////////////////////////////////////////////////////
INTERNAL SAFE MATH LOGIC
//////////////////////////////////////////////////////////////*/
function _add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "ERC20: addition overflow");
return c;
}
function _sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(a >= b, "ERC20: subtraction underflow");
return a - b;
}
/*//////////////////////////////////////////////////////////////
HELPERS
//////////////////////////////////////////////////////////////*/
// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
// can't simply access the chain ID in a normal view or pure function because the solc View Pure
// Checker changed `chainid` from pure to view in 0.8.0.
function _viewChainId() private view returns (uint256 chainId) {
// Assembly required since `block.chainid` was introduced in 0.8.0.
assembly {
chainId := chainid()
}
address(this); // Silence warnings in older Solc versions.
}
function _pureChainId() private pure returns (uint256 chainId) {
function() internal view returns (uint256) fnIn = _viewChainId;
function() internal pure returns (uint256) pureChainId;
assembly {
pureChainId := fnIn
}
chainId = pureChainId();
}
}
MockERC721.sol 221 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production.
/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol
contract MockERC721 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 indexed id);
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
function tokenURI(uint256 id) public view virtual returns (string memory) {}
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => address) internal _ownerOf;
mapping(address => uint256) internal _balanceOf;
function ownerOf(uint256 id) public view virtual returns (address owner) {
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
}
function balanceOf(address owner) public view virtual returns (uint256) {
require(owner != address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
/*//////////////////////////////////////////////////////////////
INITIALIZE
//////////////////////////////////////////////////////////////*/
/// @dev A bool to track whether the contract has been initialized.
bool private initialized;
/// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
/// syntaxes, we add an initialization function that can be called only once.
function initialize(string memory _name, string memory _symbol) public {
require(!initialized, "ALREADY_INITIALIZED");
name = _name;
symbol = _symbol;
initialized = true;
}
/*//////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 id) public virtual {
address owner = _ownerOf[id];
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function transferFrom(address from, address to, uint256 id) public virtual {
require(from == _ownerOf[id], "WRONG_FROM");
require(to != address(0), "INVALID_RECIPIENT");
require(
msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED"
);
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
_balanceOf[from]--;
_balanceOf[to]++;
_ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
function safeTransferFrom(address from, address to, uint256 id) public virtual {
transferFrom(from, to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "")
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public virtual {
transferFrom(from, to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data)
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/
function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
|| interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721
|| interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 id) internal virtual {
require(to != address(0), "INVALID_RECIPIENT");
require(_ownerOf[id] == address(0), "ALREADY_MINTED");
// Counter overflow is incredibly unrealistic.
_balanceOf[to]++;
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function _burn(uint256 id) internal virtual {
address owner = _ownerOf[id];
require(owner != address(0), "NOT_MINTED");
_balanceOf[owner]--;
delete _ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
/*//////////////////////////////////////////////////////////////
INTERNAL SAFE MINT LOGIC
//////////////////////////////////////////////////////////////*/
function _safeMint(address to, uint256 id) internal virtual {
_mint(to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "")
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
_mint(to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data)
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*//////////////////////////////////////////////////////////////
HELPERS
//////////////////////////////////////////////////////////////*/
function _isContract(address _addr) private view returns (bool) {
uint256 codeLength;
// Assembly required for versions < 0.8.0 to check extcodesize.
assembly {
codeLength := extcodesize(_addr)
}
return codeLength > 0;
}
}
interface IERC721TokenReceiver {
function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4);
}
safeconsole.sol 13248 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
/// @author philogy <https://github.com/philogy>
/// @dev Code generated automatically by script.
library safeconsole {
uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67;
// Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374)
// for the view-to-pure log trick.
function _sendLogPayload(uint256 offset, uint256 size) private pure {
function(uint256, uint256) internal view fnIn = _sendLogPayloadView;
function(uint256, uint256) internal pure pureSendLogPayload;
assembly {
pureSendLogPayload := fnIn
}
pureSendLogPayload(offset, size);
}
function _sendLogPayloadView(uint256 offset, uint256 size) private view {
assembly {
pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0))
}
}
function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
function(uint256, uint256, uint256) internal view fnIn = _memcopyView;
function(uint256, uint256, uint256) internal pure pureMemcopy;
assembly {
pureMemcopy := fnIn
}
pureMemcopy(fromOffset, toOffset, length);
}
function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
assembly {
pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length))
}
}
function logMemory(uint256 offset, uint256 length) internal pure {
if (offset >= 0x60) {
// Sufficient memory before slice to prepare call header.
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(sub(offset, 0x60))
m1 := mload(sub(offset, 0x40))
m2 := mload(sub(offset, 0x20))
// Selector of `logBytes(bytes)`.
mstore(sub(offset, 0x60), 0xe17bf956)
mstore(sub(offset, 0x40), 0x20)
mstore(sub(offset, 0x20), length)
}
_sendLogPayload(offset - 0x44, length + 0x44);
assembly {
mstore(sub(offset, 0x60), m0)
mstore(sub(offset, 0x40), m1)
mstore(sub(offset, 0x20), m2)
}
} else {
// Insufficient space, so copy slice forward, add header and reverse.
bytes32 m0;
bytes32 m1;
bytes32 m2;
uint256 endOffset = offset + length;
assembly {
m0 := mload(add(endOffset, 0x00))
m1 := mload(add(endOffset, 0x20))
m2 := mload(add(endOffset, 0x40))
}
_memcopy(offset, offset + 0x60, length);
assembly {
// Selector of `logBytes(bytes)`.
mstore(add(offset, 0x00), 0xe17bf956)
mstore(add(offset, 0x20), 0x20)
mstore(add(offset, 0x40), length)
}
_sendLogPayload(offset + 0x1c, length + 0x44);
_memcopy(offset + 0x60, offset, length);
assembly {
mstore(add(endOffset, 0x00), m0)
mstore(add(endOffset, 0x20), m1)
mstore(add(endOffset, 0x40), m2)
}
}
}
function log(address p0) internal pure {
bytes32 m0;
bytes32 m1;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
// Selector of `log(address)`.
mstore(0x00, 0x2c2ecbc2)
mstore(0x20, p0)
}
_sendLogPayload(0x1c, 0x24);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
}
}
function log(bool p0) internal pure {
bytes32 m0;
bytes32 m1;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
// Selector of `log(bool)`.
mstore(0x00, 0x32458eed)
mstore(0x20, p0)
}
_sendLogPayload(0x1c, 0x24);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
}
}
function log(uint256 p0) internal pure {
bytes32 m0;
bytes32 m1;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
// Selector of `log(uint256)`.
mstore(0x00, 0xf82c50f1)
mstore(0x20, p0)
}
_sendLogPayload(0x1c, 0x24);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
}
}
function log(bytes32 p0) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(string)`.
mstore(0x00, 0x41304fac)
mstore(0x20, 0x20)
writeString(0x40, p0)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(address,address)`.
mstore(0x00, 0xdaf0d4aa)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(address p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(address,bool)`.
mstore(0x00, 0x75b605d3)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(address p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(address,uint256)`.
mstore(0x00, 0x8309e8a8)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(address p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(address,string)`.
mstore(0x00, 0x759f86bb)
mstore(0x20, p0)
mstore(0x40, 0x40)
writeString(0x60, p1)
}
_sendLogPayload(0x1c, 0x84);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bool p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(bool,address)`.
mstore(0x00, 0x853c4849)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(bool p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(bool,bool)`.
mstore(0x00, 0x2a110e83)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(bool p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(bool,uint256)`.
mstore(0x00, 0x399174d3)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(bool p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(bool,string)`.
mstore(0x00, 0x8feac525)
mstore(0x20, p0)
mstore(0x40, 0x40)
writeString(0x60, p1)
}
_sendLogPayload(0x1c, 0x84);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(uint256 p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(uint256,address)`.
mstore(0x00, 0x69276c86)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(uint256 p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(uint256,bool)`.
mstore(0x00, 0x1c9d7eb3)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(uint256 p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(uint256,uint256)`.
mstore(0x00, 0xf666715a)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(uint256 p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(uint256,string)`.
mstore(0x00, 0x643fd0df)
mstore(0x20, p0)
mstore(0x40, 0x40)
writeString(0x60, p1)
}
_sendLogPayload(0x1c, 0x84);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(string,address)`.
mstore(0x00, 0x319af333)
mstore(0x20, 0x40)
mstore(0x40, p1)
writeString(0x60, p0)
}
_sendLogPayload(0x1c, 0x84);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(string,bool)`.
mstore(0x00, 0xc3b55635)
mstore(0x20, 0x40)
mstore(0x40, p1)
writeString(0x60, p0)
}
_sendLogPayload(0x1c, 0x84);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(string,uint256)`.
mstore(0x00, 0xb60e72cc)
mstore(0x20, 0x40)
mstore(0x40, p1)
writeString(0x60, p0)
}
_sendLogPayload(0x1c, 0x84);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
bytes32 m6;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
m6 := mload(0xc0)
// Selector of `log(string,string)`.
mstore(0x00, 0x4b5c4277)
mstore(0x20, 0x40)
mstore(0x40, 0x80)
writeString(0x60, p0)
writeString(0xa0, p1)
}
_sendLogPayload(0x1c, 0xc4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
mstore(0xc0, m6)
}
}
function log(address p0, address p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,address,address)`.
mstore(0x00, 0x018c84c2)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,address,bool)`.
mstore(0x00, 0xf2a66286)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,address,uint256)`.
mstore(0x00, 0x17fe6185)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,address,string)`.
mstore(0x00, 0x007150be)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bool p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,bool,address)`.
mstore(0x00, 0xf11699ed)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, bool p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,bool,bool)`.
mstore(0x00, 0xeb830c92)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, bool p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,bool,uint256)`.
mstore(0x00, 0x9c4f99fb)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, bool p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,bool,string)`.
mstore(0x00, 0x212255cc)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, uint256 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,uint256,address)`.
mstore(0x00, 0x7bc0d848)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, uint256 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,uint256,bool)`.
mstore(0x00, 0x678209a8)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,uint256,uint256)`.
mstore(0x00, 0xb69bcaf6)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, uint256 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,uint256,string)`.
mstore(0x00, 0xa1f2e8aa)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,string,address)`.
mstore(0x00, 0xf08744e8)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,string,bool)`.
mstore(0x00, 0xcf020fb1)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,string,uint256)`.
mstore(0x00, 0x67dd6ff1)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
bytes32 m6;
bytes32 m7;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
m6 := mload(0xc0)
m7 := mload(0xe0)
// Selector of `log(address,string,string)`.
mstore(0x00, 0xfb772265)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, 0xa0)
writeString(0x80, p1)
writeString(0xc0, p2)
}
_sendLogPayload(0x1c, 0xe4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
mstore(0xc0, m6)
mstore(0xe0, m7)
}
}
function log(bool p0, address p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,address,address)`.
mstore(0x00, 0xd2763667)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, address p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,address,bool)`.
mstore(0x00, 0x18c9c746)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, address p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,address,uint256)`.
mstore(0x00, 0x5f7b9afb)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, address p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,address,string)`.
mstore(0x00, 0xde9a9270)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bool p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,bool,address)`.
mstore(0x00, 0x1078f68d)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, bool p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,bool,bool)`.
mstore(0x00, 0x50709698)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, bool p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,bool,uint256)`.
mstore(0x00, 0x12f21602)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, bool p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,bool,string)`.
mstore(0x00, 0x2555fa46)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, uint256 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,uint256,address)`.
mstore(0x00, 0x088ef9d2)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, uint256 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,uint256,bool)`.
mstore(0x00, 0xe8defba9)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,uint256,uint256)`.
mstore(0x00, 0x37103367)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, uint256 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,uint256,string)`.
mstore(0x00, 0xc3fc3970)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,string,address)`.
mstore(0x00, 0x9591b953)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,string,bool)`.
mstore(0x00, 0xdbb4c247)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,string,uint256)`.
mstore(0x00, 0x1093ee11)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
bytes32 m6;
bytes32 m7;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
m6 := mload(0xc0)
m7 := mload(0xe0)
// Selector of `log(bool,string,string)`.
mstore(0x00, 0xb076847f)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, 0xa0)
writeString(0x80, p1)
writeString(0xc0, p2)
}
_sendLogPayload(0x1c, 0xe4);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
mstore(0xc0, m6)
mstore(0xe0, m7)
}
}
function log(uint256 p0, address p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(uint256,address,address)`.
mstore(0x00, 0xbcfd9be0)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(uint256 p0, address p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(uint256,address,bool)`.
mstore(0x00, 0x9b6ec042)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(uint256,address,uint256)`.
mstore(0x00, 0x5a9b5ed5)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(uint256 p0, address p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
...
// [truncated — 397898 bytes total]
OApp.sol 39 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OApp is OAppSender, OAppReceiver {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol implementation.
* @return receiverVersion The version of the OAppReceiver.sol implementation.
*/
function oAppVersion()
public
pure
virtual
override(OAppSender, OAppReceiver)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}
OAppCore.sol 83 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";
/**
* @title OAppCore
* @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
*/
abstract contract OAppCore is IOAppCore, Ownable {
// The LayerZero endpoint associated with the given OApp
ILayerZeroEndpointV2 public immutable endpoint;
// Mapping to store peers associated with corresponding endpoints
mapping(uint32 eid => bytes32 peer) public peers;
/**
* @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
* @param _endpoint The address of the LOCAL Layer Zero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*
* @dev The delegate typically should be set as the owner of the contract.
*/
constructor(address _endpoint, address _delegate) {
endpoint = ILayerZeroEndpointV2(_endpoint);
if (_delegate == address(0)) revert InvalidDelegate();
endpoint.setDelegate(_delegate);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
_setPeer(_eid, _peer);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
peers[_eid] = _peer;
emit PeerSet(_eid, _peer);
}
/**
* @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
* ie. the peer is set to bytes32(0).
* @param _eid The endpoint ID.
* @return peer The address of the peer associated with the specified endpoint.
*/
function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
bytes32 peer = peers[_eid];
if (peer == bytes32(0)) revert NoPeer(_eid);
return peer;
}
/**
* @notice Sets the delegate address for the OApp.
* @param _delegate The address of the delegate to be set.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
*/
function setDelegate(address _delegate) public onlyOwner {
endpoint.setDelegate(_delegate);
}
}
OAppReceiver.sol 122 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppReceiver
* @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
*/
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
// Custom error message for when the caller is not the registered endpoint/
error OnlyEndpoint(address addr);
// @dev The version of the OAppReceiver implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant RECEIVER_VERSION = 2;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
* ie. this is a RECEIVE only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (0, RECEIVER_VERSION);
}
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @dev _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @dev _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata /*_origin*/,
bytes calldata /*_message*/,
address _sender
) public view virtual returns (bool) {
return _sender == address(this);
}
/**
* @notice Checks if the path initialization is allowed based on the provided origin.
* @param origin The origin information containing the source endpoint and sender address.
* @return Whether the path has been initialized.
*
* @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
* @dev This defaults to assuming if a peer has been set, its initialized.
* Can be overridden by the OApp if there is other logic to determine this.
*/
function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
return peers[origin.srcEid] == origin.sender;
}
/**
* @notice Retrieves the next nonce for a given source endpoint and sender address.
* @dev _srcEid The source endpoint ID.
* @dev _sender The sender address.
* @return nonce The next nonce.
*
* @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
* @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
* @dev This is also enforced by the OApp.
* @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
*/
function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
return 0;
}
/**
* @dev Entry point for receiving messages or packets from the endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The payload of the received message.
* @param _executor The address of the executor for the received message.
* @param _extraData Additional arbitrary data provided by the corresponding executor.
*
* @dev Entry point for receiving msg/packet from the LayerZero endpoint.
*/
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) public payable virtual {
// Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);
// Ensure that the sender matches the expected peer for the source endpoint.
if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);
// Call the internal OApp implementation of lzReceive.
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
}
OAppSender.sol 127 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";
import {console2} from "../../../../../../lib/forge-std/src/Script.sol";
/**
* @title OAppSender
* @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
*/
abstract contract OAppSender is OAppCore {
using SafeERC20 for IERC20;
// Custom error messages
error NotEnoughNative(uint256 msgValue);
error LzTokenUnavailable();
// @dev The version of the OAppSender implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant SENDER_VERSION = 1;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
* ie. this is a SEND only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (SENDER_VERSION, 0);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
* @return fee The calculated MessagingFee for the message.
* - nativeFee: The native fee for the message.
* - lzTokenFee: The LZ token fee for the message.
*/
function _quote(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
bool _payInLzToken
) internal view virtual returns (MessagingFee memory fee) {
_getPeerOrRevert(_dstEid);
return
endpoint.quote(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
address(this)
);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _fee The calculated LayerZero fee for the message.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess fee values sent to the endpoint.
* @return receipt The receipt for the sent message.
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function _lzSend(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
MessagingFee memory _fee,
address _refundAddress
) internal virtual returns (MessagingReceipt memory receipt) {
// @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
uint256 messageValue = _payNative(_fee.nativeFee);
if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
return
// solhint-disable-next-line check-send-result
endpoint.send{ value: messageValue }(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
_refundAddress
);
}
/**
* @dev Internal function to pay the native fee associated with the message.
* @param _nativeFee The native fee to be paid.
* @return nativeFee The amount of native currency paid.
*
* @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
* this will need to be overridden because msg.value would contain multiple lzFees.
* @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
* @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
* @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
*/
function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
return _nativeFee;
}
/**
* @dev Internal function to pay the LZ token fee associated with the message.
* @param _lzTokenFee The LZ token fee to be paid.
*
* @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
* @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
*/
function _payLzToken(uint256 _lzTokenFee) internal virtual {
// @dev Cannot cache the token because it is not immutable in the endpoint.
address lzToken = endpoint.lzToken();
if (lzToken == address(0)) revert LzTokenUnavailable();
// Pay LZ token fee by sending tokens to the endpoint.
IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
}
}
IOAppCore.sol 52 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
/**
* @title IOAppCore
*/
interface IOAppCore {
// Custom error messages
error OnlyPeer(uint32 eid, bytes32 sender);
error NoPeer(uint32 eid);
error InvalidEndpointCall();
error InvalidDelegate();
// Event emitted when a peer (OApp) is set for a corresponding endpoint
event PeerSet(uint32 eid, bytes32 peer);
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*/
function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);
/**
* @notice Retrieves the LayerZero endpoint associated with the OApp.
* @return iEndpoint The LayerZero endpoint as an interface.
*/
function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);
/**
* @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
* @param _eid The endpoint ID.
* @return peer The peer address (OApp instance) associated with the corresponding endpoint.
*/
function peers(uint32 _eid) external view returns (bytes32 peer);
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*/
function setPeer(uint32 _eid, bytes32 _peer) external;
/**
* @notice Sets the delegate address for the OApp Core.
* @param _delegate The address of the delegate to be set.
*/
function setDelegate(address _delegate) external;
}
IOAppMsgInspector.sol 22 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title IOAppMsgInspector
* @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.
*/
interface IOAppMsgInspector {
// Custom error message for inspection failure
error InspectionFailed(bytes message, bytes options);
/**
* @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.
* @param _message The message payload to be inspected.
* @param _options Additional options or parameters for inspection.
* @return valid A boolean indicating whether the inspection passed (true) or failed (false).
*
* @dev Optionally done as a revert, OR use the boolean provided to handle the failure.
*/
function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);
}
IOAppOptionsType3.sol 43 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @dev Struct representing enforced option parameters.
*/
struct EnforcedOptionParam {
uint32 eid; // Endpoint ID
uint16 msgType; // Message Type
bytes options; // Additional options
}
/**
* @title IOAppOptionsType3
* @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.
*/
interface IOAppOptionsType3 {
// Custom error message for invalid options
error InvalidOptions(bytes options);
// Event emitted when enforced options are set
event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);
/**
* @notice Sets enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*/
function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;
/**
* @notice Combines options for a given endpoint and message type.
* @param _eid The endpoint ID.
* @param _msgType The OApp message type.
* @param _extraOptions Additional options passed by the caller.
* @return options The combination of caller specified options AND enforced options.
*/
function combineOptions(
uint32 _eid,
uint16 _msgType,
bytes calldata _extraOptions
) external view returns (bytes memory options);
}
IOAppReceiver.sol 25 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";
interface IOAppReceiver is ILayerZeroReceiver {
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata _origin,
bytes calldata _message,
address _sender
) external view returns (bool isSender);
}
OAppOptionsType3.sol 98 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol";
/**
* @title OAppOptionsType3
* @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
*/
abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {
uint16 internal constant OPTION_TYPE_3 = 3;
// @dev The "msgType" should be defined in the child contract.
mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;
/**
* @dev Sets the enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
* @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
* eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
* if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
*/
function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {
_setEnforcedOptions(_enforcedOptions);
}
/**
* @dev Sets the enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*
* @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
* @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
* eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
* if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
*/
function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {
for (uint256 i = 0; i < _enforcedOptions.length; i++) {
// @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.
_assertOptionsType3(_enforcedOptions[i].options);
enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;
}
emit EnforcedOptionSet(_enforcedOptions);
}
/**
* @notice Combines options for a given endpoint and message type.
* @param _eid The endpoint ID.
* @param _msgType The OAPP message type.
* @param _extraOptions Additional options passed by the caller.
* @return options The combination of caller specified options AND enforced options.
*
* @dev If there is an enforced lzReceive option:
* - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}
* - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.
* @dev This presence of duplicated options is handled off-chain in the verifier/executor.
*/
function combineOptions(
uint32 _eid,
uint16 _msgType,
bytes calldata _extraOptions
) public view virtual returns (bytes memory) {
bytes memory enforced = enforcedOptions[_eid][_msgType];
// No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.
if (enforced.length == 0) return _extraOptions;
// No caller options, return enforced
if (_extraOptions.length == 0) return enforced;
// @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.
if (_extraOptions.length >= 2) {
_assertOptionsType3(_extraOptions);
// @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.
return bytes.concat(enforced, _extraOptions[2:]);
}
// No valid set of options was found.
revert InvalidOptions(_extraOptions);
}
/**
* @dev Internal function to assert that options are of type 3.
* @param _options The options to be checked.
*/
function _assertOptionsType3(bytes memory _options) internal pure virtual {
uint16 optionsType;
assembly {
optionsType := mload(add(_options, 2))
}
if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
}
}
OFTAdapter.sol 106 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IOFT, OFTCore } from "./OFTCore.sol";
/**
* @title OFTAdapter Contract
* @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
*
* @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
* @dev WARNING: ONLY 1 of these should exist for a given global mesh,
* unless you make a NON-default implementation of OFT and needs to be done very carefully.
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
*/
abstract contract OFTAdapter is OFTCore {
using SafeERC20 for IERC20;
IERC20 internal immutable innerToken;
/**
* @dev Constructor for the OFTAdapter contract.
* @param _token The address of the ERC-20 token to be adapted.
* @param _lzEndpoint The LayerZero endpoint address.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(
address _token,
address _lzEndpoint,
address _delegate
) OFTCore(IERC20Metadata(_token).decimals(), _lzEndpoint, _delegate) {
innerToken = IERC20(_token);
}
/**
* @dev Retrieves the address of the underlying ERC20 implementation.
* @return The address of the adapted ERC-20 token.
*
* @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract.
*/
function token() public view returns (address) {
return address(innerToken);
}
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev In the case of default OFTAdapter, approval is required.
* @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval.
*/
function approvalRequired() external pure virtual returns (bool) {
return true;
}
/**
* @dev Burns tokens from the sender's specified balance, ie. pull method.
* @param _from The address to debit from.
* @param _amountLD The amount of tokens to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination chain ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*
* @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract.
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountReceivedLD.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
(amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);
// @dev Lock tokens by moving them into this contract from the caller.
innerToken.safeTransferFrom(_from, address(this), amountSentLD);
}
/**
* @dev Credits tokens to the specified address.
* @param _to The address to credit the tokens to.
* @param _amountLD The amount of tokens to credit in local decimals.
* @dev _srcEid The source chain ID.
* @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
*
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountReceivedLD.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 /*_srcEid*/
) internal virtual override returns (uint256 amountReceivedLD) {
// @dev Unlock the tokens and transfer to the recipient.
innerToken.safeTransfer(_to, _amountLD);
// @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD.
return _amountLD;
}
}
OFTCore.sol 402 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { OApp, Origin } from "../oapp/OApp.sol";
import { OAppOptionsType3 } from "../oapp/libs/OAppOptionsType3.sol";
import { IOAppMsgInspector } from "../oapp/interfaces/IOAppMsgInspector.sol";
import { OAppPreCrimeSimulator } from "../precrime/OAppPreCrimeSimulator.sol";
import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "./interfaces/IOFT.sol";
import { OFTMsgCodec } from "./libs/OFTMsgCodec.sol";
import { OFTComposeMsgCodec } from "./libs/OFTComposeMsgCodec.sol";
import {console2} from "../../../../../../../../lib/forge-std/src/Script.sol";
/**
* @title OFTCore
* @dev Abstract contract for the OftChain (OFT) token.
*/
abstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {
using OFTMsgCodec for bytes;
using OFTMsgCodec for bytes32;
// @notice Provides a conversion rate when swapping between denominations of SD and LD
// - shareDecimals == SD == shared Decimals
// - localDecimals == LD == local decimals
// @dev Considers that tokens have different decimal amounts on various chains.
// @dev eg.
// For a token
// - locally with 4 decimals --> 1.2345 => uint(12345)
// - remotely with 2 decimals --> 1.23 => uint(123)
// - The conversion rate would be 10 ** (4 - 2) = 100
// @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote,
// you can only display 1.23 -> uint(123).
// @dev To preserve the dust that would otherwise be lost on that conversion,
// we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh
uint256 public immutable decimalConversionRate;
// @notice Msg types that are used to identify the various OFT operations.
// @dev This can be extended in child contracts for non-default oft operations
// @dev These values are used in things like combineOptions() in OAppOptionsType3.sol.
uint16 public constant SEND = 1;
uint16 public constant SEND_AND_CALL = 2;
// Address of an optional contract to inspect both 'message' and 'options'
address public msgInspector;
event MsgInspectorSet(address inspector);
/**
* @dev Constructor.
* @param _localDecimals The decimals of the token on the local chain (this chain).
* @param _endpoint The address of the LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) {
if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals();
decimalConversionRate = 10 ** (_localDecimals - sharedDecimals());
}
/**
* @notice Retrieves interfaceID and the version of the OFT.
* @return interfaceId The interface ID.
* @return version The version.
*
* @dev interfaceId: This specific interface ID is '0x02e49c2c'.
* @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
* @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
* ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
*/
function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {
return (type(IOFT).interfaceId, 1);
}
/**
* @dev Retrieves the shared decimals of the OFT.
* @return The shared decimals of the OFT.
*
* @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap
* Lowest common decimal denominator between chains.
* Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).
* For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller.
* ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615
*/
function sharedDecimals() public view virtual returns (uint8) {
return 6;
}
/**
* @dev Sets the message inspector address for the OFT.
* @param _msgInspector The address of the message inspector.
*
* @dev This is an optional contract that can be used to inspect both 'message' and 'options'.
* @dev Set it to address(0) to disable it, or set it to a contract address to enable it.
*/
function setMsgInspector(address _msgInspector) public virtual onlyOwner {
msgInspector = _msgInspector;
emit MsgInspectorSet(_msgInspector);
}
/**
* @notice Provides a quote for OFT-related operations.
* @param _sendParam The parameters for the send operation.
* @return oftLimit The OFT limit information.
* @return oftFeeDetails The details of OFT fees.
* @return oftReceipt The OFT receipt information.
*/
function quoteOFT(
SendParam calldata _sendParam
)
external
view
virtual
returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)
{
uint256 minAmountLD = 0; // Unused in the default implementation.
uint256 maxAmountLD = type(uint64).max; // Unused in the default implementation.
oftLimit = OFTLimit(minAmountLD, maxAmountLD);
// Unused in the default implementation; reserved for future complex fee details.
oftFeeDetails = new OFTFeeDetail[](0);
// @dev This is the same as the send() operation, but without the actual send.
// - amountSentLD is the amount in local decimals that would be sent from the sender.
// - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.
// @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.
(uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(
_sendParam.amountLD,
_sendParam.minAmountLD,
_sendParam.dstEid
);
oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
}
/**
* @notice Provides a quote for the send() operation.
* @param _sendParam The parameters for the send() operation.
* @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
* @return msgFee The calculated LayerZero messaging fee from the send() operation.
*
* @dev MessagingFee: LayerZero msg fee
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
*/
function quoteSend(
SendParam calldata _sendParam,
bool _payInLzToken
) external view virtual returns (MessagingFee memory msgFee) {
// @dev mock the amount to receive, this is the same operation used in the send().
// The quote is as similar as possible to the actual send() operation.
(, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);
// @dev Builds the options and OFT message to quote in the endpoint.
(bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
// @dev Calculates the LayerZero fee for the send() operation.
return _quote(_sendParam.dstEid, message, options, _payInLzToken);
}
/**
* @dev Executes the send operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The calculated fee for the send() operation.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds.
* @return msgReceipt The receipt for the send operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
// @dev Applies the token transfers regarding this send() operation.
// - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.
// - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.
(uint256 amountSentLD, uint256 amountReceivedLD) = _debit(
msg.sender,
_sendParam.amountLD,
_sendParam.minAmountLD,
_sendParam.dstEid
);
// @dev Builds the options and OFT message to quote in the endpoint.
(bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
// @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.
msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
// @dev Formulate the OFT receipt.
oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);
}
/**
* @dev Internal function to build the message and options.
* @param _sendParam The parameters for the send() operation.
* @param _amountLD The amount in local decimals.
* @return message The encoded message.
* @return options The encoded options.
*/
function _buildMsgAndOptions(
SendParam calldata _sendParam,
uint256 _amountLD
) internal view virtual returns (bytes memory message, bytes memory options) {
bool hasCompose;
// @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is.
(message, hasCompose) = OFTMsgCodec.encode(
_sendParam.to,
_toSD(_amountLD),
// @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote.
// EVEN if you dont require an arbitrary payload to be sent... eg. '0x01'
_sendParam.composeMsg
);
// @dev Change the msg type depending if its composed or not.
uint16 msgType = hasCompose ? SEND_AND_CALL : SEND;
// @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3.
options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);
// @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.
// @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean
if (msgInspector != address(0)) IOAppMsgInspector(msgInspector).inspect(message, options);
}
/**
* @dev Internal function to handle the receive on the LayerZero endpoint.
* @param _origin The origin information.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address from the src chain.
* - nonce: The nonce of the LayerZero message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The encoded message.
* @dev _executor The address of the executor.
* @dev _extraData Additional data.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address /*_executor*/, // @dev unused in the default implementation.
bytes calldata /*_extraData*/ // @dev unused in the default implementation.
) internal virtual override {
// @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)
// Thus everything is bytes32() encoded in flight.
address toAddress = _message.sendTo().bytes32ToAddress();
// @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals
uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);
if (_message.isComposed()) {
// @dev Proprietary composeMsg format for the OFT.
bytes memory composeMsg = OFTComposeMsgCodec.encode(
_origin.nonce,
_origin.srcEid,
amountReceivedLD,
_message.composeMsg()
);
// @dev Stores the lzCompose payload that will be executed in a separate tx.
// Standardizes functionality for executing arbitrary contract invocation on some non-evm chains.
// @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed.
// @dev The index is used when a OApp needs to compose multiple msgs on lzReceive.
// For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0.
endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg);
}
emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);
}
/**
* @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
* @param _origin The origin information.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address from the src chain.
* - nonce: The nonce of the LayerZero message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The LayerZero message.
* @param _executor The address of the off-chain executor.
* @param _extraData Arbitrary data passed by the msg executor.
*
* @dev Enables the preCrime simulator to mock sending lzReceive() messages,
* routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
*/
function _lzReceiveSimulate(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual override {
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Check if the peer is considered 'trusted' by the OApp.
* @param _eid The endpoint ID to check.
* @param _peer The peer to check.
* @return Whether the peer passed is considered 'trusted' by the OApp.
*
* @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source.
*/
function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {
return peers[_eid] == _peer;
}
/**
* @dev Internal function to remove dust from the given local decimal amount.
* @param _amountLD The amount in local decimals.
* @return amountLD The amount after removing dust.
*
* @dev Prevents the loss of dust when moving amounts between chains with different decimals.
* @dev eg. uint(123) with a conversion rate of 100 becomes uint(100).
*/
function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) {
return (_amountLD / decimalConversionRate) * decimalConversionRate;
}
/**
* @dev Internal function to convert an amount from shared decimals into local decimals.
* @param _amountSD The amount in shared decimals.
* @return amountLD The amount in local decimals.
*/
function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) {
return _amountSD * decimalConversionRate;
}
/**
* @dev Internal function to convert an amount from local decimals into shared decimals.
* @param _amountLD The amount in local decimals.
* @return amountSD The amount in shared decimals.
*/
function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {
return uint64(_amountLD / decimalConversionRate);
}
/**
* @dev Internal function to mock the amount mutation from a OFT debit() operation.
* @param _amountLD The amount to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @dev _dstEid The destination endpoint ID.
* @return amountSentLD The amount sent, in local decimals.
* @return amountReceivedLD The amount to be received on the remote chain, in local decimals.
*
* @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.
*/
function _debitView(
uint256 _amountLD,
uint256 _minAmountLD,
uint32 /*_dstEid*/
) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
// @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.
amountSentLD = _removeDust(_amountLD);
// @dev The amount to send is the same as amount received in the default implementation.
amountReceivedLD = amountSentLD;
// @dev Check for slippage.
if (amountReceivedLD < _minAmountLD) {
revert SlippageExceeded(amountReceivedLD, _minAmountLD);
}
}
/**
* @dev Internal function to perform a debit operation.
* @param _from The address to debit.
* @param _amountLD The amount to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination endpoint ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*
* @dev Defined here but are intended to be overriden depending on the OFT implementation.
* @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD);
/**
* @dev Internal function to perform a credit operation.
* @param _to The address to credit.
* @param _amountLD The amount to credit in local decimals.
* @param _srcEid The source endpoint ID.
* @return amountReceivedLD The amount ACTUALLY received in local decimals.
*
* @dev Defined here but are intended to be overriden depending on the OFT implementation.
* @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 _srcEid
) internal virtual returns (uint256 amountReceivedLD);
}
IOFT.sol 149 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { MessagingReceipt, MessagingFee } from "../../oapp/OAppSender.sol";
/**
* @dev Struct representing token parameters for the OFT send() operation.
*/
struct SendParam {
uint32 dstEid; // Destination endpoint ID.
bytes32 to; // Recipient address.
uint256 amountLD; // Amount to send in local decimals.
uint256 minAmountLD; // Minimum amount to send in local decimals.
bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
bytes composeMsg; // The composed message for the send() operation.
bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}
/**
* @dev Struct representing OFT limit information.
* @dev These amounts can change dynamically and are up the the specific oft implementation.
*/
struct OFTLimit {
uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.
uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.
}
/**
* @dev Struct representing OFT receipt information.
*/
struct OFTReceipt {
uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
// @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}
/**
* @dev Struct representing OFT fee details.
* @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.
*/
struct OFTFeeDetail {
int256 feeAmountLD; // Amount of the fee in local decimals.
string description; // Description of the fee.
}
/**
* @title IOFT
* @dev Interface for the OftChain (OFT) token.
* @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.
* @dev This specific interface ID is '0x02e49c2c'.
*/
interface IOFT {
// Custom error messages
error InvalidLocalDecimals();
error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);
// Events
event OFTSent(
bytes32 indexed guid, // GUID of the OFT message.
uint32 dstEid, // Destination Endpoint ID.
address indexed fromAddress, // Address of the sender on the src chain.
uint256 amountSentLD, // Amount of tokens sent in local decimals.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
event OFTReceived(
bytes32 indexed guid, // GUID of the OFT message.
uint32 srcEid, // Source Endpoint ID.
address indexed toAddress, // Address of the recipient on the dst chain.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
/**
* @notice Retrieves interfaceID and the version of the OFT.
* @return interfaceId The interface ID.
* @return version The version.
*
* @dev interfaceId: This specific interface ID is '0x02e49c2c'.
* @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
* @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
* ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
*/
function oftVersion() external view returns (bytes4 interfaceId, uint64 version);
/**
* @notice Retrieves the address of the token associated with the OFT.
* @return token The address of the ERC20 token implementation.
*/
function token() external view returns (address);
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev Allows things like wallet implementers to determine integration requirements,
* without understanding the underlying token implementation.
*/
function approvalRequired() external view returns (bool);
/**
* @notice Retrieves the shared decimals of the OFT.
* @return sharedDecimals The shared decimals of the OFT.
*/
function sharedDecimals() external view returns (uint8);
/**
* @notice Provides a quote for OFT-related operations.
* @param _sendParam The parameters for the send operation.
* @return limit The OFT limit information.
* @return oftFeeDetails The details of OFT fees.
* @return receipt The OFT receipt information.
*/
function quoteOFT(
SendParam calldata _sendParam
) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);
/**
* @notice Provides a quote for the send() operation.
* @param _sendParam The parameters for the send() operation.
* @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
* @return fee The calculated LayerZero messaging fee from the send() operation.
*
* @dev MessagingFee: LayerZero msg fee
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
*/
function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);
/**
* @notice Executes the send() operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The fee information supplied by the caller.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds from fees etc. on the src.
* @return receipt The LayerZero messaging receipt from the send() operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory, OFTReceipt memory);
}
OFTComposeMsgCodec.sol 91 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library OFTComposeMsgCodec {
// Offset constants for decoding composed messages
uint8 private constant NONCE_OFFSET = 8;
uint8 private constant SRC_EID_OFFSET = 12;
uint8 private constant AMOUNT_LD_OFFSET = 44;
uint8 private constant COMPOSE_FROM_OFFSET = 76;
/**
* @dev Encodes a OFT composed message.
* @param _nonce The nonce value.
* @param _srcEid The source endpoint ID.
* @param _amountLD The amount in local decimals.
* @param _composeMsg The composed message.
* @return _msg The encoded Composed message.
*/
function encode(
uint64 _nonce,
uint32 _srcEid,
uint256 _amountLD,
bytes memory _composeMsg // 0x[composeFrom][composeMsg]
) internal pure returns (bytes memory _msg) {
_msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
}
/**
* @dev Retrieves the nonce from the composed message.
* @param _msg The message.
* @return The nonce value.
*/
function nonce(bytes calldata _msg) internal pure returns (uint64) {
return uint64(bytes8(_msg[:NONCE_OFFSET]));
}
/**
* @dev Retrieves the source endpoint ID from the composed message.
* @param _msg The message.
* @return The source endpoint ID.
*/
function srcEid(bytes calldata _msg) internal pure returns (uint32) {
return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
}
/**
* @dev Retrieves the amount in local decimals from the composed message.
* @param _msg The message.
* @return The amount in local decimals.
*/
function amountLD(bytes calldata _msg) internal pure returns (uint256) {
return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
}
/**
* @dev Retrieves the composeFrom value from the composed message.
* @param _msg The message.
* @return The composeFrom value.
*/
function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
}
/**
* @dev Retrieves the composed message.
* @param _msg The message.
* @return The composed message.
*/
function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
return _msg[COMPOSE_FROM_OFFSET:];
}
/**
* @dev Converts an address to bytes32.
* @param _addr The address to convert.
* @return The bytes32 representation of the address.
*/
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
/**
* @dev Converts bytes32 to an address.
* @param _b The bytes32 value to convert.
* @return The address representation of bytes32.
*/
function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
return address(uint160(uint256(_b)));
}
}
OFTMsgCodec.sol 83 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library OFTMsgCodec {
// Offset constants for encoding and decoding OFT messages
uint8 private constant SEND_TO_OFFSET = 32;
uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;
/**
* @dev Encodes an OFT LayerZero message.
* @param _sendTo The recipient address.
* @param _amountShared The amount in shared decimals.
* @param _composeMsg The composed message.
* @return _msg The encoded message.
* @return hasCompose A boolean indicating whether the message has a composed payload.
*/
function encode(
bytes32 _sendTo,
uint64 _amountShared,
bytes memory _composeMsg
) internal view returns (bytes memory _msg, bool hasCompose) {
hasCompose = _composeMsg.length > 0;
// @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.
_msg = hasCompose
? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)
: abi.encodePacked(_sendTo, _amountShared);
}
/**
* @dev Checks if the OFT message is composed.
* @param _msg The OFT message.
* @return A boolean indicating whether the message is composed.
*/
function isComposed(bytes calldata _msg) internal pure returns (bool) {
return _msg.length > SEND_AMOUNT_SD_OFFSET;
}
/**
* @dev Retrieves the recipient address from the OFT message.
* @param _msg The OFT message.
* @return The recipient address.
*/
function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
return bytes32(_msg[:SEND_TO_OFFSET]);
}
/**
* @dev Retrieves the amount in shared decimals from the OFT message.
* @param _msg The OFT message.
* @return The amount in shared decimals.
*/
function amountSD(bytes calldata _msg) internal pure returns (uint64) {
return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));
}
/**
* @dev Retrieves the composed message from the OFT message.
* @param _msg The OFT message.
* @return The composed message.
*/
function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
return _msg[SEND_AMOUNT_SD_OFFSET:];
}
/**
* @dev Converts an address to bytes32.
* @param _addr The address to convert.
* @return The bytes32 representation of the address.
*/
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
/**
* @dev Converts bytes32 to an address.
* @param _b The bytes32 value to convert.
* @return The address representation of bytes32.
*/
function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
return address(uint160(uint256(_b)));
}
}
OAppPreCrimeSimulator.sol 125 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IPreCrime } from "./interfaces/IPreCrime.sol";
import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "./interfaces/IOAppPreCrimeSimulator.sol";
/**
* @title OAppPreCrimeSimulator
* @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
*/
abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {
// The address of the preCrime implementation.
address public preCrime;
/**
* @dev Retrieves the address of the OApp contract.
* @return The address of the OApp contract.
*
* @dev The simulator contract is the base contract for the OApp by default.
* @dev If the simulator is a separate contract, override this function.
*/
function oApp() external view virtual returns (address) {
return address(this);
}
/**
* @dev Sets the preCrime contract address.
* @param _preCrime The address of the preCrime contract.
*/
function setPreCrime(address _preCrime) public virtual onlyOwner {
preCrime = _preCrime;
emit PreCrimeSet(_preCrime);
}
/**
* @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.
* @param _packets An array of InboundPacket objects representing received packets to be delivered.
*
* @dev WARNING: MUST revert at the end with the simulation results.
* @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,
* WITHOUT actually executing them.
*/
function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {
for (uint256 i = 0; i < _packets.length; i++) {
InboundPacket calldata packet = _packets[i];
// Ignore packets that are not from trusted peers.
if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;
// @dev Because a verifier is calling this function, it doesnt have access to executor params:
// - address _executor
// - bytes calldata _extraData
// preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().
// They are instead stubbed to default values, address(0) and bytes("")
// @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,
// which would cause the revert to be ignored.
this.lzReceiveSimulate{ value: packet.value }(
packet.origin,
packet.guid,
packet.message,
packet.executor,
packet.extraData
);
}
// @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().
revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());
}
/**
* @dev Is effectively an internal function because msg.sender must be address(this).
* Allows resetting the call stack for 'internal' calls.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier of the packet.
* @param _message The message payload of the packet.
* @param _executor The executor address for the packet.
* @param _extraData Additional data for the packet.
*/
function lzReceiveSimulate(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable virtual {
// @dev Ensure ONLY can be called 'internally'.
if (msg.sender != address(this)) revert OnlySelf();
_lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
* @param _origin The origin information.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address from the src chain.
* - nonce: The nonce of the LayerZero message.
* @param _guid The GUID of the LayerZero message.
* @param _message The LayerZero message.
* @param _executor The address of the off-chain executor.
* @param _extraData Arbitrary data passed by the msg executor.
*
* @dev Enables the preCrime simulator to mock sending lzReceive() messages,
* routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
*/
function _lzReceiveSimulate(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
/**
* @dev checks if the specified peer is considered 'trusted' by the OApp.
* @param _eid The endpoint Id to check.
* @param _peer The peer to check.
* @return Whether the peer passed is considered 'trusted' by the OApp.
*/
function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);
}
IOAppPreCrimeSimulator.sol 55 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
// solhint-disable-next-line no-unused-import
import { InboundPacket, Origin } from "../libs/Packet.sol";
/**
* @title IOAppPreCrimeSimulator Interface
* @dev Interface for the preCrime simulation functionality in an OApp.
*/
interface IOAppPreCrimeSimulator {
// @dev simulation result used in PreCrime implementation
error SimulationResult(bytes result);
error OnlySelf();
/**
* @dev Emitted when the preCrime contract address is set.
* @param preCrimeAddress The address of the preCrime contract.
*/
event PreCrimeSet(address preCrimeAddress);
/**
* @dev Retrieves the address of the preCrime contract implementation.
* @return The address of the preCrime contract.
*/
function preCrime() external view returns (address);
/**
* @dev Retrieves the address of the OApp contract.
* @return The address of the OApp contract.
*/
function oApp() external view returns (address);
/**
* @dev Sets the preCrime contract address.
* @param _preCrime The address of the preCrime contract.
*/
function setPreCrime(address _preCrime) external;
/**
* @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.
* @param _packets An array of LayerZero InboundPacket objects representing received packets.
*/
function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;
/**
* @dev checks if the specified peer is considered 'trusted' by the OApp.
* @param _eid The endpoint Id to check.
* @param _peer The peer to check.
* @return Whether the peer passed is considered 'trusted' by the OApp.
*/
function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);
}
IPreCrime.sol 40 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
struct PreCrimePeer {
uint32 eid;
bytes32 preCrime;
bytes32 oApp;
}
// TODO not done yet
interface IPreCrime {
error OnlyOffChain();
// for simulate()
error PacketOversize(uint256 max, uint256 actual);
error PacketUnsorted();
error SimulationFailed(bytes reason);
// for preCrime()
error SimulationResultNotFound(uint32 eid);
error InvalidSimulationResult(uint32 eid, bytes reason);
error CrimeFound(bytes crime);
function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);
function simulate(
bytes[] calldata _packets,
uint256[] calldata _packetMsgValues
) external payable returns (bytes memory);
function buildSimulationResult() external view returns (bytes memory);
function preCrime(
bytes[] calldata _packets,
uint256[] calldata _packetMsgValues,
bytes[] calldata _simulations
) external;
function version() external view returns (uint64 major, uint8 minor);
}
Packet.sol 61 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol";
/**
* @title InboundPacket
* @dev Structure representing an inbound packet received by the contract.
*/
struct InboundPacket {
Origin origin; // Origin information of the packet.
uint32 dstEid; // Destination endpointId of the packet.
address receiver; // Receiver address for the packet.
bytes32 guid; // Unique identifier of the packet.
uint256 value; // msg.value of the packet.
address executor; // Executor address for the packet.
bytes message; // Message payload of the packet.
bytes extraData; // Additional arbitrary data for the packet.
}
/**
* @title PacketDecoder
* @dev Library for decoding LayerZero packets.
*/
library PacketDecoder {
using PacketV1Codec for bytes;
/**
* @dev Decode an inbound packet from the given packet data.
* @param _packet The packet data to decode.
* @return packet An InboundPacket struct representing the decoded packet.
*/
function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {
packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());
packet.dstEid = _packet.dstEid();
packet.receiver = _packet.receiverB20();
packet.guid = _packet.guid();
packet.message = _packet.message();
}
/**
* @dev Decode multiple inbound packets from the given packet data and associated message values.
* @param _packets An array of packet data to decode.
* @param _packetMsgValues An array of associated message values for each packet.
* @return packets An array of InboundPacket structs representing the decoded packets.
*/
function decode(
bytes[] calldata _packets,
uint256[] memory _packetMsgValues
) internal pure returns (InboundPacket[] memory packets) {
packets = new InboundPacket[](_packets.length);
for (uint256 i = 0; i < _packets.length; i++) {
bytes calldata packet = _packets[i];
packets[i] = PacketDecoder.decode(packet);
// @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.
packets[i].value = _packetMsgValues[i];
}
}
}
ILayerZeroEndpointV2.sol 89 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";
struct MessagingParams {
uint32 dstEid;
bytes32 receiver;
bytes message;
bytes options;
bool payInLzToken;
}
struct MessagingReceipt {
bytes32 guid;
uint64 nonce;
MessagingFee fee;
}
struct MessagingFee {
uint256 nativeFee;
uint256 lzTokenFee;
}
struct Origin {
uint32 srcEid;
bytes32 sender;
uint64 nonce;
}
interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);
event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);
event PacketDelivered(Origin origin, address receiver);
event LzReceiveAlert(
address indexed receiver,
address indexed executor,
Origin origin,
bytes32 guid,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
event LzTokenSet(address token);
event DelegateSet(address sender, address delegate);
function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);
function send(
MessagingParams calldata _params,
address _refundAddress
) external payable returns (MessagingReceipt memory);
function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;
function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);
function initializable(Origin calldata _origin, address _receiver) external view returns (bool);
function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;
// oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;
function setLzToken(address _lzToken) external;
function lzToken() external view returns (address);
function nativeToken() external view returns (address);
function setDelegate(address _delegate) external;
}
ILayerZeroReceiver.sol 19 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { Origin } from "./ILayerZeroEndpointV2.sol";
interface ILayerZeroReceiver {
function allowInitializePath(Origin calldata _origin) external view returns (bool);
function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable;
}
IMessageLib.sol 26 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { SetConfigParam } from "./IMessageLibManager.sol";
enum MessageLibType {
Send,
Receive,
SendAndReceive
}
interface IMessageLib is IERC165 {
function setConfig(address _oapp, SetConfigParam[] calldata _config) external;
function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);
function isSupportedEid(uint32 _eid) external view returns (bool);
// message libs of same major version are compatible
function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);
function messageLibType() external view returns (MessageLibType);
}
IMessageLibManager.sol 70 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
struct SetConfigParam {
uint32 eid;
uint32 configType;
bytes config;
}
interface IMessageLibManager {
struct Timeout {
address lib;
uint256 expiry;
}
event LibraryRegistered(address newLib);
event DefaultSendLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
event SendLibrarySet(address sender, uint32 eid, address newLib);
event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);
function registerLibrary(address _lib) external;
function isRegisteredLibrary(address _lib) external view returns (bool);
function getRegisteredLibraries() external view returns (address[] memory);
function setDefaultSendLibrary(uint32 _eid, address _newLib) external;
function defaultSendLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _timeout) external;
function defaultReceiveLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;
function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);
function isSupportedEid(uint32 _eid) external view returns (bool);
function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);
/// ------------------- OApp interfaces -------------------
function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;
function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);
function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);
function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);
function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external;
function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);
function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;
function getConfig(
address _oapp,
address _lib,
uint32 _eid,
uint32 _configType
) external view returns (bytes memory config);
}
IMessagingChannel.sol 34 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingChannel {
event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
function eid() external view returns (uint32);
// this is an emergency function if a message cannot be verified for some reasons
// required to provide _nextNonce to avoid race condition
function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;
function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);
function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);
function inboundPayloadHash(
address _receiver,
uint32 _srcEid,
bytes32 _sender,
uint64 _nonce
) external view returns (bytes32);
function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}
IMessagingComposer.sol 38 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingComposer {
event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
event LzComposeAlert(
address indexed from,
address indexed to,
address indexed executor,
bytes32 guid,
uint16 index,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
function composeQueue(
address _from,
address _to,
bytes32 _guid,
uint16 _index
) external view returns (bytes32 messageHash);
function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;
function lzCompose(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData
) external payable;
}
IMessagingContext.sol 9 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingContext {
function isSendingMessage() external view returns (bool);
function getSendContext() external view returns (uint32 dstEid, address sender);
}
ISendLib.sol 36 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { MessagingFee } from "./ILayerZeroEndpointV2.sol";
import { IMessageLib } from "./IMessageLib.sol";
struct Packet {
uint64 nonce;
uint32 srcEid;
address sender;
uint32 dstEid;
bytes32 receiver;
bytes32 guid;
bytes message;
}
interface ISendLib is IMessageLib {
function send(
Packet calldata _packet,
bytes calldata _options,
bool _payInLzToken
) external returns (MessagingFee memory, bytes memory encodedPacket);
function quote(
Packet calldata _packet,
bytes calldata _options,
bool _payInLzToken
) external view returns (MessagingFee memory);
function setTreasury(address _treasury) external;
function withdrawFee(address _to, uint256 _amount) external;
function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;
}
AddressCast.sol 41 lines
// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
library AddressCast {
error AddressCast_InvalidSizeForAddress();
error AddressCast_InvalidAddress();
function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
result = bytes32(_addressBytes);
unchecked {
uint256 offset = 32 - _addressBytes.length;
result = result >> (offset * 8);
}
}
function toBytes32(address _address) internal pure returns (bytes32 result) {
result = bytes32(uint256(uint160(_address)));
}
function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
result = new bytes(_size);
unchecked {
uint256 offset = 256 - _size * 8;
assembly {
mstore(add(result, 32), shl(offset, _addressBytes32))
}
}
}
function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
result = address(uint160(uint256(_addressBytes32)));
}
function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
result = address(bytes20(_addressBytes));
}
}
PacketV1Codec.sol 108 lines
// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
import { Packet } from "../../interfaces/ISendLib.sol";
import { AddressCast } from "../../libs/AddressCast.sol";
library PacketV1Codec {
using AddressCast for address;
using AddressCast for bytes32;
uint8 internal constant PACKET_VERSION = 1;
// header (version + nonce + path)
// version
uint256 private constant PACKET_VERSION_OFFSET = 0;
// nonce
uint256 private constant NONCE_OFFSET = 1;
// path
uint256 private constant SRC_EID_OFFSET = 9;
uint256 private constant SENDER_OFFSET = 13;
uint256 private constant DST_EID_OFFSET = 45;
uint256 private constant RECEIVER_OFFSET = 49;
// payload (guid + message)
uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)
uint256 private constant MESSAGE_OFFSET = 113;
function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
encodedPacket = abi.encodePacked(
PACKET_VERSION,
_packet.nonce,
_packet.srcEid,
_packet.sender.toBytes32(),
_packet.dstEid,
_packet.receiver,
_packet.guid,
_packet.message
);
}
function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
return
abi.encodePacked(
PACKET_VERSION,
_packet.nonce,
_packet.srcEid,
_packet.sender.toBytes32(),
_packet.dstEid,
_packet.receiver
);
}
function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
return abi.encodePacked(_packet.guid, _packet.message);
}
function header(bytes calldata _packet) internal pure returns (bytes calldata) {
return _packet[0:GUID_OFFSET];
}
function version(bytes calldata _packet) internal pure returns (uint8) {
return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
}
function nonce(bytes calldata _packet) internal pure returns (uint64) {
return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
}
function srcEid(bytes calldata _packet) internal pure returns (uint32) {
return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
}
function sender(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
}
function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
return sender(_packet).toAddress();
}
function dstEid(bytes calldata _packet) internal pure returns (uint32) {
return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
}
function receiver(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
}
function receiverB20(bytes calldata _packet) internal pure returns (address) {
return receiver(_packet).toAddress();
}
function guid(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
}
function message(bytes calldata _packet) internal pure returns (bytes calldata) {
return bytes(_packet[MESSAGE_OFFSET:]);
}
function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
return bytes(_packet[GUID_OFFSET:]);
}
function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
return keccak256(payload(_packet));
}
}
Base.sol 48 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
import {StdStorage} from "./StdStorage.sol";
import {Vm, VmSafe} from "./Vm.sol";
abstract contract CommonBase {
/// @dev Cheat code address.
/// Calculated as `address(uint160(uint256(keccak256("hevm cheat code"))))`.
address internal constant VM_ADDRESS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;
/// @dev console.sol and console2.sol work by executing a staticcall to this address.
/// Calculated as `address(uint160(uint88(bytes11("console.log"))))`.
address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
/// @dev Used when deploying with create2.
/// Taken from https://github.com/Arachnid/deterministic-deployment-proxy.
address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
/// @dev The default address for tx.origin and msg.sender.
/// Calculated as `address(uint160(uint256(keccak256("foundry default caller"))))`.
address internal constant DEFAULT_SENDER = 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
/// @dev The address of the first contract `CREATE`d by a running test contract.
/// When running tests, each test contract is `CREATE`d by `DEFAULT_SENDER` with nonce 1.
/// Calculated as `VM.computeCreateAddress(VM.computeCreateAddress(DEFAULT_SENDER, 1), 1)`.
address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
/// @dev Deterministic deployment address of the Multicall3 contract.
/// Taken from https://www.multicall3.com.
address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
/// @dev The order of the secp256k1 curve.
uint256 internal constant SECP256K1_ORDER =
115792089237316195423570985008687907852837564279074904382605163141518161494337;
uint256 internal constant UINT256_MAX =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
Vm internal constant vm = Vm(VM_ADDRESS);
StdStorage internal stdstore;
}
abstract contract TestBase is CommonBase {}
abstract contract ScriptBase is CommonBase {
VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
}
Script.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
// 💬 ABOUT
// Forge Std's default Script.
// 🧩 MODULES
import {console} from "./console.sol";
import {console2} from "./console2.sol";
import {safeconsole} from "./safeconsole.sol";
import {StdChains} from "./StdChains.sol";
import {StdCheatsSafe} from "./StdCheats.sol";
import {StdConstants} from "./StdConstants.sol";
import {stdJson} from "./StdJson.sol";
import {stdMath} from "./StdMath.sol";
import {StdStorage, stdStorageSafe} from "./StdStorage.sol";
import {StdStyle} from "./StdStyle.sol";
import {StdUtils} from "./StdUtils.sol";
import {VmSafe} from "./Vm.sol";
// 📦 BOILERPLATE
import {ScriptBase} from "./Base.sol";
// ⭐️ SCRIPT
abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils {
// Note: IS_SCRIPT() must return true.
bool public IS_SCRIPT = true;
}
StdChains.sol 287 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
import {VmSafe} from "./Vm.sol";
/**
* StdChains provides information about EVM compatible chains that can be used in scripts/tests.
* For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
* identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
* the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
* alias used in this contract, which can be found as the first argument to the
* `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
*
* There are two main ways to use this contract:
* 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
* `setChain(string memory chainAlias, Chain memory chain)`
* 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
*
* The first time either of those are used, chains are initialized with the default set of RPC URLs.
* This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
* `defaultRpcUrls`.
*
* The `setChain` function is straightforward, and it simply saves off the given chain data.
*
* The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
* we want to retrieve the RPC URL for `mainnet`:
* - If you have specified data with `setChain`, it will return that.
* - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
* is valid (e.g. a URL is specified, or an environment variable is given and exists).
* - If neither of the above conditions is met, the default data is returned.
*
* Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
*/
abstract contract StdChains {
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
bool private stdChainsInitialized;
struct ChainData {
string name;
uint256 chainId;
string rpcUrl;
}
struct Chain {
// The chain name.
string name;
// The chain's Chain ID.
uint256 chainId;
// The chain's alias. (i.e. what gets specified in `foundry.toml`).
string chainAlias;
// A default RPC endpoint for this chain.
// NOTE: This default RPC URL is included for convenience to facilitate quick tests and
// experimentation. Do not use this RPC URL for production test suites, CI, or other heavy
// usage as you will be throttled and this is a disservice to others who need this endpoint.
string rpcUrl;
}
// Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.
mapping(string => Chain) private chains;
// Maps from the chain's alias to it's default RPC URL.
mapping(string => string) private defaultRpcUrls;
// Maps from a chain ID to it's alias.
mapping(uint256 => string) private idToAlias;
bool private fallbackToDefaultRpcUrls = true;
// The RPC URL will be fetched from config or defaultRpcUrls if possible.
function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");
initializeStdChains();
chain = chains[chainAlias];
require(
chain.chainId != 0,
string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
);
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}
function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
initializeStdChains();
string memory chainAlias = idToAlias[chainId];
chain = chains[chainAlias];
require(
chain.chainId != 0,
string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
);
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}
// set chain info, with priority to argument's rpcUrl field.
function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
require(
bytes(chainAlias).length != 0,
"StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
);
require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
initializeStdChains();
string memory foundAlias = idToAlias[chain.chainId];
require(
bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),
string(
abi.encodePacked(
"StdChains setChain(string,ChainData): Chain ID ",
vm.toString(chain.chainId),
" already used by \"",
foundAlias,
"\"."
)
)
);
uint256 oldChainId = chains[chainAlias].chainId;
delete idToAlias[oldChainId];
chains[chainAlias] =
Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
idToAlias[chain.chainId] = chainAlias;
}
// set chain info, with priority to argument's rpcUrl field.
function setChain(string memory chainAlias, Chain memory chain) internal virtual {
setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
}
function _toUpper(string memory str) private pure returns (string memory) {
bytes memory strb = bytes(str);
bytes memory copy = new bytes(strb.length);
for (uint256 i = 0; i < strb.length; i++) {
bytes1 b = strb[i];
if (b >= 0x61 && b <= 0x7A) {
copy[i] = bytes1(uint8(b) - 32);
} else {
copy[i] = b;
}
}
return string(copy);
}
// lookup rpcUrl, in descending order of priority:
// current -> config (foundry.toml) -> environment variable -> default
function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)
private
view
returns (Chain memory)
{
if (bytes(chain.rpcUrl).length == 0) {
try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
chain.rpcUrl = configRpcUrl;
} catch (bytes memory err) {
string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
if (fallbackToDefaultRpcUrls) {
chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
} else {
chain.rpcUrl = vm.envString(envName);
}
// Distinguish 'not found' from 'cannot read'
// The upstream error thrown by forge for failing cheats changed so we check both the old and new versions
bytes memory oldNotFoundError =
abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
bytes memory newNotFoundError = abi.encodeWithSignature(
"CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
);
bytes32 errHash = keccak256(err);
if (
(errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError))
|| bytes(chain.rpcUrl).length == 0
) {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, err), mload(err))
}
}
}
}
return chain;
}
function setFallbackToDefaultRpcUrls(bool useDefault) internal {
fallbackToDefaultRpcUrls = useDefault;
}
function initializeStdChains() private {
if (stdChainsInitialized) return;
stdChainsInitialized = true;
// If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol`
setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
setChainWithDefaultRpcUrl("mainnet", ChainData("Mainnet", 1, "https://eth.llamarpc.com"));
setChainWithDefaultRpcUrl(
"sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
setChainWithDefaultRpcUrl("hoodi", ChainData("Hoodi", 560048, "https://rpc.hoodi.ethpandaops.io"));
setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
setChainWithDefaultRpcUrl(
"optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
);
setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl(
"arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
);
setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
setChainWithDefaultRpcUrl(
"polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
);
setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
setChainWithDefaultRpcUrl(
"avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
);
setChainWithDefaultRpcUrl(
"bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
);
setChainWithDefaultRpcUrl(
"bnb_smart_chain_testnet",
ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
);
setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
setChainWithDefaultRpcUrl(
"moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
);
setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io"));
setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io"));
setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/"));
setChainWithDefaultRpcUrl(
"fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/")
);
setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
setChainWithDefaultRpcUrl(
"berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com")
);
setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc"));
setChainWithDefaultRpcUrl(
"flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc")
);
setChainWithDefaultRpcUrl("mode", ChainData("Mode", 34443, "https://mode.drpc.org"));
setChainWithDefaultRpcUrl("mode_sepolia", ChainData("Mode Sepolia", 919, "https://sepolia.mode.network"));
setChainWithDefaultRpcUrl("zora", ChainData("Zora", 7777777, "https://zora.drpc.org"));
setChainWithDefaultRpcUrl(
"zora_sepolia", ChainData("Zora Sepolia", 999999999, "https://sepolia.rpc.zora.energy")
);
setChainWithDefaultRpcUrl("race", ChainData("Race", 6805, "https://racemainnet.io"));
setChainWithDefaultRpcUrl("race_sepolia", ChainData("Race Sepolia", 6806, "https://racemainnet.io"));
setChainWithDefaultRpcUrl("metal", ChainData("Metal", 1750, "https://metall2.drpc.org"));
setChainWithDefaultRpcUrl("metal_sepolia", ChainData("Metal Sepolia", 1740, "https://testnet.rpc.metall2.com"));
setChainWithDefaultRpcUrl("binary", ChainData("Binary", 624, "https://rpc.zero.thebinaryholdings.com"));
setChainWithDefaultRpcUrl(
"binary_sepolia", ChainData("Binary Sepolia", 625, "https://rpc.zero.thebinaryholdings.com")
);
setChainWithDefaultRpcUrl("orderly", ChainData("Orderly", 291, "https://rpc.orderly.network"));
setChainWithDefaultRpcUrl(
"orderly_sepolia", ChainData("Orderly Sepolia", 4460, "https://testnet-rpc.orderly.org")
);
}
// set chain info, with priority to chainAlias' rpc url in foundry.toml
function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
string memory rpcUrl = chain.rpcUrl;
defaultRpcUrls[chainAlias] = rpcUrl;
chain.rpcUrl = "";
setChain(chainAlias, chain);
chain.rpcUrl = rpcUrl; // restore argument
}
}
StdCheats.sol 829 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
import {StdStorage, stdStorage} from "./StdStorage.sol";
import {console2} from "./console2.sol";
import {Vm} from "./Vm.sol";
abstract contract StdCheatsSafe {
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
uint256 private constant UINT256_MAX =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
bool private gasMeteringOff;
// Data structures to parse Transaction objects from the broadcast artifact
// that conform to EIP1559. The Raw structs is what is parsed from the JSON
// and then converted to the one that is used by the user for better UX.
struct RawTx1559 {
string[] arguments;
address contractAddress;
string contractName;
// json value name = function
string functionSig;
bytes32 hash;
// json value name = tx
RawTx1559Detail txDetail;
// json value name = type
string opcode;
}
struct RawTx1559Detail {
AccessList[] accessList;
bytes data;
address from;
bytes gas;
bytes nonce;
address to;
bytes txType;
bytes value;
}
struct Tx1559 {
string[] arguments;
address contractAddress;
string contractName;
string functionSig;
bytes32 hash;
Tx1559Detail txDetail;
string opcode;
}
struct Tx1559Detail {
AccessList[] accessList;
bytes data;
address from;
uint256 gas;
uint256 nonce;
address to;
uint256 txType;
uint256 value;
}
// Data structures to parse Transaction objects from the broadcast artifact
// that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
// and then converted to the one that is used by the user for better UX.
struct TxLegacy {
string[] arguments;
address contractAddress;
string contractName;
string functionSig;
string hash;
string opcode;
TxDetailLegacy transaction;
}
struct TxDetailLegacy {
AccessList[] accessList;
uint256 chainId;
bytes data;
address from;
uint256 gas;
uint256 gasPrice;
bytes32 hash;
uint256 nonce;
bytes1 opcode;
bytes32 r;
bytes32 s;
uint256 txType;
address to;
uint8 v;
uint256 value;
}
struct AccessList {
address accessAddress;
bytes32[] storageKeys;
}
// Data structures to parse Receipt objects from the broadcast artifact.
// The Raw structs is what is parsed from the JSON
// and then converted to the one that is used by the user for better UX.
struct RawReceipt {
bytes32 blockHash;
bytes blockNumber;
address contractAddress;
bytes cumulativeGasUsed;
bytes effectiveGasPrice;
address from;
bytes gasUsed;
RawReceiptLog[] logs;
bytes logsBloom;
bytes status;
address to;
bytes32 transactionHash;
bytes transactionIndex;
}
struct Receipt {
bytes32 blockHash;
uint256 blockNumber;
address contractAddress;
uint256 cumulativeGasUsed;
uint256 effectiveGasPrice;
address from;
uint256 gasUsed;
ReceiptLog[] logs;
bytes logsBloom;
uint256 status;
address to;
bytes32 transactionHash;
uint256 transactionIndex;
}
// Data structures to parse the entire broadcast artifact, assuming the
// transactions conform to EIP1559.
struct EIP1559ScriptArtifact {
string[] libraries;
string path;
string[] pending;
Receipt[] receipts;
uint256 timestamp;
Tx1559[] transactions;
TxReturn[] txReturns;
}
struct RawEIP1559ScriptArtifact {
string[] libraries;
string path;
string[] pending;
RawReceipt[] receipts;
TxReturn[] txReturns;
uint256 timestamp;
RawTx1559[] transactions;
}
struct RawReceiptLog {
// json value = address
address logAddress;
bytes32 blockHash;
bytes blockNumber;
bytes data;
bytes logIndex;
bool removed;
bytes32[] topics;
bytes32 transactionHash;
bytes transactionIndex;
bytes transactionLogIndex;
}
struct ReceiptLog {
// json value = address
address logAddress;
bytes32 blockHash;
uint256 blockNumber;
bytes data;
uint256 logIndex;
bytes32[] topics;
uint256 transactionIndex;
uint256 transactionLogIndex;
bool removed;
}
struct TxReturn {
string internalType;
string value;
}
struct Account {
address addr;
uint256 key;
}
enum AddressType {
Payable,
NonPayable,
ZeroAddress,
Precompile,
ForgeAddress
}
// Checks that `addr` is not blacklisted by token contracts that have a blacklist.
function assumeNotBlacklisted(address token, address addr) internal view virtual {
// Nothing to check if `token` is not a contract.
uint256 tokenCodeSize;
assembly {
tokenCodeSize := extcodesize(token)
}
require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
bool success;
bytes memory returnData;
// 4-byte selector for `isBlacklisted(address)`, used by USDC.
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
vm.assume(!success || abi.decode(returnData, (bool)) == false);
// 4-byte selector for `isBlackListed(address)`, used by USDT.
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
vm.assume(!success || abi.decode(returnData, (bool)) == false);
}
// Checks that `addr` is not blacklisted by token contracts that have a blacklist.
// This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
// backwards compatibility, since this name was used in the original PR which already has
// a release. This function can be removed in a future release once we want a breaking change.
function assumeNoBlacklisted(address token, address addr) internal view virtual {
assumeNotBlacklisted(token, addr);
}
function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
if (addressType == AddressType.Payable) {
assumeNotPayable(addr);
} else if (addressType == AddressType.NonPayable) {
assumePayable(addr);
} else if (addressType == AddressType.ZeroAddress) {
assumeNotZeroAddress(addr);
} else if (addressType == AddressType.Precompile) {
assumeNotPrecompile(addr);
} else if (addressType == AddressType.ForgeAddress) {
assumeNotForgeAddress(addr);
}
}
function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
}
function assumeAddressIsNot(
address addr,
AddressType addressType1,
AddressType addressType2,
AddressType addressType3
) internal virtual {
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
assumeAddressIsNot(addr, addressType3);
}
function assumeAddressIsNot(
address addr,
AddressType addressType1,
AddressType addressType2,
AddressType addressType3,
AddressType addressType4
) internal virtual {
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
assumeAddressIsNot(addr, addressType3);
assumeAddressIsNot(addr, addressType4);
}
// This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
// `addr` and checking the `success` return value.
// NOTE: This function may result in state changes depending on the fallback/receive logic
// implemented by `addr`, which should be taken into account when this function is used.
function _isPayable(address addr) private returns (bool) {
require(
addr.balance < UINT256_MAX,
"StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
);
uint256 origBalanceTest = address(this).balance;
uint256 origBalanceAddr = address(addr).balance;
vm.deal(address(this), 1);
(bool success,) = payable(addr).call{value: 1}("");
// reset balances
vm.deal(address(this), origBalanceTest);
vm.deal(addr, origBalanceAddr);
return success;
}
// NOTE: This function may result in state changes depending on the fallback/receive logic
// implemented by `addr`, which should be taken into account when this function is used. See the
// `_isPayable` method for more information.
function assumePayable(address addr) internal virtual {
vm.assume(_isPayable(addr));
}
function assumeNotPayable(address addr) internal virtual {
vm.assume(!_isPayable(addr));
}
function assumeNotZeroAddress(address addr) internal pure virtual {
vm.assume(addr != address(0));
}
function assumeNotPrecompile(address addr) internal pure virtual {
assumeNotPrecompile(addr, _pureChainId());
}
function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
// Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
// address), but the same rationale for excluding them applies so we include those too.
// These are reserved by Ethereum and may be on all EVM-compatible chains.
vm.assume(addr < address(0x1) || addr > address(0xff));
// forgefmt: disable-start
if (chainId == 10 || chainId == 420) {
// https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
} else if (chainId == 42161 || chainId == 421613) {
// https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
} else if (chainId == 43114 || chainId == 43113) {
// https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
}
// forgefmt: disable-end
}
function assumeNotForgeAddress(address addr) internal pure virtual {
// vm, console, and Create2Deployer addresses
vm.assume(
addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
&& addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
);
}
function assumeUnusedAddress(address addr) internal view virtual {
uint256 size;
assembly {
size := extcodesize(addr)
}
vm.assume(size == 0);
assumeNotPrecompile(addr);
assumeNotZeroAddress(addr);
assumeNotForgeAddress(addr);
}
function readEIP1559ScriptArtifact(string memory path)
internal
view
virtual
returns (EIP1559ScriptArtifact memory)
{
string memory data = vm.readFile(path);
bytes memory parsedData = vm.parseJson(data);
RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
EIP1559ScriptArtifact memory artifact;
artifact.libraries = rawArtifact.libraries;
artifact.path = rawArtifact.path;
artifact.timestamp = rawArtifact.timestamp;
artifact.pending = rawArtifact.pending;
artifact.txReturns = rawArtifact.txReturns;
artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
return artifact;
}
function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
Tx1559[] memory txs = new Tx1559[](rawTxs.length);
for (uint256 i; i < rawTxs.length; i++) {
txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
}
return txs;
}
function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
Tx1559 memory transaction;
transaction.arguments = rawTx.arguments;
transaction.contractName = rawTx.contractName;
transaction.functionSig = rawTx.functionSig;
transaction.hash = rawTx.hash;
transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
transaction.opcode = rawTx.opcode;
return transaction;
}
function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
internal
pure
virtual
returns (Tx1559Detail memory)
{
Tx1559Detail memory txDetail;
txDetail.data = rawDetail.data;
txDetail.from = rawDetail.from;
txDetail.to = rawDetail.to;
txDetail.nonce = _bytesToUint(rawDetail.nonce);
txDetail.txType = _bytesToUint(rawDetail.txType);
txDetail.value = _bytesToUint(rawDetail.value);
txDetail.gas = _bytesToUint(rawDetail.gas);
txDetail.accessList = rawDetail.accessList;
return txDetail;
}
function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
string memory deployData = vm.readFile(path);
bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
return rawToConvertedEIPTx1559s(rawTxs);
}
function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
string memory deployData = vm.readFile(path);
string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
bytes memory parsedDeployData = vm.parseJson(deployData, key);
RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
return rawToConvertedEIPTx1559(rawTx);
}
// Analogous to readTransactions, but for receipts.
function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
string memory deployData = vm.readFile(path);
bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
return rawToConvertedReceipts(rawReceipts);
}
function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
string memory deployData = vm.readFile(path);
string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
bytes memory parsedDeployData = vm.parseJson(deployData, key);
RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
return rawToConvertedReceipt(rawReceipt);
}
function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
Receipt[] memory receipts = new Receipt[](rawReceipts.length);
for (uint256 i; i < rawReceipts.length; i++) {
receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
}
return receipts;
}
function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
Receipt memory receipt;
receipt.blockHash = rawReceipt.blockHash;
receipt.to = rawReceipt.to;
receipt.from = rawReceipt.from;
receipt.contractAddress = rawReceipt.contractAddress;
receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
receipt.status = _bytesToUint(rawReceipt.status);
receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
receipt.logsBloom = rawReceipt.logsBloom;
receipt.transactionHash = rawReceipt.transactionHash;
return receipt;
}
function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
internal
pure
virtual
returns (ReceiptLog[] memory)
{
ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
for (uint256 i; i < rawLogs.length; i++) {
logs[i].logAddress = rawLogs[i].logAddress;
logs[i].blockHash = rawLogs[i].blockHash;
logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
logs[i].data = rawLogs[i].data;
logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
logs[i].topics = rawLogs[i].topics;
logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
logs[i].removed = rawLogs[i].removed;
}
return logs;
}
// Deploy a contract by fetching the contract bytecode from
// the artifacts directory
// e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
/// @solidity memory-safe-assembly
assembly {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
}
function deployCode(string memory what) internal virtual returns (address addr) {
bytes memory bytecode = vm.getCode(what);
/// @solidity memory-safe-assembly
assembly {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
}
/// @dev deploy contract with value on construction
function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
/// @solidity memory-safe-assembly
assembly {
addr := create(val, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
}
function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
bytes memory bytecode = vm.getCode(what);
/// @solidity memory-safe-assembly
assembly {
addr := create(val, add(bytecode, 0x20), mload(bytecode))
}
require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
}
// creates a labeled address and the corresponding private key
function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
privateKey = uint256(keccak256(abi.encodePacked(name)));
addr = vm.addr(privateKey);
vm.label(addr, name);
}
// creates a labeled address
function makeAddr(string memory name) internal virtual returns (address addr) {
(addr,) = makeAddrAndKey(name);
}
// Destroys an account immediately, sending the balance to beneficiary.
// Destroying means: balance will be zero, code will be empty, and nonce will be 0
// This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
// only after tx ends, this will run immediately.
function destroyAccount(address who, address beneficiary) internal virtual {
uint256 currBalance = who.balance;
vm.etch(who, abi.encode());
vm.deal(who, 0);
vm.resetNonce(who);
uint256 beneficiaryBalance = beneficiary.balance;
vm.deal(beneficiary, currBalance + beneficiaryBalance);
}
// creates a struct containing both a labeled address and the corresponding private key
function makeAccount(string memory name) internal virtual returns (Account memory account) {
(account.addr, account.key) = makeAddrAndKey(name);
}
function deriveRememberKey(string memory mnemonic, uint32 index)
internal
virtual
returns (address who, uint256 privateKey)
{
privateKey = vm.deriveKey(mnemonic, index);
who = vm.rememberKey(privateKey);
}
function _bytesToUint(bytes memory b) private pure returns (uint256) {
require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
}
function isFork() internal view virtual returns (bool status) {
try vm.activeFork() {
status = true;
} catch (bytes memory) {}
}
modifier skipWhenForking() {
if (!isFork()) {
_;
}
}
modifier skipWhenNotForking() {
if (isFork()) {
_;
}
}
modifier noGasMetering() {
vm.pauseGasMetering();
// To prevent turning gas monitoring back on with nested functions that use this modifier,
// we check if gasMetering started in the off position. If it did, we don't want to turn
// it back on until we exit the top level function that used the modifier
//
// i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
// funcA will have `gasStartedOff` as false, funcB will have it as true,
// so we only turn metering back on at the end of the funcA
bool gasStartedOff = gasMeteringOff;
gasMeteringOff = true;
_;
// if gas metering was on when this modifier was called, turn it back on at the end
if (!gasStartedOff) {
gasMeteringOff = false;
vm.resumeGasMetering();
}
}
// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
// can't simply access the chain ID in a normal view or pure function because the solc View Pure
// Checker changed `chainid` from pure to view in 0.8.0.
function _viewChainId() private view returns (uint256 chainId) {
// Assembly required since `block.chainid` was introduced in 0.8.0.
assembly {
chainId := chainid()
}
address(this); // Silence warnings in older Solc versions.
}
function _pureChainId() private pure returns (uint256 chainId) {
function() internal view returns (uint256) fnIn = _viewChainId;
function() internal pure returns (uint256) pureChainId;
assembly {
pureChainId := fnIn
}
chainId = pureChainId();
}
}
// Wrappers around cheatcodes to avoid footguns
abstract contract StdCheats is StdCheatsSafe {
using stdStorage for StdStorage;
StdStorage private stdstore;
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
// Skip forward or rewind time by the specified number of seconds
function skip(uint256 time) internal virtual {
vm.warp(vm.getBlockTimestamp() + time);
}
function rewind(uint256 time) internal virtual {
vm.warp(vm.getBlockTimestamp() - time);
}
// Setup a prank from an address that has some ether
function hoax(address msgSender) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.prank(msgSender);
}
function hoax(address msgSender, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.prank(msgSender);
}
function hoax(address msgSender, address origin) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.prank(msgSender, origin);
}
function hoax(address msgSender, address origin, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.prank(msgSender, origin);
}
// Start perpetual prank from an address that has some ether
function startHoax(address msgSender) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.startPrank(msgSender);
}
function startHoax(address msgSender, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.startPrank(msgSender);
}
// Start perpetual prank from an address that has some ether
// tx.origin is set to the origin parameter
function startHoax(address msgSender, address origin) internal virtual {
vm.deal(msgSender, 1 << 128);
vm.startPrank(msgSender, origin);
}
function startHoax(address msgSender, address origin, uint256 give) internal virtual {
vm.deal(msgSender, give);
vm.startPrank(msgSender, origin);
}
function changePrank(address msgSender) internal virtual {
console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
vm.stopPrank();
vm.startPrank(msgSender);
}
function changePrank(address msgSender, address txOrigin) internal virtual {
vm.stopPrank();
vm.startPrank(msgSender, txOrigin);
}
// The same as Vm's `deal`
// Use the alternative signature for ERC20 tokens
function deal(address to, uint256 give) internal virtual {
vm.deal(to, give);
}
// Set the balance of an account for any ERC20 token
// Use the alternative signature to update `totalSupply`
function deal(address token, address to, uint256 give) internal virtual {
deal(token, to, give, false);
}
// Set the balance of an account for any ERC1155 token
// Use the alternative signature to update `totalSupply`
function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
dealERC1155(token, to, id, give, false);
}
function deal(address token, address to, uint256 give, bool adjust) internal virtual {
// get current balance
(, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
uint256 prevBal = abi.decode(balData, (uint256));
// update balance
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
// update total supply
if (adjust) {
(, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
uint256 totSup = abi.decode(totSupData, (uint256));
if (give < prevBal) {
totSup -= (prevBal - give);
} else {
totSup += (give - prevBal);
}
stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
}
}
function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
// get current balance
(, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
uint256 prevBal = abi.decode(balData, (uint256));
// update balance
stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
// update total supply
if (adjust) {
(, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
require(
totSupData.length != 0,
"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
);
uint256 totSup = abi.decode(totSupData, (uint256));
if (give < prevBal) {
totSup -= (prevBal - give);
} else {
totSup += (give - prevBal);
}
stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
}
}
function dealERC721(address token, address to, uint256 id) internal virtual {
// check if token id is already minted and the actual owner.
(bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
// get owner current balance
(, bytes memory fromBalData) =
token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
// get new user current balance
(, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
uint256 toPrevBal = abi.decode(toBalData, (uint256));
// update balances
stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
// update owner
stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
}
function deployCodeTo(string memory what, address where) internal virtual {
deployCodeTo(what, "", 0, where);
}
function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
deployCodeTo(what, args, 0, where);
}
function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
bytes memory creationCode = vm.getCode(what);
vm.etch(where, abi.encodePacked(creationCode, args));
(bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
vm.etch(where, runtimeBytecode);
}
// Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
function console2_log_StdCheats(string memory p0) private view {
(bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
status;
}
}
StdConstants.sol 30 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
import {IMulticall3} from "./interfaces/IMulticall3.sol";
import {Vm} from "./Vm.sol";
library StdConstants {
/// @dev Cheat code address.
/// Calculated as `address(uint160(uint256(keccak256("hevm cheat code"))))`.
Vm internal constant VM = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
/// @dev console.sol and console2.sol work by executing a staticcall to this address.
/// Calculated as `address(uint160(uint88(bytes11("console.log"))))`.
address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
/// @dev Used when deploying with create2.
/// Taken from https://github.com/Arachnid/deterministic-deployment-proxy.
address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
/// @dev The default address for tx.origin and msg.sender.
/// Calculated as `address(uint160(uint256(keccak256("foundry default caller"))))`.
address internal constant DEFAULT_SENDER = 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
/// @dev The address of the first contract `CREATE`d by a running test contract.
/// When running tests, each test contract is `CREATE`d by `DEFAULT_SENDER` with nonce 1.
/// Calculated as `VM.computeCreateAddress(VM.computeCreateAddress(DEFAULT_SENDER, 1), 1)`.
address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
/// @dev Deterministic deployment address of the Multicall3 contract.
/// Taken from https://www.multicall3.com.
IMulticall3 internal constant MULTICALL3_ADDRESS = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
/// @dev The order of the secp256k1 curve.
uint256 internal constant SECP256K1_ORDER =
115792089237316195423570985008687907852837564279074904382605163141518161494337;
}
StdJson.sol 283 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;
import {VmSafe} from "./Vm.sol";
// Helpers for parsing and writing JSON files
// To parse:
// ```
// using stdJson for string;
// string memory json = vm.readFile("<some_path>");
// json.readUint("<json_path>");
// ```
// To write:
// ```
// using stdJson for string;
// string memory json = "json";
// json.serialize("a", uint256(123));
// string memory semiFinal = json.serialize("b", string("test"));
// string memory finalJson = json.serialize("c", semiFinal);
// finalJson.write("<some_path>");
// ```
library stdJson {
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
function keyExists(string memory json, string memory key) internal view returns (bool) {
return vm.keyExistsJson(json, key);
}
function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
return vm.parseJson(json, key);
}
function readUint(string memory json, string memory key) internal pure returns (uint256) {
return vm.parseJsonUint(json, key);
}
function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
return vm.parseJsonUintArray(json, key);
}
function readInt(string memory json, string memory key) internal pure returns (int256) {
return vm.parseJsonInt(json, key);
}
function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
return vm.parseJsonIntArray(json, key);
}
function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
return vm.parseJsonBytes32(json, key);
}
function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
return vm.parseJsonBytes32Array(json, key);
}
function readString(string memory json, string memory key) internal pure returns (string memory) {
return vm.parseJsonString(json, key);
}
function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
return vm.parseJsonStringArray(json, key);
}
function readAddress(string memory json, string memory key) internal pure returns (address) {
return vm.parseJsonAddress(json, key);
}
function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
return vm.parseJsonAddressArray(json, key);
}
function readBool(string memory json, string memory key) internal pure returns (bool) {
return vm.parseJsonBool(json, key);
}
function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
return vm.parseJsonBoolArray(json, key);
}
function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
return vm.parseJsonBytes(json, key);
}
function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
return vm.parseJsonBytesArray(json, key);
}
function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) {
return keyExists(json, key) ? readUint(json, key) : defaultValue;
}
function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue)
internal
view
returns (uint256[] memory)
{
return keyExists(json, key) ? readUintArray(json, key) : defaultValue;
}
function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) {
return keyExists(json, key) ? readInt(json, key) : defaultValue;
}
function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue)
internal
view
returns (int256[] memory)
{
return keyExists(json, key) ? readIntArray(json, key) : defaultValue;
}
function readBytes32Or(string memory json, string memory key, bytes32 defaultValue)
internal
view
returns (bytes32)
{
return keyExists(json, key) ? readBytes32(json, key) : defaultValue;
}
function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue)
internal
view
returns (bytes32[] memory)
{
return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue;
}
function readStringOr(string memory json, string memory key, string memory defaultValue)
internal
view
returns (string memory)
{
return keyExists(json, key) ? readString(json, key) : defaultValue;
}
function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue)
internal
view
returns (string[] memory)
{
return keyExists(json, key) ? readStringArray(json, key) : defaultValue;
}
function readAddressOr(string memory json, string memory key, address defaultValue)
internal
view
returns (address)
{
return keyExists(json, key) ? readAddress(json, key) : defaultValue;
}
function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue)
internal
view
returns (address[] memory)
{
return keyExists(json, key) ? readAddressArray(json, key) : defaultValue;
}
function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) {
return keyExists(json, key) ? readBool(json, key) : defaultValue;
}
function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue)
internal
view
returns (bool[] memory)
{
return keyExists(json, key) ? readBoolArray(json, key) : defaultValue;
}
function readBytesOr(string memory json, string memory key, bytes memory defaultValue)
internal
view
returns (bytes memory)
{
return keyExists(json, key) ? readBytes(json, key) : defaultValue;
}
function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue)
internal
view
returns (bytes[] memory)
{
return keyExists(json, key) ? readBytesArray(json, key) : defaultValue;
}
function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
return vm.serializeJson(jsonKey, rootObject);
}
function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
return vm.serializeBool(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bool[] memory value)
internal
returns (string memory)
{
return vm.serializeBool(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
return vm.serializeUint(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, uint256[] memory value)
internal
returns (string memory)
{
return vm.serializeUint(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
return vm.serializeInt(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, int256[] memory value)
internal
returns (string memory)
{
return vm.serializeInt(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
return vm.serializeAddress(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, address[] memory value)
internal
returns (string memory)
{
return vm.serializeAddress(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
return vm.serializeBytes32(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
internal
returns (string memory)
{
return vm.serializeBytes32(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
return vm.serializeBytes(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, bytes[] memory value)
internal
returns (string memory)
{
return vm.serializeBytes(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, string memory value)
internal
returns (string memory)
{
return vm.serializeString(jsonKey, key, value);
}
function serialize(string memory jsonKey, string memory key, string[] memory value)
internal
returns (string memory)
{
return vm.serializeString(jsonKey, key, value);
}
function write(string memory jsonKey, string memory path) internal {
vm.writeJson(jsonKey, path);
}
function write(string memory jsonKey, string memory path, string memory valueKey) internal {
vm.writeJson(jsonKey, path, valueKey);
}
}
StdMath.sol 43 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
library stdMath {
int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;
function abs(int256 a) internal pure returns (uint256) {
// Required or it will fail when `a = type(int256).min`
if (a == INT256_MIN) {
return 57896044618658097711785492504343953926634992332820282019728792003956564819968;
}
return uint256(a > 0 ? a : -a);
}
function delta(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a - b : b - a;
}
function delta(int256 a, int256 b) internal pure returns (uint256) {
// a and b are of the same sign
// this works thanks to two's complement, the left-most bit is the sign bit
if ((a ^ b) > -1) {
return delta(abs(a), abs(b));
}
// a and b are of opposite signs
return abs(a) + abs(b);
}
function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 absDelta = delta(a, b);
return absDelta * 1e18 / b;
}
function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
uint256 absDelta = delta(a, b);
uint256 absB = abs(b);
return absDelta * 1e18 / absB;
}
}
StdStorage.sol 473 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
import {Vm} from "./Vm.sol";
struct FindData {
uint256 slot;
uint256 offsetLeft;
uint256 offsetRight;
bool found;
}
struct StdStorage {
mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds;
bytes32[] _keys;
bytes4 _sig;
uint256 _depth;
address _target;
bytes32 _set;
bool _enable_packed_slots;
bytes _calldata;
}
library stdStorageSafe {
event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
event WARNING_UninitedSlot(address who, uint256 slot);
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
function sigs(string memory sigStr) internal pure returns (bytes4) {
return bytes4(keccak256(bytes(sigStr)));
}
function getCallParams(StdStorage storage self) internal view returns (bytes memory) {
if (self._calldata.length == 0) {
return flatten(self._keys);
} else {
return self._calldata;
}
}
// Calls target contract with configured parameters
function callTarget(StdStorage storage self) internal view returns (bool, bytes32) {
bytes memory cd = abi.encodePacked(self._sig, getCallParams(self));
(bool success, bytes memory rdat) = self._target.staticcall(cd);
bytes32 result = bytesToBytes32(rdat, 32 * self._depth);
return (success, result);
}
// Tries mutating slot value to determine if the targeted value is stored in it.
// If current value is 0, then we are setting slot value to type(uint256).max
// Otherwise, we set it to 0. That way, return value should always be affected.
function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) {
bytes32 prevSlotValue = vm.load(self._target, slot);
(bool success, bytes32 prevReturnValue) = callTarget(self);
bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0);
vm.store(self._target, slot, testVal);
(, bytes32 newReturnValue) = callTarget(self);
vm.store(self._target, slot, prevSlotValue);
return (success && (prevReturnValue != newReturnValue));
}
// Tries setting one of the bits in slot to 1 until return value changes.
// Index of resulted bit is an offset packed slot has from left/right side
function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) {
for (uint256 offset = 0; offset < 256; offset++) {
uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset);
vm.store(self._target, slot, bytes32(valueToPut));
(bool success, bytes32 data) = callTarget(self);
if (success && (uint256(data) > 0)) {
return (true, offset);
}
}
return (false, 0);
}
function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) {
bytes32 prevSlotValue = vm.load(self._target, slot);
(bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true);
(bool foundRight, uint256 offsetRight) = findOffset(self, slot, false);
// `findOffset` may mutate slot value, so we are setting it to initial value
vm.store(self._target, slot, prevSlotValue);
return (foundLeft && foundRight, offsetLeft, offsetRight);
}
function find(StdStorage storage self) internal returns (FindData storage) {
return find(self, true);
}
/// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
// slot complexity:
// if flat, will be bytes32(uint256(uint));
// if map, will be keccak256(abi.encode(key, uint(slot)));
// if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
// if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
function find(StdStorage storage self, bool _clear) internal returns (FindData storage) {
address who = self._target;
bytes4 fsig = self._sig;
uint256 field_depth = self._depth;
bytes memory params = getCallParams(self);
// calldata to test against
if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
if (_clear) {
clear(self);
}
return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
}
vm.record();
(, bytes32 callResult) = callTarget(self);
(bytes32[] memory reads,) = vm.accesses(address(who));
if (reads.length == 0) {
revert("stdStorage find(StdStorage): No storage use detected for target.");
} else {
for (uint256 i = reads.length; --i >= 0;) {
bytes32 prev = vm.load(who, reads[i]);
if (prev == bytes32(0)) {
emit WARNING_UninitedSlot(who, uint256(reads[i]));
}
if (!checkSlotMutatesCall(self, reads[i])) {
continue;
}
(uint256 offsetLeft, uint256 offsetRight) = (0, 0);
if (self._enable_packed_slots) {
bool found;
(found, offsetLeft, offsetRight) = findOffsets(self, reads[i]);
if (!found) {
continue;
}
}
// Check that value between found offsets is equal to the current call result
uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight;
if (uint256(callResult) != curVal) {
continue;
}
emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i]));
self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] =
FindData(uint256(reads[i]), offsetLeft, offsetRight, true);
break;
}
}
require(
self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found,
"stdStorage find(StdStorage): Slot(s) not found."
);
if (_clear) {
clear(self);
}
return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
}
function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
self._target = _target;
return self;
}
function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
self._sig = _sig;
return self;
}
function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
self._sig = sigs(_sig);
return self;
}
function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
self._calldata = _calldata;
return self;
}
function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
self._keys.push(bytes32(uint256(uint160(who))));
return self;
}
function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
self._keys.push(bytes32(amt));
return self;
}
function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
self._keys.push(key);
return self;
}
function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
self._enable_packed_slots = true;
return self;
}
function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
self._depth = _depth;
return self;
}
function read(StdStorage storage self) private returns (bytes memory) {
FindData storage data = find(self, false);
uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight);
uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight;
clear(self);
return abi.encode(value);
}
function read_bytes32(StdStorage storage self) internal returns (bytes32) {
return abi.decode(read(self), (bytes32));
}
function read_bool(StdStorage storage self) internal returns (bool) {
int256 v = read_int(self);
if (v == 0) return false;
if (v == 1) return true;
revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
}
function read_address(StdStorage storage self) internal returns (address) {
return abi.decode(read(self), (address));
}
function read_uint(StdStorage storage self) internal returns (uint256) {
return abi.decode(read(self), (uint256));
}
function read_int(StdStorage storage self) internal returns (int256) {
return abi.decode(read(self), (int256));
}
function parent(StdStorage storage self) internal returns (uint256, bytes32) {
address who = self._target;
uint256 field_depth = self._depth;
vm.startMappingRecording();
uint256 child = find(self, true).slot - field_depth;
(bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
if (!found) {
revert(
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
);
}
return (uint256(parent_slot), key);
}
function root(StdStorage storage self) internal returns (uint256) {
address who = self._target;
uint256 field_depth = self._depth;
vm.startMappingRecording();
uint256 child = find(self, true).slot - field_depth;
bool found;
bytes32 root_slot;
bytes32 parent_slot;
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
if (!found) {
revert(
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
);
}
while (found) {
root_slot = parent_slot;
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
}
return uint256(root_slot);
}
function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
bytes32 out;
uint256 max = b.length > 32 ? 32 : b.length;
for (uint256 i = 0; i < max; i++) {
out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
}
return out;
}
function flatten(bytes32[] memory b) private pure returns (bytes memory) {
bytes memory result = new bytes(b.length * 32);
for (uint256 i = 0; i < b.length; i++) {
bytes32 k = b[i];
/// @solidity memory-safe-assembly
assembly {
mstore(add(result, add(32, mul(32, i))), k)
}
}
return result;
}
function clear(StdStorage storage self) internal {
delete self._target;
delete self._sig;
delete self._keys;
delete self._depth;
delete self._enable_packed_slots;
delete self._calldata;
}
// Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight`
// (slotValue & mask) >> offsetRight will be the value of the given packed variable
function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) {
// mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight;
// using assembly because (1 << 256) causes overflow
assembly {
mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1))
}
}
// Returns slot value with updated packed variable.
function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight)
internal
pure
returns (bytes32 newValue)
{
return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight));
}
}
library stdStorage {
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
function sigs(string memory sigStr) internal pure returns (bytes4) {
return stdStorageSafe.sigs(sigStr);
}
function find(StdStorage storage self) internal returns (uint256) {
return find(self, true);
}
function find(StdStorage storage self, bool _clear) internal returns (uint256) {
return stdStorageSafe.find(self, _clear).slot;
}
function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
return stdStorageSafe.target(self, _target);
}
function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
return stdStorageSafe.sig(self, _sig);
}
function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
return stdStorageSafe.sig(self, _sig);
}
function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
return stdStorageSafe.with_key(self, who);
}
function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
return stdStorageSafe.with_key(self, amt);
}
function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
return stdStorageSafe.with_key(self, key);
}
function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
return stdStorageSafe.with_calldata(self, _calldata);
}
function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
return stdStorageSafe.enable_packed_slots(self);
}
function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
return stdStorageSafe.depth(self, _depth);
}
function clear(StdStorage storage self) internal {
stdStorageSafe.clear(self);
}
function checked_write(StdStorage storage self, address who) internal {
checked_write(self, bytes32(uint256(uint160(who))));
}
function checked_write(StdStorage storage self, uint256 amt) internal {
checked_write(self, bytes32(amt));
}
function checked_write_int(StdStorage storage self, int256 val) internal {
checked_write(self, bytes32(uint256(val)));
}
function checked_write(StdStorage storage self, bool write) internal {
bytes32 t;
/// @solidity memory-safe-assembly
assembly {
t := write
}
checked_write(self, t);
}
function checked_write(StdStorage storage self, bytes32 set) internal {
address who = self._target;
bytes4 fsig = self._sig;
uint256 field_depth = self._depth;
bytes memory params = stdStorageSafe.getCallParams(self);
if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
find(self, false);
}
FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
if ((data.offsetLeft + data.offsetRight) > 0) {
uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight));
require(
uint256(set) < maxVal,
string(
abi.encodePacked(
"stdStorage find(StdStorage): Packed slot. We can't fit value greater than ",
vm.toString(maxVal)
)
)
);
}
bytes32 curVal = vm.load(who, bytes32(data.slot));
bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight);
vm.store(who, bytes32(data.slot), valToSet);
(bool success, bytes32 callResult) = stdStorageSafe.callTarget(self);
if (!success || callResult != set) {
vm.store(who, bytes32(data.slot), curVal);
revert("stdStorage find(StdStorage): Failed to write value.");
}
clear(self);
}
function read_bytes32(StdStorage storage self) internal returns (bytes32) {
return stdStorageSafe.read_bytes32(self);
}
function read_bool(StdStorage storage self) internal returns (bool) {
return stdStorageSafe.read_bool(self);
}
function read_address(StdStorage storage self) internal returns (address) {
return stdStorageSafe.read_address(self);
}
function read_uint(StdStorage storage self) internal returns (uint256) {
return stdStorageSafe.read_uint(self);
}
function read_int(StdStorage storage self) internal returns (int256) {
return stdStorageSafe.read_int(self);
}
function parent(StdStorage storage self) internal returns (uint256, bytes32) {
return stdStorageSafe.parent(self);
}
function root(StdStorage storage self) internal returns (uint256) {
return stdStorageSafe.root(self);
}
}
StdStyle.sol 333 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import {VmSafe} from "./Vm.sol";
library StdStyle {
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
string constant RED = "\u001b[91m";
string constant GREEN = "\u001b[92m";
string constant YELLOW = "\u001b[93m";
string constant BLUE = "\u001b[94m";
string constant MAGENTA = "\u001b[95m";
string constant CYAN = "\u001b[96m";
string constant BOLD = "\u001b[1m";
string constant DIM = "\u001b[2m";
string constant ITALIC = "\u001b[3m";
string constant UNDERLINE = "\u001b[4m";
string constant INVERSE = "\u001b[7m";
string constant RESET = "\u001b[0m";
function styleConcat(string memory style, string memory self) private pure returns (string memory) {
return string(abi.encodePacked(style, self, RESET));
}
function red(string memory self) internal pure returns (string memory) {
return styleConcat(RED, self);
}
function red(uint256 self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function red(int256 self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function red(address self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function red(bool self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function redBytes(bytes memory self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function redBytes32(bytes32 self) internal pure returns (string memory) {
return red(vm.toString(self));
}
function green(string memory self) internal pure returns (string memory) {
return styleConcat(GREEN, self);
}
function green(uint256 self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function green(int256 self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function green(address self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function green(bool self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function greenBytes(bytes memory self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function greenBytes32(bytes32 self) internal pure returns (string memory) {
return green(vm.toString(self));
}
function yellow(string memory self) internal pure returns (string memory) {
return styleConcat(YELLOW, self);
}
function yellow(uint256 self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellow(int256 self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellow(address self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellow(bool self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellowBytes(bytes memory self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function yellowBytes32(bytes32 self) internal pure returns (string memory) {
return yellow(vm.toString(self));
}
function blue(string memory self) internal pure returns (string memory) {
return styleConcat(BLUE, self);
}
function blue(uint256 self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blue(int256 self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blue(address self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blue(bool self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blueBytes(bytes memory self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function blueBytes32(bytes32 self) internal pure returns (string memory) {
return blue(vm.toString(self));
}
function magenta(string memory self) internal pure returns (string memory) {
return styleConcat(MAGENTA, self);
}
function magenta(uint256 self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magenta(int256 self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magenta(address self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magenta(bool self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magentaBytes(bytes memory self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function magentaBytes32(bytes32 self) internal pure returns (string memory) {
return magenta(vm.toString(self));
}
function cyan(string memory self) internal pure returns (string memory) {
return styleConcat(CYAN, self);
}
function cyan(uint256 self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyan(int256 self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyan(address self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyan(bool self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyanBytes(bytes memory self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function cyanBytes32(bytes32 self) internal pure returns (string memory) {
return cyan(vm.toString(self));
}
function bold(string memory self) internal pure returns (string memory) {
return styleConcat(BOLD, self);
}
function bold(uint256 self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function bold(int256 self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function bold(address self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function bold(bool self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function boldBytes(bytes memory self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function boldBytes32(bytes32 self) internal pure returns (string memory) {
return bold(vm.toString(self));
}
function dim(string memory self) internal pure returns (string memory) {
return styleConcat(DIM, self);
}
function dim(uint256 self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dim(int256 self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dim(address self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dim(bool self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dimBytes(bytes memory self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function dimBytes32(bytes32 self) internal pure returns (string memory) {
return dim(vm.toString(self));
}
function italic(string memory self) internal pure returns (string memory) {
return styleConcat(ITALIC, self);
}
function italic(uint256 self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italic(int256 self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italic(address self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italic(bool self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italicBytes(bytes memory self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function italicBytes32(bytes32 self) internal pure returns (string memory) {
return italic(vm.toString(self));
}
function underline(string memory self) internal pure returns (string memory) {
return styleConcat(UNDERLINE, self);
}
function underline(uint256 self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underline(int256 self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underline(address self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underline(bool self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underlineBytes(bytes memory self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function underlineBytes32(bytes32 self) internal pure returns (string memory) {
return underline(vm.toString(self));
}
function inverse(string memory self) internal pure returns (string memory) {
return styleConcat(INVERSE, self);
}
function inverse(uint256 self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverse(int256 self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverse(address self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverse(bool self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverseBytes(bytes memory self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
function inverseBytes32(bytes32 self) internal pure returns (string memory) {
return inverse(vm.toString(self));
}
}
StdUtils.sol 208 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
import {IMulticall3} from "./interfaces/IMulticall3.sol";
import {VmSafe} from "./Vm.sol";
abstract contract StdUtils {
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/
IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
uint256 private constant INT256_MIN_ABS =
57896044618658097711785492504343953926634992332820282019728792003956564819968;
uint256 private constant SECP256K1_ORDER =
115792089237316195423570985008687907852837564279074904382605163141518161494337;
uint256 private constant UINT256_MAX =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
// Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
/*//////////////////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
// If x is between min and max, return x directly. This is to ensure that dictionary values
// do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
if (x >= min && x <= max) return x;
uint256 size = max - min + 1;
// If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
// This helps ensure coverage of the min/max values.
if (x <= 3 && size > x) return min + x;
if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
// Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
if (x > max) {
uint256 diff = x - max;
uint256 rem = diff % size;
if (rem == 0) return max;
result = min + rem - 1;
} else if (x < min) {
uint256 diff = min - x;
uint256 rem = diff % size;
if (rem == 0) return min;
result = max - rem + 1;
}
}
function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
result = _bound(x, min, max);
console2_log_StdUtils("Bound result", result);
}
function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
// Shifting all int256 values to uint256 to use _bound function. The range of two types are:
// int256 : -(2**255) ~ (2**255 - 1)
// uint256: 0 ~ (2**256 - 1)
// So, add 2**255, INT256_MIN_ABS to the integer values.
//
// If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
// So, use `~uint256(x) + 1` instead.
uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
uint256 y = _bound(_x, _min, _max);
// To move it back to int256 value, subtract INT256_MIN_ABS at here.
result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
}
function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
result = _bound(x, min, max);
console2_log_StdUtils("Bound result", vm.toString(result));
}
function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
}
function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
}
/// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
return vm.computeCreateAddress(deployer, nonce);
}
function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
internal
pure
virtual
returns (address)
{
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
return vm.computeCreate2Address(salt, initcodeHash, deployer);
}
/// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
return vm.computeCreate2Address(salt, initCodeHash);
}
/// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
return hashInitCode(creationCode, "");
}
/// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
/// @param args the ABI-encoded arguments to the constructor of C
function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(creationCode, args));
}
// Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
function getTokenBalances(address token, address[] memory addresses)
internal
virtual
returns (uint256[] memory balances)
{
uint256 tokenCodeSize;
assembly {
tokenCodeSize := extcodesize(token)
}
require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
// ABI encode the aggregate call to Multicall3.
uint256 length = addresses.length;
IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
for (uint256 i = 0; i < length; ++i) {
// 0x70a08231 = bytes4("balanceOf(address)"))
calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
}
// Make the aggregate call.
(, bytes[] memory returnData) = multicall.aggregate(calls);
// ABI decode the return data and return the balances.
balances = new uint256[](length);
for (uint256 i = 0; i < length; ++i) {
balances[i] = abi.decode(returnData[i], (uint256));
}
}
/*//////////////////////////////////////////////////////////////////////////
PRIVATE FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
return address(uint160(uint256(bytesValue)));
}
// This section is used to prevent the compilation of console, which shortens the compilation time when console is
// not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
// any breaking changes to function signatures.
function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
internal
pure
returns (function(bytes memory) internal pure fnOut)
{
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castLogPayloadViewToPure(_sendLogPayloadView)(payload);
}
function _sendLogPayloadView(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE2_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function console2_log_StdUtils(string memory p0) private pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function console2_log_StdUtils(string memory p0, string memory p1) private pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
}
Vm.sol 2494 lines
// Automatically @generated by scripts/vm.py. Do not modify manually.
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
/// result in Script simulations differing from on-chain execution. It is recommended to only use
/// these cheats in scripts.
interface VmSafe {
/// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.
enum CallerMode {
// No caller modification is currently active.
None,
// A one time broadcast triggered by a `vm.broadcast()` call is currently active.
Broadcast,
// A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
RecurrentBroadcast,
// A one time prank triggered by a `vm.prank()` call is currently active.
Prank,
// A recurrent prank triggered by a `vm.startPrank()` call is currently active.
RecurrentPrank
}
/// The kind of account access that occurred.
enum AccountAccessKind {
// The account was called.
Call,
// The account was called via delegatecall.
DelegateCall,
// The account was called via callcode.
CallCode,
// The account was called via staticcall.
StaticCall,
// The account was created.
Create,
// The account was selfdestructed.
SelfDestruct,
// Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
Resume,
// The account's balance was read.
Balance,
// The account's codesize was read.
Extcodesize,
// The account's codehash was read.
Extcodehash,
// The account's code was copied.
Extcodecopy
}
/// Forge execution contexts.
enum ForgeContext {
// Test group execution context (test, coverage or snapshot).
TestGroup,
// `forge test` execution context.
Test,
// `forge coverage` execution context.
Coverage,
// `forge snapshot` execution context.
Snapshot,
// Script group execution context (dry run, broadcast or resume).
ScriptGroup,
// `forge script` execution context.
ScriptDryRun,
// `forge script --broadcast` execution context.
ScriptBroadcast,
// `forge script --resume` execution context.
ScriptResume,
// Unknown `forge` execution context.
Unknown
}
/// The transaction type (`txType`) of the broadcast.
enum BroadcastTxType {
// Represents a CALL broadcast tx.
Call,
// Represents a CREATE broadcast tx.
Create,
// Represents a CREATE2 broadcast tx.
Create2
}
/// An Ethereum log. Returned by `getRecordedLogs`.
struct Log {
// The topics of the log, including the signature, if any.
bytes32[] topics;
// The raw data of the log.
bytes data;
// The address of the log's emitter.
address emitter;
}
/// An RPC URL and its alias. Returned by `rpcUrlStructs`.
struct Rpc {
// The alias of the RPC URL.
string key;
// The RPC URL.
string url;
}
/// An RPC log object. Returned by `eth_getLogs`.
struct EthGetLogs {
// The address of the log's emitter.
address emitter;
// The topics of the log, including the signature, if any.
bytes32[] topics;
// The raw data of the log.
bytes data;
// The block hash.
bytes32 blockHash;
// The block number.
uint64 blockNumber;
// The transaction hash.
bytes32 transactionHash;
// The transaction index in the block.
uint64 transactionIndex;
// The log index.
uint256 logIndex;
// Whether the log was removed.
bool removed;
}
/// A single entry in a directory listing. Returned by `readDir`.
struct DirEntry {
// The error message, if any.
string errorMessage;
// The path of the entry.
string path;
// The depth of the entry.
uint64 depth;
// Whether the entry is a directory.
bool isDir;
// Whether the entry is a symlink.
bool isSymlink;
}
/// Metadata information about a file.
/// This structure is returned from the `fsMetadata` function and represents known
/// metadata about a file such as its permissions, size, modification
/// times, etc.
struct FsMetadata {
// True if this metadata is for a directory.
bool isDir;
// True if this metadata is for a symlink.
bool isSymlink;
// The size of the file, in bytes, this metadata is for.
uint256 length;
// True if this metadata is for a readonly (unwritable) file.
bool readOnly;
// The last modification time listed in this metadata.
uint256 modified;
// The last access time of this metadata.
uint256 accessed;
// The creation time listed in this metadata.
uint256 created;
}
/// A wallet with a public and private key.
struct Wallet {
// The wallet's address.
address addr;
// The wallet's public key `X`.
uint256 publicKeyX;
// The wallet's public key `Y`.
uint256 publicKeyY;
// The wallet's private key.
uint256 privateKey;
}
/// The result of a `tryFfi` call.
struct FfiResult {
// The exit code of the call.
int32 exitCode;
// The optionally hex-decoded `stdout` data.
bytes stdout;
// The `stderr` data.
bytes stderr;
}
/// Information on the chain and fork.
struct ChainInfo {
// The fork identifier. Set to zero if no fork is active.
uint256 forkId;
// The chain ID of the current fork.
uint256 chainId;
}
/// Information about a blockchain.
struct Chain {
// The chain name.
string name;
// The chain's Chain ID.
uint256 chainId;
// The chain's alias. (i.e. what gets specified in `foundry.toml`).
string chainAlias;
// A default RPC endpoint for this chain.
string rpcUrl;
}
/// The result of a `stopAndReturnStateDiff` call.
struct AccountAccess {
// The chain and fork the access occurred.
ChainInfo chainInfo;
// The kind of account access that determines what the account is.
// If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.
// If kind is Create, then the account is the newly created account.
// If kind is SelfDestruct, then the account is the selfdestruct recipient.
// If kind is a Resume, then account represents a account context that has resumed.
AccountAccessKind kind;
// The account that was accessed.
// It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
address account;
// What accessed the account.
address accessor;
// If the account was initialized or empty prior to the access.
// An account is considered initialized if it has code, a
// non-zero nonce, or a non-zero balance.
bool initialized;
// The previous balance of the accessed account.
uint256 oldBalance;
// The potential new balance of the accessed account.
// That is, all balance changes are recorded here, even if reverts occurred.
uint256 newBalance;
// Code of the account deployed by CREATE.
bytes deployedCode;
// Value passed along with the account access
uint256 value;
// Input data provided to the CREATE or CALL
bytes data;
// If this access reverted in either the current or parent context.
bool reverted;
// An ordered list of storage accesses made during an account access operation.
StorageAccess[] storageAccesses;
// Call depth traversed during the recording of state differences
uint64 depth;
// The previous nonce of the accessed account.
uint64 oldNonce;
// The new nonce of the accessed account.
uint64 newNonce;
}
/// The storage accessed during an `AccountAccess`.
struct StorageAccess {
// The account whose storage was accessed.
address account;
// The slot that was accessed.
bytes32 slot;
// If the access was a write.
bool isWrite;
// The previous value of the slot.
bytes32 previousValue;
// The new value of the slot.
bytes32 newValue;
// If the access was reverted.
bool reverted;
}
/// Gas used. Returned by `lastCallGas`.
struct Gas {
// The gas limit of the call.
uint64 gasLimit;
// The total gas used.
uint64 gasTotalUsed;
// DEPRECATED: The amount of gas used for memory expansion. Ref: <https://github.com/foundry-rs/foundry/pull/7934#pullrequestreview-2069236939>
uint64 gasMemoryUsed;
// The amount of gas refunded.
int64 gasRefunded;
// The amount of gas remaining.
uint64 gasRemaining;
}
/// The result of the `stopDebugTraceRecording` call
struct DebugStep {
// The stack before executing the step of the run.
// stack\[0\] represents the top of the stack.
// and only stack data relevant to the opcode execution is contained.
uint256[] stack;
// The memory input data before executing the step of the run.
// only input data relevant to the opcode execution is contained.
// e.g. for MLOAD, it will have memory\[offset:offset+32\] copied here.
// the offset value can be get by the stack data.
bytes memoryInput;
// The opcode that was accessed.
uint8 opcode;
// The call depth of the step.
uint64 depth;
// Whether the call end up with out of gas error.
bool isOutOfGas;
// The contract address where the opcode is running
address contractAddr;
}
/// Represents a transaction's broadcast details.
struct BroadcastTxSummary {
// The hash of the transaction that was broadcasted
bytes32 txHash;
// Represent the type of transaction among CALL, CREATE, CREATE2
BroadcastTxType txType;
// The address of the contract that was called or created.
// This is address of the contract that is created if the txType is CREATE or CREATE2.
address contractAddress;
// The block number the transaction landed in.
uint64 blockNumber;
// Status of the transaction, retrieved from the transaction receipt.
bool success;
}
/// Holds a signed EIP-7702 authorization for an authority account to delegate to an implementation.
struct SignedDelegation {
// The y-parity of the recovered secp256k1 signature (0 or 1).
uint8 v;
// First 32 bytes of the signature.
bytes32 r;
// Second 32 bytes of the signature.
bytes32 s;
// The current nonce of the authority account at signing time.
// Used to ensure signature can't be replayed after account nonce changes.
uint64 nonce;
// Address of the contract implementation that will be delegated to.
// Gets encoded into delegation code: 0xef0100 || implementation.
address implementation;
}
/// Represents a "potential" revert reason from a single subsequent call when using `vm.assumeNoReverts`.
/// Reverts that match will result in a FOUNDRY::ASSUME rejection, whereas unmatched reverts will be surfaced
/// as normal.
struct PotentialRevert {
// The allowed origin of the revert opcode; address(0) allows reverts from any address
address reverter;
// When true, only matches on the beginning of the revert data, otherwise, matches on entire revert data
bool partialMatch;
// The data to use to match encountered reverts
bytes revertData;
}
/// An EIP-2930 access list item.
struct AccessListItem {
// The address to be added in access list.
address target;
// The storage keys to be added in access list.
bytes32[] storageKeys;
}
// ======== Crypto ========
/// Derives a private key from the name, labels the account with that name, and returns the wallet.
function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);
/// Generates a wallet from the private key and returns the wallet.
function createWallet(uint256 privateKey) external returns (Wallet memory wallet);
/// Generates a wallet from the private key, labels the account with that name, and returns the wallet.
function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);
/// Derive a private key from a provided mnemonic string (or mnemonic file path)
/// at the derivation path `m/44'/60'/0'/0/{index}`.
function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
/// Derive a private key from a provided mnemonic string (or mnemonic file path)
/// at `{derivationPath}{index}`.
function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
external
pure
returns (uint256 privateKey);
/// Derive a private key from a provided mnemonic string (or mnemonic file path) in the specified language
/// at the derivation path `m/44'/60'/0'/0/{index}`.
function deriveKey(string calldata mnemonic, uint32 index, string calldata language)
external
pure
returns (uint256 privateKey);
/// Derive a private key from a provided mnemonic string (or mnemonic file path) in the specified language
/// at `{derivationPath}{index}`.
function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language)
external
pure
returns (uint256 privateKey);
/// Derives secp256r1 public key from the provided `privateKey`.
function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY);
/// Adds a private key to the local forge wallet and returns the address.
function rememberKey(uint256 privateKey) external returns (address keyAddr);
/// Derive a set number of wallets from a mnemonic at the derivation path `m/44'/60'/0'/0/{0..count}`.
/// The respective private keys are saved to the local forge wallet for later use and their addresses are returned.
function rememberKeys(string calldata mnemonic, string calldata derivationPath, uint32 count)
external
returns (address[] memory keyAddrs);
/// Derive a set number of wallets from a mnemonic in the specified language at the derivation path `m/44'/60'/0'/0/{0..count}`.
/// The respective private keys are saved to the local forge wallet for later use and their addresses are returned.
function rememberKeys(
string calldata mnemonic,
string calldata derivationPath,
string calldata language,
uint32 count
) external returns (address[] memory keyAddrs);
/// Signs data with a `Wallet`.
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
/// signature's `s` value, and the recovery id `v` in a single bytes32.
/// This format reduces the signature size from 65 to 64 bytes.
function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs);
/// Signs `digest` with `privateKey` using the secp256k1 curve.
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
/// signature's `s` value, and the recovery id `v` in a single bytes32.
/// This format reduces the signature size from 65 to 64 bytes.
function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
/// Signs `digest` with signer provided to script using the secp256k1 curve.
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
/// signature's `s` value, and the recovery id `v` in a single bytes32.
/// This format reduces the signature size from 65 to 64 bytes.
/// If `--sender` is provided, the signer with provided address is used, otherwise,
/// if exactly one signer is provided to the script, that signer is used.
/// Raises error if signer passed through `--sender` does not match any unlocked signers or
/// if `--sender` is not provided and not exactly one signer is passed to the script.
function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
/// Signs `digest` with signer provided to script using the secp256k1 curve.
/// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
/// signature's `s` value, and the recovery id `v` in a single bytes32.
/// This format reduces the signature size from 65 to 64 bytes.
/// Raises error if none of the signers passed into the script have provided address.
function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
/// Signs `digest` with `privateKey` using the secp256r1 curve.
function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s);
/// Signs data with a `Wallet`.
function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
/// Signs `digest` with `privateKey` using the secp256k1 curve.
function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
/// Signs `digest` with signer provided to script using the secp256k1 curve.
/// If `--sender` is provided, the signer with provided address is used, otherwise,
/// if exactly one signer is provided to the script, that signer is used.
/// Raises error if signer passed through `--sender` does not match any unlocked signers or
/// if `--sender` is not provided and not exactly one signer is passed to the script.
function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
/// Signs `digest` with signer provided to script using the secp256k1 curve.
/// Raises error if none of the signers passed into the script have provided address.
function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
// ======== Environment ========
/// Gets the environment variable `name` and parses it as `address`.
/// Reverts if the variable was not found or could not be parsed.
function envAddress(string calldata name) external view returns (address value);
/// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
/// Gets the environment variable `name` and parses it as `bool`.
/// Reverts if the variable was not found or could not be parsed.
function envBool(string calldata name) external view returns (bool value);
/// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
/// Gets the environment variable `name` and parses it as `bytes32`.
/// Reverts if the variable was not found or could not be parsed.
function envBytes32(string calldata name) external view returns (bytes32 value);
/// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
/// Gets the environment variable `name` and parses it as `bytes`.
/// Reverts if the variable was not found or could not be parsed.
function envBytes(string calldata name) external view returns (bytes memory value);
/// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
/// Gets the environment variable `name` and returns true if it exists, else returns false.
function envExists(string calldata name) external view returns (bool result);
/// Gets the environment variable `name` and parses it as `int256`.
/// Reverts if the variable was not found or could not be parsed.
function envInt(string calldata name) external view returns (int256 value);
/// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
/// Gets the environment variable `name` and parses it as `bool`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, bool defaultValue) external view returns (bool value);
/// Gets the environment variable `name` and parses it as `uint256`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value);
/// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
external
view
returns (address[] memory value);
/// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
external
view
returns (bytes32[] memory value);
/// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
external
view
returns (string[] memory value);
/// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
external
view
returns (bytes[] memory value);
/// Gets the environment variable `name` and parses it as `int256`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, int256 defaultValue) external view returns (int256 value);
/// Gets the environment variable `name` and parses it as `address`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, address defaultValue) external view returns (address value);
/// Gets the environment variable `name` and parses it as `bytes32`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value);
/// Gets the environment variable `name` and parses it as `string`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value);
/// Gets the environment variable `name` and parses it as `bytes`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value);
/// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
external
view
returns (bool[] memory value);
/// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
external
view
returns (uint256[] memory value);
/// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
/// Reverts if the variable could not be parsed.
/// Returns `defaultValue` if the variable was not found.
function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
external
view
returns (int256[] memory value);
/// Gets the environment variable `name` and parses it as `string`.
/// Reverts if the variable was not found or could not be parsed.
function envString(string calldata name) external view returns (string memory value);
/// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
/// Gets the environment variable `name` and parses it as `uint256`.
/// Reverts if the variable was not found or could not be parsed.
function envUint(string calldata name) external view returns (uint256 value);
/// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
/// Reverts if the variable was not found or could not be parsed.
function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
/// Returns true if `forge` command was executed in given context.
function isContext(ForgeContext context) external view returns (bool result);
/// Resolves the env variable placeholders of a given input string.
function resolveEnv(string calldata input) external returns (string memory);
/// Sets environment variables.
function setEnv(string calldata name, string calldata value) external;
// ======== EVM ========
/// Gets all accessed reads and write slot from a `vm.record` session, for a given address.
function accesses(address target) external view returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
/// Gets the address for a given private key.
function addr(uint256 privateKey) external pure returns (address keyAddr);
/// Gets all the logs according to specified filter.
function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
external
view
returns (EthGetLogs[] memory logs);
/// Gets the current `block.blobbasefee`.
/// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,
/// and as a result will get optimized out by the compiler.
/// See https://github.com/foundry-rs/foundry/issues/6180
function getBlobBaseFee() external view returns (uint256 blobBaseFee);
/// Gets the current `block.number`.
/// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,
/// and as a result will get optimized out by the compiler.
/// See https://github.com/foundry-rs/foundry/issues/6180
function getBlockNumber() external view returns (uint256 height);
/// Gets the current `block.timestamp`.
/// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,
/// and as a result will get optimized out by the compiler.
/// See https://github.com/foundry-rs/foundry/issues/6180
function getBlockTimestamp() external view returns (uint256 timestamp);
/// Gets the current `block.chainid` of the currently selected environment.
/// You should use this instead of `block.chainid` if you use `vm.selectFork` or `vm.createSelectFork`, as `block.chainid` could be assumed
/// to be constant across a transaction, and as a result will get optimized out by the compiler.
/// See https://github.com/foundry-rs/foundry/issues/6180
function getChainId() external view returns (uint256 blockChainId);
/// Gets the map key and parent of a mapping at a given slot, for a given address.
function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
external
view
returns (bool found, bytes32 key, bytes32 parent);
/// Gets the number of elements in the mapping at the given slot, for a given address.
function getMappingLength(address target, bytes32 mappingSlot) external view returns (uint256 length);
/// Gets the elements at index idx of the mapping at the given slot, for a given address. The
/// index must be less than the length of the mapping (i.e. the number of keys in the mapping).
function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external view returns (bytes32 value);
/// Gets the nonce of an account.
function getNonce(address account) external view returns (uint64 nonce);
/// Get the nonce of a `Wallet`.
function getNonce(Wallet calldata wallet) external view returns (uint64 nonce);
/// Gets the RLP encoded block header for a given block number.
/// Returns the block header in the same format as `cast block <block_number> --raw`.
function getRawBlockHeader(uint256 blockNumber) external view returns (bytes memory rlpHeader);
/// Gets all the recorded logs.
function getRecordedLogs() external view returns (Log[] memory logs);
/// Returns state diffs from current `vm.startStateDiffRecording` session.
function getStateDiff() external view returns (string memory diff);
/// Returns state diffs from current `vm.startStateDiffRecording` session, in json format.
function getStateDiffJson() external view returns (string memory diff);
/// Returns an array of `StorageAccess` from current `vm.stateStateDiffRecording` session
function getStorageAccesses() external view returns (StorageAccess[] memory storageAccesses);
/// Gets the gas used in the last call from the callee perspective.
function lastCallGas() external view returns (Gas memory gas);
/// Loads a storage slot from an address.
function load(address target, bytes32 slot) external view returns (bytes32 data);
/// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
function pauseGasMetering() external;
/// Records all storage reads and writes. Use `accesses` to get the recorded data.
/// Subsequent calls to `record` will clear the previous data.
function record() external;
/// Record all the transaction logs.
function recordLogs() external;
/// Reset gas metering (i.e. gas usage is set to gas limit).
function resetGasMetering() external;
/// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
function resumeGasMetering() external;
/// Performs an Ethereum JSON-RPC request to the current fork URL.
function rpc(string calldata method, string calldata params) external returns (bytes memory data);
/// Performs an Ethereum JSON-RPC request to the given endpoint.
function rpc(string calldata urlOrAlias, string calldata method, string calldata params)
external
returns (bytes memory data);
/// Records the debug trace during the run.
function startDebugTraceRecording() external;
/// Starts recording all map SSTOREs for later retrieval.
function startMappingRecording() external;
/// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
/// along with the context of the calls
function startStateDiffRecording() external;
/// Stop debug trace recording and returns the recorded debug trace.
function stopAndReturnDebugTraceRecording() external returns (DebugStep[] memory step);
/// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);
/// Stops recording all map SSTOREs for later retrieval and clears the recorded data.
function stopMappingRecording() external;
/// Stops recording storage reads and writes.
function stopRecord() external;
// ======== Filesystem ========
/// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
/// `path` is relative to the project root.
function closeFile(string calldata path) external;
/// Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
/// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
/// Both `from` and `to` are relative to the project root.
function copyFile(string calldata from, string calldata to) external returns (uint64 copied);
/// Creates a new, empty directory at the provided path.
/// This cheatcode will revert in the following situations, but is not limited to just these cases:
/// - User lacks permissions to modify `path`.
/// - A parent of the given path doesn't exist and `recursive` is false.
/// - `path` already exists and `recursive` is false.
/// `path` is relative to the project root.
function createDir(string calldata path, bool recursive) external;
/// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
function deployCode(string calldata artifactPath) external returns (address deployedAddress);
/// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
/// Additionally accepts abi-encoded constructor arguments.
function deployCode(string calldata artifactPath, bytes calldata constructorArgs)
external
returns (address deployedAddress);
/// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
/// Additionally accepts `msg.value`.
function deployCode(string calldata artifactPath, uint256 value) external returns (address deployedAddress);
/// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
/// Additionally accepts abi-encoded constructor arguments and `msg.value`.
function deployCode(string calldata artifactPath, bytes calldata constructorArgs, uint256 value)
external
returns (address deployedAddress);
/// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
function deployCode(string calldata artifactPath, bytes32 salt) external returns (address deployedAddress);
/// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
/// Additionally accepts abi-encoded constructor arguments.
function deployCode(string calldata artifactPath, bytes calldata constructorArgs, bytes32 salt)
external
returns (address deployedAddress);
/// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
/// Additionally accepts `msg.value`.
function deployCode(string calldata artifactPath, uint256 value, bytes32 salt)
external
returns (address deployedAddress);
/// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
/// Additionally accepts abi-encoded constructor arguments and `msg.value`.
function deployCode(string calldata artifactPath, bytes calldata constructorArgs, uint256 value, bytes32 salt)
external
returns (address deployedAddress);
/// Returns true if the given path points to an existing entity, else returns false.
function exists(string calldata path) external view returns (bool result);
/// Performs a foreign function call via the terminal.
function ffi(string[] calldata commandInput) external returns (bytes memory result);
/// Given a path, query the file system to get information about a file, directory, etc.
function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);
/// Gets the artifact path from code (aka. creation code).
function getArtifactPathByCode(bytes calldata code) external view returns (string memory path);
/// Gets the artifact path from deployed code (aka. runtime code).
function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path);
/// Returns the most recent broadcast for the given contract on `chainId` matching `txType`.
/// For example:
/// The most recent deployment can be fetched by passing `txType` as `CREATE` or `CREATE2`.
/// The most recent call can be fetched by passing `txType` as `CALL`.
function getBroadcast(string calldata contractName, uint64 chainId, BroadcastTxType txType)
external
view
returns (BroadcastTxSummary memory);
/// Returns all broadcasts for the given contract on `chainId` with the specified `txType`.
/// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.
function getBroadcasts(string calldata contractName, uint64 chainId, BroadcastTxType txType)
external
view
returns (BroadcastTxSummary[] memory);
/// Returns all broadcasts for the given contract on `chainId`.
/// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.
function getBroadcasts(string calldata contractName, uint64 chainId)
external
view
returns (BroadcastTxSummary[] memory);
/// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
/// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the
/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
/// Returns the most recent deployment for the current `chainId`.
function getDeployment(string calldata contractName) external view returns (address deployedAddress);
/// Returns the most recent deployment for the given contract on `chainId`
function getDeployment(string calldata contractName, uint64 chainId)
external
view
returns (address deployedAddress);
/// Returns all deployments for the given contract on `chainId`
/// Sorted in descending order of deployment time i.e descending order of BroadcastTxSummary.blockNumber.
/// The most recent deployment is the first element, and the oldest is the last.
function getDeployments(string calldata contractName, uint64 chainId)
external
view
returns (address[] memory deployedAddresses);
/// Returns true if the path exists on disk and is pointing at a directory, else returns false.
function isDir(string calldata path) external view returns (bool result);
/// Returns true if the path exists on disk and is pointing at a regular file, else returns false.
function isFile(string calldata path) external view returns (bool result);
/// Get the path of the current project root.
function projectRoot() external view returns (string memory path);
/// Prompts the user for a string value in the terminal.
function prompt(string calldata promptText) external returns (string memory input);
/// Prompts the user for an address in the terminal.
function promptAddress(string calldata promptText) external returns (address);
/// Prompts the user for a hidden string value in the terminal.
function promptSecret(string calldata promptText) external returns (string memory input);
/// Prompts the user for hidden uint256 in the terminal (usually pk).
function promptSecretUint(string calldata promptText) external returns (uint256);
/// Prompts the user for uint256 in the terminal.
function promptUint(string calldata promptText) external returns (uint256);
/// Reads the directory at the given path recursively, up to `maxDepth`.
/// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned.
/// Follows symbolic links if `followLinks` is true.
function readDir(string calldata path) external view returns (DirEntry[] memory entries);
/// See `readDir(string)`.
function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
/// See `readDir(string)`.
function readDir(string calldata path, uint64 maxDepth, bool followLinks)
external
view
returns (DirEntry[] memory entries);
/// Reads the entire content of file to string. `path` is relative to the project root.
function readFile(string calldata path) external view returns (string memory data);
/// Reads the entire content of file as binary. `path` is relative to the project root.
function readFileBinary(string calldata path) external view returns (bytes memory data);
/// Reads next line of file to string.
function readLine(string calldata path) external view returns (string memory line);
/// Reads a symbolic link, returning the path that the link points to.
/// This cheatcode will revert in the following situations, but is not limited to just these cases:
/// - `path` is not a symbolic link.
/// - `path` does not exist.
function readLink(string calldata linkPath) external view returns (string memory targetPath);
/// Removes a directory at the provided path.
/// This cheatcode will revert in the following situations, but is not limited to just these cases:
/// - `path` doesn't exist.
/// - `path` isn't a directory.
/// - User lacks permissions to modify `path`.
/// - The directory is not empty and `recursive` is false.
/// `path` is relative to the project root.
function removeDir(string calldata path, bool recursive) external;
/// Removes a file from the filesystem.
/// This cheatcode will revert in the following situations, but is not limited to just these cases:
/// - `path` points to a directory.
/// - The file doesn't exist.
/// - The user lacks permissions to remove the file.
/// `path` is relative to the project root.
function removeFile(string calldata path) external;
/// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr.
function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);
/// Returns the time since unix epoch in milliseconds.
function unixTime() external view returns (uint256 milliseconds);
/// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
/// `path` is relative to the project root.
function writeFile(string calldata path, string calldata data) external;
/// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
/// `path` is relative to the project root.
function writeFileBinary(string calldata path, bytes calldata data) external;
/// Writes line to file, creating a file if it does not exist.
/// `path` is relative to the project root.
function writeLine(string calldata path, string calldata data) external;
// ======== JSON ========
/// Checks if `key` exists in a JSON object.
function keyExistsJson(string calldata json, string calldata key) external view returns (bool);
/// Parses a string of JSON data at `key` and coerces it to `address`.
function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
/// Parses a string of JSON data at `key` and coerces it to `address[]`.
function parseJsonAddressArray(string calldata json, string calldata key)
external
pure
returns (address[] memory);
/// Parses a string of JSON data at `key` and coerces it to `bool`.
function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
/// Parses a string of JSON data at `key` and coerces it to `bool[]`.
function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
/// Parses a string of JSON data at `key` and coerces it to `bytes`.
function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
/// Parses a string of JSON data at `key` and coerces it to `bytes32`.
function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
/// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.
function parseJsonBytes32Array(string calldata json, string calldata key)
external
pure
returns (bytes32[] memory);
/// Parses a string of JSON data at `key` and coerces it to `bytes[]`.
function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
/// Parses a string of JSON data at `key` and coerces it to `int256`.
function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
/// Parses a string of JSON data at `key` and coerces it to `int256[]`.
function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
/// Returns an array of all the keys in a JSON object.
function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);
/// Parses a string of JSON data at `key` and coerces it to `string`.
function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
/// Parses a string of JSON data at `key` and coerces it to `string[]`.
function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
/// Parses a string of JSON data at `key` and coerces it to type array corresponding to...
// [truncated — 130769 bytes total]
console.sol 1560 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS =
0x000000000000000000636F6e736F6c652e6c6f67;
function _sendLogPayloadImplementation(bytes memory payload) internal view {
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
pop(
staticcall(
gas(),
consoleAddress,
add(payload, 32),
mload(payload),
0,
0
)
)
}
}
function _castToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castToPure(_sendLogPayloadImplementation)(payload);
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, int256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string...
// [truncated — 69270 bytes total]
console2.sol 4 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import {console as console2} from "./console.sol";
IMulticall3.sol 73 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
pragma experimental ABIEncoderV2;
interface IMulticall3 {
struct Call {
address target;
bytes callData;
}
struct Call3 {
address target;
bool allowFailure;
bytes callData;
}
struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
function aggregate(Call[] calldata calls)
external
payable
returns (uint256 blockNumber, bytes[] memory returnData);
function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
function blockAndAggregate(Call[] calldata calls)
external
payable
returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
function getBasefee() external view returns (uint256 basefee);
function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);
function getBlockNumber() external view returns (uint256 blockNumber);
function getChainId() external view returns (uint256 chainid);
function getCurrentBlockCoinbase() external view returns (address coinbase);
function getCurrentBlockDifficulty() external view returns (uint256 difficulty);
function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);
function getCurrentBlockTimestamp() external view returns (uint256 timestamp);
function getEthBalance(address addr) external view returns (uint256 balance);
function getLastBlockHash() external view returns (bytes32 blockHash);
function tryAggregate(bool requireSuccess, Call[] calldata calls)
external
payable
returns (Result[] memory returnData);
function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
external
payable
returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
}
safeconsole.sol 13937 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;
/// @author philogy <https://github.com/philogy>
/// @dev Code generated automatically by script.
library safeconsole {
uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67;
// Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374)
// for the view-to-pure log trick.
function _sendLogPayload(uint256 offset, uint256 size) private pure {
function(uint256, uint256) internal view fnIn = _sendLogPayloadView;
function(uint256, uint256) internal pure pureSendLogPayload;
/// @solidity memory-safe-assembly
assembly {
pureSendLogPayload := fnIn
}
pureSendLogPayload(offset, size);
}
function _sendLogPayloadView(uint256 offset, uint256 size) private view {
/// @solidity memory-safe-assembly
assembly {
pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0))
}
}
function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
function(uint256, uint256, uint256) internal view fnIn = _memcopyView;
function(uint256, uint256, uint256) internal pure pureMemcopy;
/// @solidity memory-safe-assembly
assembly {
pureMemcopy := fnIn
}
pureMemcopy(fromOffset, toOffset, length);
}
function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
/// @solidity memory-safe-assembly
assembly {
pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length))
}
}
function logMemory(uint256 offset, uint256 length) internal pure {
if (offset >= 0x60) {
// Sufficient memory before slice to prepare call header.
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(sub(offset, 0x60))
m1 := mload(sub(offset, 0x40))
m2 := mload(sub(offset, 0x20))
// Selector of `log(bytes)`.
mstore(sub(offset, 0x60), 0x0be77f56)
mstore(sub(offset, 0x40), 0x20)
mstore(sub(offset, 0x20), length)
}
_sendLogPayload(offset - 0x44, length + 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(sub(offset, 0x60), m0)
mstore(sub(offset, 0x40), m1)
mstore(sub(offset, 0x20), m2)
}
} else {
// Insufficient space, so copy slice forward, add header and reverse.
bytes32 m0;
bytes32 m1;
bytes32 m2;
uint256 endOffset = offset + length;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(add(endOffset, 0x00))
m1 := mload(add(endOffset, 0x20))
m2 := mload(add(endOffset, 0x40))
}
_memcopy(offset, offset + 0x60, length);
/// @solidity memory-safe-assembly
assembly {
// Selector of `log(bytes)`.
mstore(add(offset, 0x00), 0x0be77f56)
mstore(add(offset, 0x20), 0x20)
mstore(add(offset, 0x40), length)
}
_sendLogPayload(offset + 0x1c, length + 0x44);
_memcopy(offset + 0x60, offset, length);
/// @solidity memory-safe-assembly
assembly {
mstore(add(endOffset, 0x00), m0)
mstore(add(endOffset, 0x20), m1)
mstore(add(endOffset, 0x40), m2)
}
}
}
function log(address p0) internal pure {
bytes32 m0;
bytes32 m1;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
// Selector of `log(address)`.
mstore(0x00, 0x2c2ecbc2)
mstore(0x20, p0)
}
_sendLogPayload(0x1c, 0x24);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
}
}
function log(bool p0) internal pure {
bytes32 m0;
bytes32 m1;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
// Selector of `log(bool)`.
mstore(0x00, 0x32458eed)
mstore(0x20, p0)
}
_sendLogPayload(0x1c, 0x24);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
}
}
function log(uint256 p0) internal pure {
bytes32 m0;
bytes32 m1;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
// Selector of `log(uint256)`.
mstore(0x00, 0xf82c50f1)
mstore(0x20, p0)
}
_sendLogPayload(0x1c, 0x24);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
}
}
function log(bytes32 p0) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(string)`.
mstore(0x00, 0x41304fac)
mstore(0x20, 0x20)
writeString(0x40, p0)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(address,address)`.
mstore(0x00, 0xdaf0d4aa)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(address p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(address,bool)`.
mstore(0x00, 0x75b605d3)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(address p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(address,uint256)`.
mstore(0x00, 0x8309e8a8)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(address p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(address,string)`.
mstore(0x00, 0x759f86bb)
mstore(0x20, p0)
mstore(0x40, 0x40)
writeString(0x60, p1)
}
_sendLogPayload(0x1c, 0x84);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bool p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(bool,address)`.
mstore(0x00, 0x853c4849)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(bool p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(bool,bool)`.
mstore(0x00, 0x2a110e83)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(bool p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(bool,uint256)`.
mstore(0x00, 0x399174d3)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(bool p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(bool,string)`.
mstore(0x00, 0x8feac525)
mstore(0x20, p0)
mstore(0x40, 0x40)
writeString(0x60, p1)
}
_sendLogPayload(0x1c, 0x84);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(uint256 p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(uint256,address)`.
mstore(0x00, 0x69276c86)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(uint256 p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(uint256,bool)`.
mstore(0x00, 0x1c9d7eb3)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(uint256 p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
// Selector of `log(uint256,uint256)`.
mstore(0x00, 0xf666715a)
mstore(0x20, p0)
mstore(0x40, p1)
}
_sendLogPayload(0x1c, 0x44);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
}
}
function log(uint256 p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(uint256,string)`.
mstore(0x00, 0x643fd0df)
mstore(0x20, p0)
mstore(0x40, 0x40)
writeString(0x60, p1)
}
_sendLogPayload(0x1c, 0x84);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, address p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(string,address)`.
mstore(0x00, 0x319af333)
mstore(0x20, 0x40)
mstore(0x40, p1)
writeString(0x60, p0)
}
_sendLogPayload(0x1c, 0x84);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, bool p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(string,bool)`.
mstore(0x00, 0xc3b55635)
mstore(0x20, 0x40)
mstore(0x40, p1)
writeString(0x60, p0)
}
_sendLogPayload(0x1c, 0x84);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, uint256 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
// Selector of `log(string,uint256)`.
mstore(0x00, 0xb60e72cc)
mstore(0x20, 0x40)
mstore(0x40, p1)
writeString(0x60, p0)
}
_sendLogPayload(0x1c, 0x84);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
}
}
function log(bytes32 p0, bytes32 p1) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
bytes32 m6;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
m6 := mload(0xc0)
// Selector of `log(string,string)`.
mstore(0x00, 0x4b5c4277)
mstore(0x20, 0x40)
mstore(0x40, 0x80)
writeString(0x60, p0)
writeString(0xa0, p1)
}
_sendLogPayload(0x1c, 0xc4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
mstore(0xc0, m6)
}
}
function log(address p0, address p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,address,address)`.
mstore(0x00, 0x018c84c2)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,address,bool)`.
mstore(0x00, 0xf2a66286)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,address,uint256)`.
mstore(0x00, 0x17fe6185)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, address p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,address,string)`.
mstore(0x00, 0x007150be)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bool p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,bool,address)`.
mstore(0x00, 0xf11699ed)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, bool p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,bool,bool)`.
mstore(0x00, 0xeb830c92)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, bool p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,bool,uint256)`.
mstore(0x00, 0x9c4f99fb)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, bool p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,bool,string)`.
mstore(0x00, 0x212255cc)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, uint256 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,uint256,address)`.
mstore(0x00, 0x7bc0d848)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, uint256 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,uint256,bool)`.
mstore(0x00, 0x678209a8)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(address,uint256,uint256)`.
mstore(0x00, 0xb69bcaf6)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(address p0, uint256 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,uint256,string)`.
mstore(0x00, 0xa1f2e8aa)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,string,address)`.
mstore(0x00, 0xf08744e8)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,string,bool)`.
mstore(0x00, 0xcf020fb1)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(address,string,uint256)`.
mstore(0x00, 0x67dd6ff1)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(address p0, bytes32 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
bytes32 m6;
bytes32 m7;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
m6 := mload(0xc0)
m7 := mload(0xe0)
// Selector of `log(address,string,string)`.
mstore(0x00, 0xfb772265)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, 0xa0)
writeString(0x80, p1)
writeString(0xc0, p2)
}
_sendLogPayload(0x1c, 0xe4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
mstore(0xc0, m6)
mstore(0xe0, m7)
}
}
function log(bool p0, address p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,address,address)`.
mstore(0x00, 0xd2763667)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, address p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,address,bool)`.
mstore(0x00, 0x18c9c746)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, address p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,address,uint256)`.
mstore(0x00, 0x5f7b9afb)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, address p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,address,string)`.
mstore(0x00, 0xde9a9270)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bool p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,bool,address)`.
mstore(0x00, 0x1078f68d)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, bool p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,bool,bool)`.
mstore(0x00, 0x50709698)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, bool p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,bool,uint256)`.
mstore(0x00, 0x12f21602)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, bool p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,bool,string)`.
mstore(0x00, 0x2555fa46)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, uint256 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,uint256,address)`.
mstore(0x00, 0x088ef9d2)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, uint256 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,uint256,bool)`.
mstore(0x00, 0xe8defba9)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
/// @solidity memory-safe-assembly
assembly {
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
// Selector of `log(bool,uint256,uint256)`.
mstore(0x00, 0x37103367)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, p2)
}
_sendLogPayload(0x1c, 0x64);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
}
}
function log(bool p0, uint256 p1, bytes32 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,uint256,string)`.
mstore(0x00, 0xc3fc3970)
mstore(0x20, p0)
mstore(0x40, p1)
mstore(0x60, 0x60)
writeString(0x80, p2)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, address p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,string,address)`.
mstore(0x00, 0x9591b953)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, bool p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
mstore(pos, length)
let shift := sub(256, shl(3, length))
mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
}
m0 := mload(0x00)
m1 := mload(0x20)
m2 := mload(0x40)
m3 := mload(0x60)
m4 := mload(0x80)
m5 := mload(0xa0)
// Selector of `log(bool,string,bool)`.
mstore(0x00, 0xdbb4c247)
mstore(0x20, p0)
mstore(0x40, 0x60)
mstore(0x60, p2)
writeString(0x80, p1)
}
_sendLogPayload(0x1c, 0xa4);
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, m0)
mstore(0x20, m1)
mstore(0x40, m2)
mstore(0x60, m3)
mstore(0x80, m4)
mstore(0xa0, m5)
}
}
function log(bool p0, bytes32 p1, uint256 p2) internal pure {
bytes32 m0;
bytes32 m1;
bytes32 m2;
bytes32 m3;
bytes32 m4;
bytes32 m5;
/// @solidity memory-safe-assembly
assembly {
function writeString(pos, w) {
let length := 0
...
// [truncated — 427535 bytes total]
Ownable.sol 100 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
IERC1363.sol 86 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}
IERC165.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";
IERC20.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
IERC20Metadata.sol 26 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity >=0.6.2;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
SafeERC20.sol 280 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_safeTransfer(token, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
if (!_safeTransferFrom(token, from, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _safeTransfer(token, to, value, false);
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _safeTransferFrom(token, from, to, value, false);
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
if (!_safeApprove(token, spender, value, false)) {
if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the
* return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.transfer.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(to, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0, 0x44, 0, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
/**
* @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return
* value: the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param from The sender of the tokens
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value,
bool bubble
) private returns (bool success) {
bytes4 selector = IERC20.transferFrom.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(from, shr(96, not(0))))
mstore(0x24, and(to, shr(96, not(0))))
mstore(0x44, value)
success := call(gas(), token, 0, 0, 0x64, 0, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
mstore(0x60, 0)
}
}
/**
* @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:
* the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param spender The spender of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.approve.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(spender, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0, 0x44, 0, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
ILVOFTAdapter.sol 19 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
import {OFTAdapter} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTAdapter.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
/// @title ILVOFTAdapter
/// @notice Adapter contract for bridging existing ILV tokens on Ethereum via LayerZero V2.
/// @dev This contract locks ILV tokens on Ethereum and sends cross-chain messages to mint on destination chains.
contract ILVOFTAdapter is OFTAdapter {
/// @notice Constructor initializes the OFT adapter
/// @param _token The ILV token address on Ethereum
/// @param _lzEndpoint LayerZero endpoint address
/// @param _owner Owner of the contract
constructor(address _token, address _lzEndpoint, address _owner)
OFTAdapter(_token, _lzEndpoint, _owner)
Ownable(_owner)
{}
}
Read Contract
SEND 0x1f5e1334 → uint16
SEND_AND_CALL 0x134d4f25 → uint16
allowInitializePath 0xbfe94e81 → bool
approvalRequired 0x9f68b964 → bool
combineOptions 0xbc70b354 → bytes
decimalConversionRate 0x963efcaa → uint256
endpoint 0x5e280f11 → address
enforcedOptions 0x5535d461 → bytes
isComposeMsgSender 0x8833c245 → bool
isPeer 0x5a0dfe4d → bool
msgInspector 0x111ecdad → address
nextNonce 0x7d25a05e → uint64
oApp 0x52ae2879 → address
oAppVersion 0x17442b70 → uint64, uint64
oftVersion 0x156a0d0f → bytes4, uint64
owner 0x8da5cb5b → address
peers 0xbb0b6a53 → bytes32
preCrime 0xb731ea0a → address
quoteOFT 0xe6343d44 → tuple, tuple[], tuple
quoteSend 0x2f603a24 → tuple
sharedDecimals 0x857749b0 → uint8
token 0xfc0c546a → address
Write Contract 11 functions
These functions modify contract state and require a wallet transaction to execute.
lzReceive 0xbf282d99
tuple _origin
bytes32 _guid
bytes _message
address _executor
bytes _extraData
lzReceiveAndRevert 0x215f7f2f
tuple[] _packets
lzReceiveSimulate 0xa454778b
tuple _origin
bytes32 _guid
bytes _message
address _executor
bytes _extraData
renounceOwnership 0x715018a6
No parameters
send 0xccfc9451
tuple _sendParam
tuple _fee
address _refundAddress
returns: tuple, tuple
setDelegate 0xca5eb5e1
address _delegate
setEnforcedOptions 0xd833f371
tuple[] _enforcedOptions
setMsgInspector 0x6fc1b31e
address _msgInspector
setPeer 0x3400288b
uint32 _eid
bytes32 _peer
setPreCrime 0xd4243885
address _preCrime
transferOwnership 0xf2fde38b
address newOwner
Recent Transactions
No transactions found for this address