Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xA80F36BA18c7f721F3F7ACDbcDEfd3a86869A036
Balance 0 ETH
Nonce 1
Code Size 11044 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

11044 bytes
0x6080604052600436106101ee5760003560e01c806382413eac1161010d578063bc70b354116100a0578063d045a0dc1161006f578063d045a0dc14610607578063d42438851461061a578063f2fde38b1461063a578063fc0c546a1461065a578063ff7bd03d1461068d57600080fd5b8063bc70b35414610593578063bd815db0146105b3578063c7c7f5b3146105c6578063ca5eb5e1146105e757600080fd5b80639f68b964116100dc5780639f68b96414610512578063b731ea0a14610526578063b98bd07014610546578063bb0b6a531461056657600080fd5b806382413eac14610476578063857749b0146104965780638da5cb5b146104b2578063963efcaa146104d057600080fd5b80633b6f743b116101855780635e280f11116101545780635e280f11146103d25780636fc1b31e14610406578063715018a6146104265780637d25a05e1461043b57600080fd5b80633b6f743b1461031e57806352ae28791461034b5780635535d4611461035e5780635a0dfe4d1461038b57600080fd5b8063156a0d0f116101c1578063156a0d0f146102a057806317442b70146102c75780631f5e1334146102e95780633400288b146102fe57600080fd5b80630d35b415146101f3578063111ecdad1461022b57806313137d6514610263578063134d4f2514610278575b600080fd5b3480156101ff57600080fd5b5061021361020e366004611c7f565b6106ad565b60405161022293929190611d03565b60405180910390f35b34801561023757600080fd5b5060045461024b906001600160a01b031681565b6040516001600160a01b039091168152602001610222565b610276610271366004611e0b565b61077e565b005b34801561028457600080fd5b5061028d600281565b60405161ffff9091168152602001610222565b3480156102ac57600080fd5b506040805162b9270b60e21b81526001602082015201610222565b3480156102d357600080fd5b5060408051600181526002602082015201610222565b3480156102f557600080fd5b5061028d600181565b34801561030a57600080fd5b50610276610319366004611ec3565b61083e565b34801561032a57600080fd5b5061033e610339366004611efb565b610854565b6040516102229190611f4c565b34801561035757600080fd5b503061024b565b34801561036a57600080fd5b5061037e610379366004611f75565b6108bd565b6040516102229190611fa8565b34801561039757600080fd5b506103c26103a6366004611ec3565b63ffffffff919091166000908152600160205260409020541490565b6040519015158152602001610222565b3480156103de57600080fd5b5061024b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b34801561041257600080fd5b50610276610421366004611fbb565b610962565b34801561043257600080fd5b506102766109bf565b34801561044757600080fd5b5061045e610456366004611ec3565b600092915050565b6040516001600160401b039091168152602001610222565b34801561048257600080fd5b506103c2610491366004611fd8565b6109d3565b3480156104a257600080fd5b5060405160068152602001610222565b3480156104be57600080fd5b506000546001600160a01b031661024b565b3480156104dc57600080fd5b506105047f000000000000000000000000000000000000000000000000000000e8d4a5100081565b604051908152602001610222565b34801561051e57600080fd5b5060016103c2565b34801561053257600080fd5b5060025461024b906001600160a01b031681565b34801561055257600080fd5b50610276610561366004612082565b6109e8565b34801561057257600080fd5b506105046105813660046120c3565b60016020526000908152604090205481565b34801561059f57600080fd5b5061037e6105ae3660046120de565b610a02565b6102766105c1366004612082565b610baa565b6105d96105d436600461213e565b610d34565b6040516102229291906121ab565b3480156105f357600080fd5b50610276610602366004611fbb565b610e2f565b610276610615366004611e0b565b610eb5565b34801561062657600080fd5b50610276610635366004611fbb565b610ee4565b34801561064657600080fd5b50610276610655366004611fbb565b610f3a565b34801561066657600080fd5b507f000000000000000000000000d5eb7e91ae88ea2550f9bfd04208399c95df4dc761024b565b34801561069957600080fd5b506103c26106a83660046121fd565b610f78565b604080518082019091526000808252602082015260606106e0604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b0360208084018290528451838152908101909452919550918261073b565b6040805180820190915260008152606060208201528152602001906001900390816107135790505b509350600080610760604089013560608a013561075b60208c018c6120c3565b610fae565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031633146107ce576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b602087018035906107e8906107e3908a6120c3565b610ff2565b14610826576107fa60208801886120c3565b60405163309afaf360e21b815263ffffffff9091166004820152602088013560248201526044016107c5565b6108358787878787878761102e565b50505050505050565b610846611195565b61085082826111c2565b5050565b604080518082019091526000808252602082015260006108846040850135606086013561075b60208801886120c3565b9150506000806108948684611217565b90925090506108b16108a960208801886120c3565b83838861133a565b93505050505b92915050565b6003602090815260009283526040808420909152908252902080546108e19061222f565b80601f016020809104026020016040519081016040528092919081815260200182805461090d9061222f565b801561095a5780601f1061092f5761010080835404028352916020019161095a565b820191906000526020600020905b81548152906001019060200180831161093d57829003601f168201915b505050505081565b61096a611195565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b6109c7611195565b6109d1600061141b565b565b6001600160a01b03811630145b949350505050565b6109f0611195565b6108506109fd8284612304565b61146b565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610a369061222f565b80601f0160208091040260200160405190810160405280929190818152602001828054610a629061222f565b8015610aaf5780601f10610a8457610100808354040283529160200191610aaf565b820191906000526020600020905b815481529060010190602001808311610a9257829003601f168201915b505050505090508051600003610aff5783838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294506109e09350505050565b6000839003610b0f5790506109e0565b60028310610b8d57610b5684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061157292505050565b80610b648460028188612419565b604051602001610b7693929190612443565b6040516020818303038152906040529150506109e0565b8383604051639a6d49cd60e01b81526004016107c5929190612494565b60005b81811015610cb35736838383818110610bc857610bc86124a8565b9050602002810190610bda91906124be565b9050610c0d610bec60208301836120c3565b602083013563ffffffff919091166000908152600160205260409020541490565b610c175750610cab565b3063d045a0dc60c08301358360a0810135610c366101008301836124df565b610c47610100890160e08a01611fbb565b610c556101208a018a6124df565b6040518963ffffffff1660e01b8152600401610c77979695949392919061253a565b6000604051808303818588803b158015610c9057600080fd5b505af1158015610ca4573d6000803e3d6000fd5b5050505050505b600101610bad565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cf2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d1a91908101906125c0565b604051638351eea760e01b81526004016107c59190611fa8565b610d3c611c20565b6040805180820190915260008082526020820152600080610d7333604089013560608a0135610d6e60208c018c6120c3565b61159e565b91509150600080610d848984611217565b9092509050610db0610d9960208b018b6120c3565b8383610daa368d90038d018d61262d565b8b6115ef565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90610dfe908d018d6120c3565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b610e37611195565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063ca5eb5e190602401600060405180830381600087803b158015610e9a57600080fd5b505af1158015610eae573d6000803e3d6000fd5b5050505050565b333014610ed55760405163029a949d60e31b815260040160405180910390fd5b61083587878787878787610826565b610eec611195565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c2427760906020016109b4565b610f42611195565b6001600160a01b038116610f6c57604051631e4fbdf760e01b8152600060048201526024016107c5565b610f758161141b565b50565b6000602082018035906001908390610f9090866120c3565b63ffffffff1681526020810191909152604001600020541492915050565b600080610fba856116fa565b915081905083811015610fea576040516371c4efed60e01b815260048101829052602481018590526044016107c5565b935093915050565b63ffffffff8116600090815260016020526040812054806108b75760405163f6ff4fb760e01b815263ffffffff841660048201526024016107c5565b600061104061103d8787611731565b90565b9050600061106c8261105a6110558a8a611750565b611773565b61106760208d018d6120c3565b6117a8565b905060288611156111335760006110a961108c60608c0160408d0161265f565b61109960208d018d6120c3565b846110a48c8c6117e6565b611831565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c1690637cb59012906110ff9086908d90600090879060040161267c565b600060405180830381600087803b15801561111957600080fd5b505af115801561112d573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61116c60208d018d6120c3565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6000546001600160a01b031633146109d15760405163118cdaa760e01b81523360048201526024016107c5565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b6060806000611274856020013561122d86611863565b61123a60a08901896124df565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188f92505050565b909350905060008161128757600161128a565b60025b90506112aa61129c60208801886120c3565b826105ae60808a018a6124df565b6004549093506001600160a01b031680156113305760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906112ed90889088906004016126ad565b602060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132e91906126d2565b505b5050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161139d89610ff2565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b81526004016113d29291906126ef565b6040805180830381865afa1580156113ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114129190612798565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b81518110156115425761149d82828151811061148c5761148c6124a8565b602002602001015160400151611572565b8181815181106114af576114af6124a8565b602002602001015160400151600360008484815181106114d1576114d16124a8565b60200260200101516000015163ffffffff1663ffffffff168152602001908152602001600020600084848151811061150b5761150b6124a8565b60200260200101516020015161ffff1661ffff16815260200190815260200160002090816115399190612804565b5060010161146e565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b674816040516109b491906128c3565b600281015161ffff81166003146108505781604051639a6d49cd60e01b81526004016107c59190611fa8565b6000806115ac858585610fae565b90925090506115e66001600160a01b037f000000000000000000000000d5eb7e91ae88ea2550f9bfd04208399c95df4dc716873085611909565b94509492505050565b6115f7611c20565b60006116068460000151611976565b60208501519091501561162057611620846020015161199e565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016116708c610ff2565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016116ac9291906126ef565b60806040518083038185885af11580156116ca573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906116ef919061294e565b979650505050505050565b60007f000000000000000000000000000000000000000000000000000000e8d4a510006117278184612998565b6108b791906129ba565b60006117406020828486612419565b611749916129df565b9392505050565b6000611760602860208486612419565b611769916129fd565b60c01c9392505050565b60006108b77f000000000000000000000000000000000000000000000000000000e8d4a510006001600160401b0384166129ba565b60006117de6001600160a01b037f000000000000000000000000d5eb7e91ae88ea2550f9bfd04208399c95df4dc7168585611a80565b509092915050565b60606117f58260288186612419565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161184a9493929190612a2d565b6040516020818303038152906040529050949350505050565b60006108b77f000000000000000000000000000000000000000000000000000000e8d4a5100083612998565b80516060901515806118d85784846040516020016118c492919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526118ff565b848433856040516020016118ef9493929190612a7c565b6040516020818303038152906040525b9150935093915050565b6040516001600160a01b0384811660248301528381166044830152606482018390526119709186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611ab6565b50505050565b600081341461199a576040516304fb820960e51b81523460048201526024016107c5565b5090565b60007f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a229190612abf565b90506001600160a01b038116611a4b576040516329b99a9560e11b815260040160405180910390fd5b6108506001600160a01b038216337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c85611909565b6040516001600160a01b03838116602483015260448201839052611ab191859182169063a9059cbb9060640161193e565b505050565b6000611acb6001600160a01b03841683611b19565b90508051600014158015611af0575080806020019051810190611aee91906126d2565b155b15611ab157604051635274afe760e01b81526001600160a01b03841660048201526024016107c5565b60606117498383600084600080856001600160a01b03168486604051611b3f9190612adc565b60006040518083038185875af1925050503d8060008114611b7c576040519150601f19603f3d011682016040523d82523d6000602084013e611b81565b606091505b5091509150611b91868383611b9b565b9695505050505050565b606082611bb057611bab82611bf7565b611749565b8151158015611bc757506001600160a01b0384163b155b15611bf057604051639996b31560e01b81526001600160a01b03851660048201526024016107c5565b5080611749565b805115611c075780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60405180606001604052806000801916815260200160006001600160401b03168152602001611c62604051806040016040528060008152602001600081525090565b905290565b600060e08284031215611c7957600080fd5b50919050565b600060208284031215611c9157600080fd5b81356001600160401b03811115611ca757600080fd5b6109e084828501611c67565b60005b83811015611cce578181015183820152602001611cb6565b50506000910152565b60008151808452611cef816020860160208601611cb3565b601f01601f19169290920160200192915050565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b83811015611d7e5788870360bf19018552815180518852830151838801879052611d6b87890182611cd7565b9750509382019390820190600101611d3f565b505087516060880152505050602085015160808501525090506109e0565b600060608284031215611c7957600080fd5b60008083601f840112611dc057600080fd5b5081356001600160401b03811115611dd757600080fd5b602083019150836020828501011115611def57600080fd5b9250929050565b6001600160a01b0381168114610f7557600080fd5b600080600080600080600060e0888a031215611e2657600080fd5b611e308989611d9c565b96506060880135955060808801356001600160401b0380821115611e5357600080fd5b611e5f8b838c01611dae565b909750955060a08a01359150611e7482611df6565b90935060c08901359080821115611e8a57600080fd5b50611e978a828b01611dae565b989b979a50959850939692959293505050565b803563ffffffff81168114611ebe57600080fd5b919050565b60008060408385031215611ed657600080fd5b611edf83611eaa565b946020939093013593505050565b8015158114610f7557600080fd5b60008060408385031215611f0e57600080fd5b82356001600160401b03811115611f2457600080fd5b611f3085828601611c67565b9250506020830135611f4181611eed565b809150509250929050565b8151815260208083015190820152604081016108b7565b803561ffff81168114611ebe57600080fd5b60008060408385031215611f8857600080fd5b611f9183611eaa565b9150611f9f60208401611f63565b90509250929050565b6020815260006117496020830184611cd7565b600060208284031215611fcd57600080fd5b813561174981611df6565b60008060008060a08587031215611fee57600080fd5b611ff88686611d9c565b935060608501356001600160401b0381111561201357600080fd5b61201f87828801611dae565b909450925050608085013561203381611df6565b939692955090935050565b60008083601f84011261205057600080fd5b5081356001600160401b0381111561206757600080fd5b6020830191508360208260051b8501011115611def57600080fd5b6000806020838503121561209557600080fd5b82356001600160401b038111156120ab57600080fd5b6120b78582860161203e565b90969095509350505050565b6000602082840312156120d557600080fd5b61174982611eaa565b600080600080606085870312156120f457600080fd5b6120fd85611eaa565b935061210b60208601611f63565b925060408501356001600160401b0381111561212657600080fd5b61213287828801611dae565b95989497509550505050565b6000806000838503608081121561215457600080fd5b84356001600160401b0381111561216a57600080fd5b61217687828801611c67565b9450506040601f198201121561218b57600080fd5b5060208401915060608401356121a081611df6565b809150509250925092565b600060c082019050835182526001600160401b03602085015116602083015260408401516121e6604084018280518252602090810151910152565b5082516080830152602083015160a0830152611749565b60006060828403121561220f57600080fd5b6117498383611d9c565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061224357607f821691505b602082108103611c7957634e487b7160e01b600052602260045260246000fd5b604051606081016001600160401b038111828210171561228557612285612219565b60405290565b604080519081016001600160401b038111828210171561228557612285612219565b604051601f8201601f191681016001600160401b03811182821017156122d5576122d5612219565b604052919050565b60006001600160401b038211156122f6576122f6612219565b50601f01601f191660200190565b60006001600160401b038084111561231e5761231e612219565b8360051b602061232f8183016122ad565b86815291850191818101903684111561234757600080fd5b865b8481101561240d578035868111156123615760008081fd5b880160603682900312156123755760008081fd5b61237d612263565b61238682611eaa565b8152612393868301611f63565b86820152604080830135898111156123ab5760008081fd5b929092019136601f8401126123c05760008081fd5b82356123d36123ce826122dd565b6122ad565b81815236898387010111156123e85760008081fd5b818986018a830137600091810189019190915290820152845250918301918301612349565b50979650505050505050565b6000808585111561242957600080fd5b8386111561243657600080fd5b5050820193919092039150565b60008451612455818460208901611cb3565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260006109e060208301848661246b565b634e487b7160e01b600052603260045260246000fd5b6000823561013e198336030181126124d557600080fd5b9190910192915050565b6000808335601e198436030181126124f657600080fd5b8301803591506001600160401b0382111561251057600080fd5b602001915036819003821315611def57600080fd5b6001600160401b0381168114610f7557600080fd5b63ffffffff61254889611eaa565b168152602088013560208201526000604089013561256581612525565b6001600160401b03811660408401525087606083015260e0608083015261259060e08301878961246b565b6001600160a01b03861660a084015282810360c08401526125b281858761246b565b9a9950505050505050505050565b6000602082840312156125d257600080fd5b81516001600160401b038111156125e857600080fd5b8201601f810184136125f957600080fd5b80516126076123ce826122dd565b81815285602083850101111561261c57600080fd5b611412826020830160208601611cb3565b60006040828403121561263f57600080fd5b61264761228b565b82358152602083013560208201528091505092915050565b60006020828403121561267157600080fd5b813561174981612525565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000611b916080830184611cd7565b6040815260006126c06040830185611cd7565b82810360208401526114128185611cd7565b6000602082840312156126e457600080fd5b815161174981611eed565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a0608084015261272560e0840182611cd7565b90506060850151603f198483030160a08501526127428282611cd7565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b60006040828403121561277a57600080fd5b61278261228b565b9050815181526020820151602082015292915050565b6000604082840312156127aa57600080fd5b6117498383612768565b601f821115611ab1576000816000526020600020601f850160051c810160208610156127dd5750805b601f850160051c820191505b818110156127fc578281556001016127e9565b505050505050565b81516001600160401b0381111561281d5761281d612219565b6128318161282b845461222f565b846127b4565b602080601f831160018114612866576000841561284e5750858301515b600019600386901b1c1916600185901b1785556127fc565b600085815260208120601f198616915b8281101561289557888601518255948401946001909101908401612876565b50858210156128b35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561294057888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261292c81860183611cd7565b9689019694505050908601906001016128ec565b509098975050505050505050565b60006080828403121561296057600080fd5b612968612263565b82518152602083015161297a81612525565b602082015261298c8460408501612768565b60408201529392505050565b6000826129b557634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176108b757634e487b7160e01b600052601160045260246000fd5b803560208310156108b757600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015612a255780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251612a6c81602c850160208701611cb3565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251612aaf816048850160208701611cb3565b9190910160480195945050505050565b600060208284031215612ad157600080fd5b815161174981611df6565b600082516124d5818460208701611cb356fea2646970667358221220e555bfa7258725f0f0aa6bb4b576d8188d716fc671b830a2aae618fd0e00f8c864736f6c63430008190033

