Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0xE5B2FAbF3b2000eB6b03Bb4EbeA80fABC6159cF0
Balance 0 ETH
Nonce 1
Code Size 12624 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

12624 bytes
0x608060405234801561000f575f80fd5b5060043610610156575f3560e01c80638d072c40116100c1578063cf891ad81161007a578063cf891ad8146103b5578063e521136f146103d1578063e7986466146103ed578063f2fde38b14610409578063f887ea4014610425578063fbfa77cf1461044357610156565b80638d072c40146102f35780638da5cb5b1461030f578063aced16611461032d578063c7ed089e1461034b578063ca362ab414610369578063cea9d26f1461039957610156565b80635fcbd285116101135780635fcbd285146102455780636817031b1461026357806368c4ac261461027f578063715018a6146102af578063748747e6146102b957806380f55605146102d557610156565b8063023a8c8b1461015a57806317f333401461018a5780631dbef4a9146101a857806351261050146101c6578063515ce517146101f657806359356c5c14610227575b5f80fd5b610174600480360381019061016f91906125b0565b610461565b60405161018191906125f3565b60405180910390f35b610192610546565b60405161019f919061261b565b60405180910390f35b6101b061056b565b6040516101bd919061268f565b60405180910390f35b6101e060048036038101906101db9190612733565b610590565b6040516101ed91906125f3565b60405180910390f35b610210600480360381019061020b91906125b0565b610c09565b60405161021e929190612912565b60405180910390f35b61022f610fcd565b60405161023c91906125f3565b60405180910390f35b61024d61106c565b60405161025a9190612967565b60405180910390f35b61027d600480360381019061027891906125b0565b611091565b005b610299600480360381019061029491906125b0565b6111c1565b6040516102a6919061299a565b60405180910390f35b6102b76111de565b005b6102d360048036038101906102ce91906125b0565b6111f1565b005b6102dd61123c565b6040516102ea919061261b565b60405180910390f35b61030d600480360381019061030891906129b3565b611261565b005b6103176113e5565b604051610324919061261b565b60405180910390f35b61033561140c565b604051610342919061261b565b60405180910390f35b610353611431565b60405161036091906129f1565b60405180910390f35b610383600480360381019061037e9190612733565b6114c9565b60405161039091906125f3565b60405180910390f35b6103b360048036038101906103ae9190612a11565b611add565b005b6103cf60048036038101906103ca9190612a61565b611b7a565b005b6103eb60048036038101906103e691906125b0565b611d95565b005b61040760048036038101906104029190612ac9565b611ec5565b005b610423600480360381019061041e91906125b0565b611fd8565b005b61042d61205c565b60405161043a9190612b27565b60405180910390f35b61044b612080565b604051610458919061261b565b60405180910390f35b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036104c7576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610500919061261b565b602060405180830381865afa15801561051b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053f9190612b54565b9050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f6105996120a5565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461061f576040517f62df054500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8403610658576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036106bd576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661073d576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610798919061261b565b602060405180830381865afa1580156107b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d79190612b54565b1015610818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080f90612bd9565b60405180910390fd5b5f8590506108887f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9468660025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166120eb9092919063ffffffff16565b5f8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016108c2919061261b565b602060405180830381865afa1580156108dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109019190612b54565b90505f807f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94673ffffffffffffffffffffffffffffffffffffffff16878760405161094c929190612c33565b5f604051808303815f865af19150503d805f8114610985576040519150601f19603f3d011682016040523d82523d5f602084013e61098a565b606091505b509150915081610a4b57610a007f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9465f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166120eb9092919063ffffffff16565b5f815103610a43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3a90612cbb565b60405180910390fd5b805160208201fd5b610ab77f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9465f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166120eb9092919063ffffffff16565b5f8473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610af1919061261b565b602060405180830381865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b309190612b54565b90508381610b3e9190612d06565b95505f8603610b79576040517f97d9569c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ba433878773ffffffffffffffffffffffffffffffffffffffff166121f89092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff167f02ffa641367f5b897c0f8be81bce51f2ef055b4113d7a1e4fd082feea749bf528a88604051610bec929190612d39565b60405180910390a25050505050610c01612277565b949350505050565b606080610c146120a5565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610cbe575060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610cf5576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614610d2f5783610d52565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b905060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4f59f9b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610dbd573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610de59190612ebc565b925060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639262187b306040518263ffffffff1660e01b8152600401610e41919061261b565b5f604051808303815f875af1158015610e5c573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610e849190612fc3565b91505f5b8351811015610f57575f848281518110610ea557610ea461300a565b5b602002602001015190505f82855111610ebe575f610eda565b848381518110610ed157610ed061300a565b5b60200260200101515b90505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610f1757505f81115b15610f4857610f4784828473ffffffffffffffffffffffffffffffffffffffff166121f89092919063ffffffff16565b5b50508080600101915050610e88565b508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f10a210883f97ab1cc72d6887723a3cfc7c0270e43a65c960ff9fc9a14239b12c8585604051610fb7929190612912565b60405180910390a350610fc8612277565b915091565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611028919061261b565b602060405180830381865afa158015611043573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110679190612b54565b905090565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611099612280565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036110fe576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f483bdedaaf23706a9800ac1af0d852b34927780d79f9d6ba60a80c7cad75ea3960405160405180910390a35050565b6006602052805f5260405f205f915054906101000a900460ff1681565b6111e6612280565b6111ef5f612307565b565b6111f9612280565b8060085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6112696120a5565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112ef576040517f62df054500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611354576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f810361138d576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113d9828260025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166121f89092919063ffffffff16565b6113e1612277565b5050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4f59f9b6040518163ffffffff1660e01b81526004015f60405180830381865afa15801561149c573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906114c49190612ebc565b905090565b5f6114d26120a5565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611558576040517f62df054500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8403611591576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036115f6576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611676576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8590505f8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016116b4919061261b565b602060405180830381865afa1580156116cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f39190612b54565b90508581101561173b575f818761170a9190612d06565b90506117393330838673ffffffffffffffffffffffffffffffffffffffff166123c8909392919063ffffffff16565b505b6117867f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946878473ffffffffffffffffffffffffffffffffffffffff166120eb9092919063ffffffff16565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016117e1919061261b565b602060405180830381865afa1580156117fc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118209190612b54565b90505f807f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94673ffffffffffffffffffffffffffffffffffffffff16888860405161186b929190612c33565b5f604051808303815f865af19150503d805f81146118a4576040519150601f19603f3d011682016040523d82523d5f602084013e6118a9565b606091505b509150915081611949576118fe7f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9465f8773ffffffffffffffffffffffffffffffffffffffff166120eb9092919063ffffffff16565b5f815103611941576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193890612cbb565b60405180910390fd5b805160208201fd5b6119947f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9465f8773ffffffffffffffffffffffffffffffffffffffff166120eb9092919063ffffffff16565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016119ef919061261b565b602060405180830381865afa158015611a0a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a2e9190612b54565b90508381611a3c9190612d06565b96505f8703611a77576040517f97d9569c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a73ffffffffffffffffffffffffffffffffffffffff167ffaddc2a572d923daf0944fe20bf804595e90ca57c85045b1081d338d1510bf148b89604051611abf929190612d39565b60405180910390a2505050505050611ad5612277565b949350505050565b611ae5612280565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611b4a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7582828573ffffffffffffffffffffffffffffffffffffffff166121f89092919063ffffffff16565b505050565b611b82612280565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480611be757505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15611c1e576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508360035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360045f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f7ec9b4ca0d9d91122c2ce339e653f9c87d70a5e9e681f085961edea2ce86503d8386604051611d87929190613037565b60405180910390a350505050565b611d9d612280565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e02576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fc8c11bb97ac2ffa10ce2e2a98f4c1fd8df84cfa2e1a15e013ed2383ab1f527ad60405160405180910390a35050565b611ecd612280565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f32576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fd86c88b4a367d9b81a6e00c9d3f7d01657bffef358fa8968c91c045ae99f0d5282604051611fcc919061299a565b60405180910390a25050565b611fe0612280565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612050575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401612047919061261b565b60405180910390fd5b61205981612307565b50565b7f000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94681565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6002600154036120e1576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600181905550565b5f8373ffffffffffffffffffffffffffffffffffffffff1663095ea7b3848460405160240161211b92919061305e565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050612169848261244a565b6121f2576121e7848573ffffffffffffffffffffffffffffffffffffffff1663095ea7b3865f6040516024016121a09291906130be565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124a3565b6121f184826124a3565b5b50505050565b612272838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb858560405160240161222b92919061305e565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124a3565b505050565b60018081905550565b61228861253e565b73ffffffffffffffffffffffffffffffffffffffff166122a66113e5565b73ffffffffffffffffffffffffffffffffffffffff1614612305576122c961253e565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016122fc919061261b565b60405180910390fd5b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612444848573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016123fd939291906130e5565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124a3565b50505050565b5f805f8060205f8651602088015f8a5af192503d91505f51905082801561249857505f821461247c5760018114612497565b5f8673ffffffffffffffffffffffffffffffffffffffff163b115b5b935050505092915050565b5f8060205f8451602086015f885af1806124c2576040513d5f823e3d81fd5b3d92505f519150505f82146124db5760018114156124f6565b5f8473ffffffffffffffffffffffffffffffffffffffff163b145b1561253857836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161252f919061261b565b60405180910390fd5b50505050565b5f33905090565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61257f82612556565b9050919050565b61258f81612575565b8114612599575f80fd5b50565b5f813590506125aa81612586565b92915050565b5f602082840312156125c5576125c461254e565b5b5f6125d28482850161259c565b91505092915050565b5f819050919050565b6125ed816125db565b82525050565b5f6020820190506126065f8301846125e4565b92915050565b61261581612575565b82525050565b5f60208201905061262e5f83018461260c565b92915050565b5f819050919050565b5f61265761265261264d84612556565b612634565b612556565b9050919050565b5f6126688261263d565b9050919050565b5f6126798261265e565b9050919050565b6126898161266f565b82525050565b5f6020820190506126a25f830184612680565b92915050565b6126b1816125db565b81146126bb575f80fd5b50565b5f813590506126cc816126a8565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f8401126126f3576126f26126d2565b5b8235905067ffffffffffffffff8111156127105761270f6126d6565b5b60208301915083600182028301111561272c5761272b6126da565b5b9250929050565b5f805f806060858703121561274b5761274a61254e565b5b5f6127588782880161259c565b9450506020612769878288016126be565b935050604085013567ffffffffffffffff81111561278a57612789612552565b5b612796878288016126de565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6127d681612575565b82525050565b5f6127e783836127cd565b60208301905092915050565b5f602082019050919050565b5f612809826127a4565b61281381856127ae565b935061281e836127be565b805f5b8381101561284e57815161283588826127dc565b9750612840836127f3565b925050600181019050612821565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61288d816125db565b82525050565b5f61289e8383612884565b60208301905092915050565b5f602082019050919050565b5f6128c08261285b565b6128ca8185612865565b93506128d583612875565b805f5b838110156129055781516128ec8882612893565b97506128f7836128aa565b9250506001810190506128d8565b5085935050505092915050565b5f6040820190508181035f83015261292a81856127ff565b9050818103602083015261293e81846128b6565b90509392505050565b5f6129518261265e565b9050919050565b61296181612947565b82525050565b5f60208201905061297a5f830184612958565b92915050565b5f8115159050919050565b61299481612980565b82525050565b5f6020820190506129ad5f83018461298b565b92915050565b5f80604083850312156129c9576129c861254e565b5b5f6129d68582860161259c565b92505060206129e7858286016126be565b9150509250929050565b5f6020820190508181035f830152612a0981846127ff565b905092915050565b5f805f60608486031215612a2857612a2761254e565b5b5f612a358682870161259c565b9350506020612a468682870161259c565b9250506040612a57868287016126be565b9150509250925092565b5f8060408385031215612a7757612a7661254e565b5b5f612a848582860161259c565b9250506020612a958582860161259c565b9150509250929050565b612aa881612980565b8114612ab2575f80fd5b50565b5f81359050612ac381612a9f565b92915050565b5f8060408385031215612adf57612ade61254e565b5b5f612aec8582860161259c565b9250506020612afd85828601612ab5565b9150509250929050565b5f612b118261265e565b9050919050565b612b2181612b07565b82525050565b5f602082019050612b3a5f830184612b18565b92915050565b5f81519050612b4e816126a8565b92915050565b5f60208284031215612b6957612b6861254e565b5b5f612b7684828501612b40565b91505092915050565b5f82825260208201905092915050565b7f696e73756666696369656e74204c5000000000000000000000000000000000005f82015250565b5f612bc3600f83612b7f565b9150612bce82612b8f565b602082019050919050565b5f6020820190508181035f830152612bf081612bb7565b9050919050565b5f81905092915050565b828183375f83830152505050565b5f612c1a8385612bf7565b9350612c27838584612c01565b82840190509392505050565b5f612c3f828486612c0f565b91508190509392505050565b7f526f757465722063616c6c206661696c656420776974686f757420726561736f5f8201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b5f612ca5602183612b7f565b9150612cb082612c4b565b604082019050919050565b5f6020820190508181035f830152612cd281612c99565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612d10826125db565b9150612d1b836125db565b9250828203905081811115612d3357612d32612cd9565b5b92915050565b5f604082019050612d4c5f8301856125e4565b612d5960208301846125e4565b9392505050565b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612da682612d60565b810181811067ffffffffffffffff82111715612dc557612dc4612d70565b5b80604052505050565b5f612dd7612545565b9050612de38282612d9d565b919050565b5f67ffffffffffffffff821115612e0257612e01612d70565b5b602082029050602081019050919050565b5f81519050612e2181612586565b92915050565b5f612e39612e3484612de8565b612dce565b90508083825260208201905060208402830185811115612e5c57612e5b6126da565b5b835b81811015612e855780612e718882612e13565b845260208401935050602081019050612e5e565b5050509392505050565b5f82601f830112612ea357612ea26126d2565b5b8151612eb3848260208601612e27565b91505092915050565b5f60208284031215612ed157612ed061254e565b5b5f82015167ffffffffffffffff811115612eee57612eed612552565b5b612efa84828501612e8f565b91505092915050565b5f67ffffffffffffffff821115612f1d57612f1c612d70565b5b602082029050602081019050919050565b5f612f40612f3b84612f03565b612dce565b90508083825260208201905060208402830185811115612f6357612f626126da565b5b835b81811015612f8c5780612f788882612b40565b845260208401935050602081019050612f65565b5050509392505050565b5f82601f830112612faa57612fa96126d2565b5b8151612fba848260208601612f2e565b91505092915050565b5f60208284031215612fd857612fd761254e565b5b5f82015167ffffffffffffffff811115612ff557612ff4612552565b5b61300184828501612f96565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60408201905061304a5f83018561260c565b613057602083018461260c565b9392505050565b5f6040820190506130715f83018561260c565b61307e60208301846125e4565b9392505050565b5f819050919050565b5f6130a86130a361309e84613085565b612634565b6125db565b9050919050565b6130b88161308e565b82525050565b5f6040820190506130d15f83018561260c565b6130de60208301846130af565b9392505050565b5f6060820190506130f85f83018661260c565b613105602083018561260c565b61311260408301846125e4565b94935050505056fea2646970667358221220292113e2a536e49409d73c10d8d91c780f8f1a49664363eb0adf08961545819964736f6c63430008160033