Verified Source Code Partial Match

Compiler: v0.8.25+commit.b61c2a91 EVM: paris Optimization: Yes (200 runs)
OFTAdapterImplementation.sol 2939 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 ^0.8.20;

// ../node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol

/**
 * @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);
}

// ../node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol

// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * 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[EIP 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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol

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 _gracePeriod) 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 _expiry) 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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol

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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol

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;
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol

interface IMessagingContext {
    function isSendingMessage() external view returns (bool);

    function getSendContext() external view returns (uint32 dstEid, address sender);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol

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));
    }
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol

/**
 * @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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol

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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol

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 for 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 for 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)));
    }
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol

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)));
    }
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the 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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@openzeppelin/contracts/utils/Address.sol

// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@openzeppelin/contracts/utils/Context.sol

// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

/**
 * @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;
    }
}

// ../node_modules/@openzeppelin/contracts/access/Ownable.sol

// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.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);
    }
}

// ../node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

/**
 * @dev Interface for the optional metadata functions from the ERC20 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);
}

// /Users/benhaslam/ambient/oft_tools/node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.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);
}

// ../node_modules/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.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);
    }
}

// ../node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol

// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 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 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 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 {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @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 {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    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.
     */
    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.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), 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 data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), 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 data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}