Verified Source Code Full Match

Compiler: v0.8.22+commit.4fc1097e EVM: shanghai Optimization: No
PendleAdapter_v3.sol 475 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";



/**
 * @title PendleAdapter
 * @notice Production-grade adapter for Pendle LP strategy
 * @dev This adapter is an EXECUTOR ONLY - all pricing, slippage, and routing
 *      is handled OFF-CHAIN via Pendle SDK or Hosted API.
 * 
 * Architecture:
 * - Backend/Keeper generates swap parameters (SwapData, GuessPtReceivedFromSy, minOut)
 * - Adapter executes the zap with provided parameters
 * - NO on-chain price calculations
 * - NO on-chain swap calldata building
 * - Follows Yearn-style adapter architecture
 */

 //VAULT 0x1B6Bb412a7E077958C9FdA5e6f0235dbB22F7a8B
 //usdc 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
 //usdt 0xdAC17F958D2ee523a2206206994597C13D831ec7
 //lptoken 0x6D520a943a4Da0784917a2e71defe95248A1DaA1
	//market	address 0x6D520a943a4Da0784917a2e71defe95248A1DaA1
 //ZapRouter  0x888888888889758F76e7103c6CbF23ABbF58F946
// NEW DEPLOY 0xCbFDBAe49883E378752fF3F64bf8d89562912Da6
 
// ========= Pendle Router Structs (must match ABI exactly) =========

interface IPMarket {
    function getRewardTokens() external view returns (address[] memory);
    function redeemRewards(address user) external returns (uint256[] memory);
}
/// =======================
/// IPAllActionV3 (minimal)
/// =======================
interface IPAllActionV3 {
    struct ApproxParams {
        uint256 guessMin;
        uint256 guessMax;
        uint256 guessOffchain;
        uint256 maxIteration;
        uint256 eps;
    }

    // EXACTLY: (uint256,address,bytes,bool)
    struct SwapData {
        uint8 swapType;
        address extRouter;
        bytes extCalldata;
        bool needScale;
    }

    // EXACTLY: (address,uint256,address,address,SwapData)
    struct TokenInput {
        address tokenIn;
        uint256 netTokenIn;
        address tokenMintSy;
        address pendleSwap;
        SwapData swapData;
    }

    // EXACTLY (for removeLiquidity): (address,uint256,address,address,SwapData) but as output params
    struct TokenOutput {
        address tokenOut;
        uint256 minTokenOut;
        address tokenRedeemSy;
        address pendleSwap;
        SwapData swapData;
    }

    /**
     * @dev Minimal placeholder for tuple element type.
     * If in future you actually pass fills (non-empty), you MUST match Pendle's real struct.
     * With empty arrays, ABI encoding is still correct.
     */
    struct FillOrderParams {
        bytes order;
        bytes signature;
        uint256 makingAmount;
        uint256 takingAmount;
    }