// ../node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol

struct MessagingParams_0 {
    uint32 dstEid;
    bytes32 receiver;
    bytes message;
    bytes options;
    bool payInLzToken;
}

struct MessagingReceipt_0 {
    bytes32 guid;
    uint64 nonce;
    MessagingFee_0 fee;
}

struct MessagingFee_0 {
    uint256 nativeFee;
    uint256 lzTokenFee;
}

struct Origin_0 {
    uint32 srcEid;
    bytes32 sender;
    uint64 nonce;
}

interface ILayerZeroEndpointV2_0 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
    event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);

    event PacketVerified(Origin_0 origin, address receiver, bytes32 payloadHash);

    event PacketDelivered(Origin_0 origin, address receiver);

    event LzReceiveAlert(
        address indexed receiver,
        address indexed executor,
        Origin_0 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_0 calldata _params, address _sender) external view returns (MessagingFee_0 memory);

    function send(
        MessagingParams_0 calldata _params,
        address _refundAddress
    ) external payable returns (MessagingReceipt_0 memory);

    function verify(Origin_0 calldata _origin, address _receiver, bytes32 _payloadHash) external;

    function verifiable(Origin_0 calldata _origin, address _receiver) external view returns (bool);

    function initializable(Origin_0 calldata _origin, address _receiver) external view returns (bool);

    function lzReceive(
        Origin_0 calldata _origin,
        address _receiver,
        bytes32 _guid,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;
...

// [truncated — 122489 bytes total]

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