    // EXACTLY: (address,uint256,tuple[],tuple[],bytes)
    struct LimitOrderData {
        address limitRouter;
        uint256 epsSkipMarket;
        FillOrderParams[] normalFills;
        FillOrderParams[] flashFills;
        bytes optData;
    }

    function addLiquiditySingleToken(
        address receiver,
        address market,
        uint256 minLpOut,
        ApproxParams calldata approx,
        TokenInput calldata input,
        LimitOrderData calldata limit
    ) external payable returns (uint256 netLpOut, uint256 netSyFee, uint256 netSyInterm);

    function removeLiquiditySingleToken(
        address receiver,
        address market,
        uint256 netLpToRemove,
        TokenOutput calldata output,
        LimitOrderData calldata limit
    ) external returns (uint256 netTokenOut, uint256 netSyFee, uint256 netSyInterm);
}

// ========= Main Contract =========

contract PendleAdapter is Ownable, ReentrancyGuard {
    using SafeERC20 for IERC20;

    // ========= Immutable State =========
    IERC20 public  lpToken;        // Pendle LP token
    address public  market;        // Pendle market address (gauge embedded)
    IPAllActionV3 public immutable router;
    // NEW: market interface for rewards
    IPMarket public  marketRewards;

    // ========= Mutable State =========
    address public vault;                   // Authorized vault address
    mapping(address => bool) public supportedTokens; // Supported tokens (USDC, USDT, etc.)
      // NEW: where harvested rewards are sent (default: vault)
    address public rewardRecipient;
    // ========= Events =========
    event Deposited(uint256 tokenAmount, uint256 lpReceived, address indexed token);
    event Withdrawn(uint256 lpAmount, uint256 tokenReceived, address indexed token);
    event VaultUpdated(address indexed oldVault, address indexed newVault);
    event TokenSupported(address indexed token, bool supported);

     // NEW events
    event RewardRecipientUpdated(address indexed oldRecipient, address indexed newRecipient);
    event RewardsHarvested(address indexed caller, address indexed recipient, address[] rewardTokens, uint256[] amounts);


    // ========= Errors =========
    error ZeroAddress();
    error ZeroAmount();
    error NotVault();
    error InvalidInput();
    error ZapFailed();
     error NotAuthorized();
     error BadCalldataSelector();
    error BadCalldataReceiver();
    error BadCalldataMarket();


    // ========= Modifiers =========
    modifier onlyVault() {
        if (msg.sender != vault) revert NotVault();
        _;
    }

    // optional: allow a keeper to harvest (owner sets it)
    address public keeper;

    modifier onlyVaultOrKeeper() {
        if (msg.sender != vault && msg.sender != keeper) revert NotAuthorized();
        _;
    }

    constructor(
        address _vault,
        address _lpToken,
        address _market,
        address  _router
    ) Ownable(msg.sender) {
        if (_vault == address(0) || _lpToken == address(0) || 
            _market == address(0) || _router == address(0)) revert ZeroAddress();
        
        vault = _vault;
        lpToken = IERC20(_lpToken);
        market = _market;
        router = IPAllActionV3(_router);

        // NEW
        marketRewards = IPMarket(_market);
        rewardRecipient = _vault;
    }


function setKeeper(address _keeper) external onlyOwner {
        keeper = _keeper; // can be zero to disable
    }

    function setRewardRecipient(address _recipient) external onlyOwner {
        if (_recipient == address(0)) revert ZeroAddress();
        address old = rewardRecipient;
        rewardRecipient = _recipient;
        emit RewardRecipientUpdated(old, _recipient);
    }
    // ========= Token Management =========

    /**
     * @notice Add or remove a supported token
     * @param token Token address to set
     * @param supported Whether the token is supported
     */
    function setSupportedToken(address token, bool supported) external onlyOwner {
        if (token == address(0)) revert ZeroAddress();
        supportedTokens[token] = supported;
        emit TokenSupported(token, supported);
    }
// -------------------- NEW: rewards view helpers --------------------

    /// @notice Reward tokens for this market (can include PENDLE + others)
    function getMarketRewardTokens() external view returns (address[] memory) {
        return marketRewards.getRewardTokens();
    }

      // -------------------- NEW: harvest rewards --------------------
    /**
     * @notice Claims (redeems) market rewards accrued by this Adapter (LP holder).
     * @dev Pendle V2 rewards for LP holders are claimed via Market.redeemRewards(adapter).
     *      This does NOT unstake anything; gauge is embedded in the market. :contentReference[oaicite:2]{index=2}
     *
     * @param recipient Where to send harvested rewards (if zero, uses rewardRecipient)
     * @return rewardTokens tokens claimed
     * @return amounts amounts claimed (same order as rewardTokens)
     */
    function harvestRewards(address recipient)
        external
        nonReentrant
        onlyVaultOrKeeper
        returns (address[] memory rewardTokens, uint256[] memory amounts)
    {
        address to = recipient == address(0) ? rewardRecipient : recipient;

        rewardTokens = marketRewards.getRewardTokens();

        // Claim rewards for THIS adapter address
        amounts = marketRewards.redeemRewards(address(this));

        // Send claimed tokens to recipient
        // Note: redeemRewards returns amounts in order of getRewardTokens() :contentReference[oaicite:3]{index=3}
        for (uint256 i = 0; i < rewardTokens.length; i++) {
            address rt = rewardTokens[i];
            uint256 amt = amounts.length > i ? amounts[i] : 0;
            if (rt != address(0) && amt > 0) {
                IERC20(rt).safeTransfer(to, amt);
            }
        }

        emit RewardsHarvested(msg.sender, to, rewardTokens, amounts);
    }

     /* =========================
        HARDENED ZAP CALL HELPERS
       ========================= */

    function _selector(bytes calldata data) internal pure returns (bytes4 sel) {
        if (data.length < 4) return 0x00000000;
        assembly {
            sel := calldataload(data.offset)
        }
    }

    /**
     * @dev Validates that calldata is calling the expected Pendle router function
     *      and that first 2 args match (receiver, market).
     *
     * ABI: function(receiver, market, ...) => first two args are address,address.
     */
    function _validateRouterCalldata(bytes calldata data) internal view {
        bytes4 sel = _selector(data);

        bytes4 addSel = IPAllActionV3.addLiquiditySingleToken.selector;
        bytes4 remSel = IPAllActionV3.removeLiquiditySingleToken.selector;

        if (sel != addSel && sel != remSel) revert BadCalldataSelector();

        // decode first two args after selector:
        // data layout: 4 bytes selector + ABI encoded args
        // args start at offset 4
        (address receiver, address mkt) = abi.decode(data[4:], (address, address));

        if (receiver != address(this)) revert BadCalldataReceiver();
        if (mkt != market) revert BadCalldataMarket();
    }

    function _approveExactThenZero(IERC20 token, address spender, uint256 amount) internal {
        // forceApprove handles USDT-style approvals
        token.forceApprove(spender, amount);
        // Important: reset after use to minimize allowance misuse window
        token.forceApprove(spender, 0);
    }
    // ========= Zap In (Deposit) =========

    /**
     * @notice Deposit token using pre-built calldata from Pendle API (GENERIC)
     * @dev This is the RECOMMENDED method - uses Pendle API's pre-built calldata
     *      which ensures correct struct encoding and selector matching.
     *      Supports any ERC20 token (USDC, USDT, etc.)
     * 
     * @param token Token address to deposit (must be supported)
     * @param tokenAmount Amount of token to deposit
     * @param routerCalldata Pre-built calldata from Pendle API (routerTx.data)
     * @return lpReceived Amount of LP tokens received
     */
    function depositWithCalldataGeneric(
        address token,
        uint256 tokenAmount,
        bytes calldata routerCalldata
    ) external nonReentrant onlyVault returns (uint256 lpReceived) {
        if (tokenAmount == 0) revert ZeroAmount();
        if (token == address(0)) revert ZeroAddress();
        if (!supportedTokens[token]) revert InvalidInput();

      //  _validateRouterCalldata(routerCalldata);

        IERC20 tokenContract = IERC20(token);

        // 1. Transfer token from caller to adapter (if not already present)
        uint256 currentBalance = tokenContract.balanceOf(address(this));
        if (currentBalance < tokenAmount) {
            uint256 needed = tokenAmount - currentBalance;
            tokenContract.safeTransferFrom(msg.sender, address(this), needed);
        }

        // 2. Approve token to ZapRouter
        // ⭐ CRITICAL: Use forceApprove for USDT compatibility
        // USDT requires allowance to be 0 before setting a new value,
        // and doesn't return true on approve() calls.
        // forceApprove() handles both cases automatically.
        tokenContract.forceApprove(address(router), tokenAmount);

        // 3. Record LP balance before
        uint256 lpBefore = lpToken.balanceOf(address(this));

        // 4. Execute router call with pre-built calldata
        // The calldata is built by Pendle API with correct struct encoding
        (bool success, bytes memory result) = address(router).call(routerCalldata);
        if (!success) {
             // reset allowance before bubbling revert (best effort)
            tokenContract.forceApprove(address(router), 0);
            if (result.length == 0) {
                revert("Router call failed without reason");
            }
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
// Reset allowance after success
        tokenContract.forceApprove(address(router), 0);
        // 5. Calculate LP received
        uint256 lpAfter = lpToken.balanceOf(address(this));
        lpReceived = lpAfter - lpBefore;

        if (lpReceived == 0) revert ZapFailed();
        emit Deposited(tokenAmount, lpReceived, token);
    }

 

   
    function withdrawWithCalldataGeneric(
        address tokenOut,
        uint256 lpAmount,
        bytes calldata routerCalldata
    ) external nonReentrant onlyVault returns (uint256 tokenReceived) {
        if (lpAmount == 0) revert ZeroAmount();
        if (tokenOut == address(0)) revert ZeroAddress();
        if (!supportedTokens[tokenOut]) revert InvalidInput();

       //  _validateRouterCalldata(routerCalldata);
        require(lpToken.balanceOf(address(this)) >= lpAmount, "insufficient LP");

        IERC20 tokenContract = IERC20(tokenOut);

        

        // 1. Approve LP tokens to ZapRouter
        // Using forceApprove for consistency (LP token is standard ERC20 but this is safer)
        lpToken.forceApprove(address(router), lpAmount);

        // 2. Record token balance before
        uint256 tokenBefore = tokenContract.balanceOf(address(this));

        // 3. Execute router call with pre-built calldata
        (bool success, bytes memory result) = address(router).call(routerCalldata);
        if (!success) {
            lpToken.forceApprove(address(router), 0);
            if (result.length == 0) {
                revert("Router call failed without reason");
            }
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
        lpToken.forceApprove(address(router), 0);
        // 4. Calculate token received
        uint256 tokenAfter = tokenContract.balanceOf(address(this));
        tokenReceived = tokenAfter - tokenBefore;

        if (tokenReceived == 0) revert ZapFailed();
     

        // 5. Transfer token to caller
        tokenContract.safeTransfer(msg.sender, tokenReceived);
        emit Withdrawn(lpAmount, tokenReceived, tokenOut);
    }

   

    function underlyingBalance() external view returns (uint256) {
        return lpToken.balanceOf(address(this));
    }

    /**
     * @notice Get idle balance of a specific token
     * @param token Token address to check
     * @return balance Idle balance of the token
     */
    function idleTokenBalance(address token) external view returns (uint256) {
        if (token == address(0)) revert ZeroAddress();
        return IERC20(token).balanceOf(address(this));
    }

    function setVault(address _newVault) external onlyOwner {
        if (_newVault == address(0)) revert ZeroAddress();
        address oldVault = vault;
        vault = _newVault;
        emit VaultUpdated(oldVault, _newVault);
    }
event MarketUpdated(
    address indexed oldMarket,
    address indexed newMarket,
    address oldLpToken,
    address newLpToken
);

    function setMarketAndLpToken(
        address _newMarket,
        address _newLpToken
    ) external onlyOwner {
        if (_newMarket == address(0) || _newLpToken == address(0)) revert ZeroAddress();

        address oldMarket = market;
        address oldLp = address(lpToken);

        market = _newMarket;
        lpToken = IERC20(_newLpToken);
        marketRewards = IPMarket(_newMarket);

        emit MarketUpdated(oldMarket, _newMarket, oldLp, _newLpToken);
    }


    function rescueTokens(address token, address to, uint256 amount) external onlyOwner {
        if (to == address(0)) revert ZeroAddress();
        IERC20(token).safeTransfer(to, amount);
    }

        /* =========================
        LP-BASED WITHDRAW HELPERS
       ========================= */

  

    /// @notice Transfer LP to `to` (for withdrawAlternativeLP in the router)
    function transferLp(address to, uint256 lpAmount) external nonReentrant onlyVault {
        if (to == address(0)) revert ZeroAddress();
        if (lpAmount == 0) revert ZeroAmount();
        lpToken.safeTransfer(to, lpAmount);
    }

}
ReentrancyGuard.sol 87 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}
SafeERC20.sol 212 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 {
        _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 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 _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @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 _callOptionalReturnBool(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.
     *
     * 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 {
        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 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 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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            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 silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}
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);
}
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);
}
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 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";
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);
}

Read Contract

getMarketRewardTokens 0xc7ed089e → address[]
idleTokenBalance 0x023a8c8b → uint256
keeper 0xaced1661 → address
lpToken 0x5fcbd285 → address
market 0x80f55605 → address
marketRewards 0x1dbef4a9 → address
owner 0x8da5cb5b → address
rewardRecipient 0x17f33340 → address
router 0xf887ea40 → address
supportedTokens 0x68c4ac26 → bool
underlyingBalance 0x59356c5c → uint256
vault 0xfbfa77cf → address

Write Contract 12 functions

These functions modify contract state and require a wallet transaction to execute.

depositWithCalldataGeneric 0xca362ab4
address token
uint256 tokenAmount
bytes routerCalldata
returns: uint256
harvestRewards 0x515ce517
address recipient
returns: address[], uint256[]
renounceOwnership 0x715018a6
No parameters
rescueTokens 0xcea9d26f
address token
address to
uint256 amount
setKeeper 0x748747e6
address _keeper
setMarketAndLpToken 0xcf891ad8
address _newMarket
address _newLpToken
setRewardRecipient 0xe521136f
address _recipient
setSupportedToken 0xe7986466
address token
bool supported
setVault 0x6817031b
address _newVault
transferLp 0x8d072c40
address to
uint256 lpAmount
transferOwnership 0xf2fde38b
address newOwner
withdrawWithCalldataGeneric 0x51261050
address tokenOut
uint256 lpAmount
bytes routerCalldata
returns: uint256

Recent Transactions

No transactions found for this address