Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x13B043bf4feBaf2ED9711C615f26B51dA6309EeD
Balance 0 ETH
Nonce 1
Code Size 9535 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9535 bytes
0x608060405234801561000f575f5ffd5b5060043610610060575f3560e01c806323a69e75146100645780638da5cb5b146100805780639e30c3591461009e578063b8dc491b146100ce578063f2fde38b146100ea578063fa461e3314610106575b5f5ffd5b61007e60048036038101906100799190611695565b610122565b005b61008861047e565b6040516100959190611745565b60405180910390f35b6100b860048036038101906100b391906117e6565b6104a2565b6040516100c59190611852565b60405180910390f35b6100e860048036038101906100e39190611895565b61077e565b005b61010460048036038101906100ff91906118d3565b6108b7565b005b610120600480360381019061011b9190611695565b610a6f565b005b5f84138061012f57505f83135b610165576040517f9b5e411b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f5f5f85858101906101789190611971565b93509350935093505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610314576101bc81610dcb565b6101f2576040517fa657de7900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8173ffffffffffffffffffffffffffffffffffffffff16631698ee828686866040518463ffffffff1660e01b8152600401610230939291906119e4565b602060405180830381865afa15801561024b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026f9190611a2d565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806102d757508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b1561030e576040517f161211a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610346565b6040517fa657de7900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f89136103545787610356565b885b90505f3373ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103c69190611a2d565b90505f5f8b13610442573373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610419573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061043d9190611a2d565b610444565b815b905061047133848373ffffffffffffffffffffffffffffffffffffffff16610f0a9092919063ffffffff16565b5050505050505050505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052890611ab2565b60405180910390fd5b5f8484905011610576576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056d90611b1a565b60405180910390fd5b5f84845f81811061058a57610589611b38565b5b905060200281019061059c9190611b71565b6040013590505f5b8585905081101561072f57368686838181106105c3576105c2611b38565b5b90506020028101906105d59190611b71565b9050600160ff168160a00160208101906105ef9190611bcf565b60ff16036106575761065081608001602081019061060d91906118d3565b825f01602081019061061f91906118d3565b83602001602081019061063291906118d3565b8685606001358660c001602081019061064b9190611c2f565b610f91565b9250610723565b600260ff168160a001602081019061066f9190611bcf565b60ff16036106e7576106e081608001602081019061068d91906118d3565b825f01602081019061069f91906118d3565b8360200160208101906106b291906118d3565b8685606001358660c00160208101906106cb9190611c2f565b878060e001906106db9190611c5a565b6111ea565b9250610722565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161071990611d06565b60405180910390fd5b5b816001019150506105a4565b5080915082821015610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161076d90611d6e565b60405180910390fd5b509392505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461080c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080390611ab2565b60405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016108469190611745565b602060405180830381865afa158015610861573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108859190611da0565b90506108b282828573ffffffffffffffffffffffffffffffffffffffff16610f0a9092919063ffffffff16565b505050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093c90611ab2565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109aa90611e15565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f841380610a7c57505f83135b610ab2576040517f9b5e411b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f5f5f8585810190610ac59190611971565b93509350935093505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c6157610b0981610dcb565b610b3f576040517fa657de7900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8173ffffffffffffffffffffffffffffffffffffffff16631698ee828686866040518463ffffffff1660e01b8152600401610b7d939291906119e4565b602060405180830381865afa158015610b98573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbc9190611a2d565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610c2457508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610c5b576040517f161211a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50610c93565b6040517fa657de7900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f8913610ca15787610ca3565b885b90505f3373ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cef573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d139190611a2d565b90505f5f8b13610d8f573373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d8a9190611a2d565b610d91565b815b9050610dbe33848373ffffffffffffffffffffffffffffffffffffffff16610f0a9092919063ffffffff16565b5050505050505050505050565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e07575f9050610f05565b7f000000000000000000000000baceb8ec6b9355dfc0269c18bac9d6e2bdc29c4f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610eac57507f0000000000000000000000001f98431c8ad98523631ae4a59f267346ea31f98473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b80610f0257507f0000000000000000000000000bfbcf9fa4f9c56b0f40a671ad40e0805a09186573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b90505b919050565b610f8b8363a9059cbb60e01b8484604051602401610f29929190611e33565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611368565b50505050565b5f5f8573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610fcc9190611745565b602060405180830381865afa158015610fe7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061100b9190611da0565b905061103888868973ffffffffffffffffffffffffffffffffffffffff16610f0a9092919063ffffffff16565b5f836110445784611046565b5f5b90505f84611054575f611056565b855b90508973ffffffffffffffffffffffffffffffffffffffff1663022c0d9f8383305f67ffffffffffffffff81111561109157611090611e5a565b5b6040519080825280601f01601f1916602001820160405280156110c35781602001600182028036833780820191505090505b506040518563ffffffff1660e01b81526004016110e39493929190611ef7565b5f604051808303815f87803b1580156110fa575f5ffd5b505af115801561110c573d5f5f3e3d5ffd5b505050505f8873ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161114a9190611745565b602060405180830381865afa158015611165573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111899190611da0565b905083816111979190611f6e565b9450868510156111dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d390611feb565b60405180910390fd5b505050509695505050505050565b5f5f5f5f6111f986868961147c565b9250925092505f8b8b84846040516020016112179493929190612009565b60405160208183030381529060405290505f8a90505f5f8f73ffffffffffffffffffffffffffffffffffffffff1663128acb08308d868b896040518663ffffffff1660e01b815260040161126f959493929190612079565b60408051808303815f875af115801561128a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ae91906120e5565b915091505f8b6112be57826112c0565b815b90505f811315611305576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fc9061216d565b60405180910390fd5b8061130f9061218b565b98508c891015611354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134b9061221b565b60405180910390fd5b505050505050505098975050505050505050565b60605f5f8473ffffffffffffffffffffffffffffffffffffffff16846040516113919190612273565b5f604051808303815f865af19150503d805f81146113ca576040519150601f19603f3d011682016040523d82523d5f602084013e6113cf565b606091505b509150915081611414576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161140b906122d3565b60405180910390fd5b5f8151111561147157808060200190518101906114319190612305565b611470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114679061237a565b60405180910390fd5b5b809250505092915050565b5f5f5f5f846114ab57600173ffffffffffffffffffffffffffffffffffffffff6114a69190612398565b6114b9565b60015f6114b891906123df565b5b90508093505f92505f91505f87879050036114d45750611564565b60208787905003611507575f87878101906114ef9190612426565b90505f8190506114fe8161156d565b95505050611562565b6040878790500361152e5786868101906115219190612451565b8093508194505050611561565b6060878790500361156057868681019061154891906124b9565b80945081955082965050505061155d8461156d565b93505b5b5b505b93509350939050565b5f60018273ffffffffffffffffffffffffffffffffffffffff161161159557600190506115f4565b73ffffffffffffffffffffffffffffffffffffffff80168273ffffffffffffffffffffffffffffffffffffffff16106115f057600173ffffffffffffffffffffffffffffffffffffffff6115e99190612398565b90506115f4565b8190505b919050565b5f5ffd5b5f5ffd5b5f819050919050565b61161381611601565b811461161d575f5ffd5b50565b5f8135905061162e8161160a565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261165557611654611634565b5b8235905067ffffffffffffffff81111561167257611671611638565b5b60208301915083600182028301111561168e5761168d61163c565b5b9250929050565b5f5f5f5f606085870312156116ad576116ac6115f9565b5b5f6116ba87828801611620565b94505060206116cb87828801611620565b935050604085013567ffffffffffffffff8111156116ec576116eb6115fd565b5b6116f887828801611640565b925092505092959194509250565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61172f82611706565b9050919050565b61173f81611725565b82525050565b5f6020820190506117585f830184611736565b92915050565b5f5f83601f84011261177357611772611634565b5b8235905067ffffffffffffffff8111156117905761178f611638565b5b6020830191508360208202830111156117ac576117ab61163c565b5b9250929050565b5f819050919050565b6117c5816117b3565b81146117cf575f5ffd5b50565b5f813590506117e0816117bc565b92915050565b5f5f5f604084860312156117fd576117fc6115f9565b5b5f84013567ffffffffffffffff81111561181a576118196115fd565b5b6118268682870161175e565b93509350506020611839868287016117d2565b9150509250925092565b61184c816117b3565b82525050565b5f6020820190506118655f830184611843565b92915050565b61187481611725565b811461187e575f5ffd5b50565b5f8135905061188f8161186b565b92915050565b5f5f604083850312156118ab576118aa6115f9565b5b5f6118b885828601611881565b92505060206118c985828601611881565b9150509250929050565b5f602082840312156118e8576118e76115f9565b5b5f6118f584828501611881565b91505092915050565b5f61190882611706565b9050919050565b611918816118fe565b8114611922575f5ffd5b50565b5f813590506119338161190f565b92915050565b5f62ffffff82169050919050565b61195081611939565b811461195a575f5ffd5b50565b5f8135905061196b81611947565b92915050565b5f5f5f5f60808587031215611989576119886115f9565b5b5f61199687828801611925565b94505060206119a787828801611925565b93505060406119b88782880161195d565b92505060606119c987828801611925565b91505092959194509250565b6119de81611939565b82525050565b5f6060820190506119f75f830186611736565b611a046020830185611736565b611a1160408301846119d5565b949350505050565b5f81519050611a278161186b565b92915050565b5f60208284031215611a4257611a416115f9565b5b5f611a4f84828501611a19565b91505092915050565b5f82825260208201905092915050565b7f4f4e4c595f4f574e4552000000000000000000000000000000000000000000005f82015250565b5f611a9c600a83611a58565b9150611aa782611a68565b602082019050919050565b5f6020820190508181035f830152611ac981611a90565b9050919050565b7f4e4f5f484f5053000000000000000000000000000000000000000000000000005f82015250565b5f611b04600783611a58565b9150611b0f82611ad0565b602082019050919050565b5f6020820190508181035f830152611b3181611af8565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f8235600161010003833603038112611b8d57611b8c611b65565b5b80830191505092915050565b5f60ff82169050919050565b611bae81611b99565b8114611bb8575f5ffd5b50565b5f81359050611bc981611ba5565b92915050565b5f60208284031215611be457611be36115f9565b5b5f611bf184828501611bbb565b91505092915050565b5f8115159050919050565b611c0e81611bfa565b8114611c18575f5ffd5b50565b5f81359050611c2981611c05565b92915050565b5f60208284031215611c4457611c436115f9565b5b5f611c5184828501611c1b565b91505092915050565b5f5f83356001602003843603038112611c7657611c75611b65565b5b80840192508235915067ffffffffffffffff821115611c9857611c97611b69565b5b602083019250600182023603831315611cb457611cb3611b6d565b5b509250929050565b7f4241445f504f4f4c5f54595045000000000000000000000000000000000000005f82015250565b5f611cf0600d83611a58565b9150611cfb82611cbc565b602082019050919050565b5f6020820190508181035f830152611d1d81611ce4565b9050919050565b7f544f54414c5f534c4950504147450000000000000000000000000000000000005f82015250565b5f611d58600e83611a58565b9150611d6382611d24565b602082019050919050565b5f6020820190508181035f830152611d8581611d4c565b9050919050565b5f81519050611d9a816117bc565b92915050565b5f60208284031215611db557611db46115f9565b5b5f611dc284828501611d8c565b91505092915050565b7f5a45524f000000000000000000000000000000000000000000000000000000005f82015250565b5f611dff600483611a58565b9150611e0a82611dcb565b602082019050919050565b5f6020820190508181035f830152611e2c81611df3565b9050919050565b5f604082019050611e465f830185611736565b611e536020830184611843565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f611ec982611e87565b611ed38185611e91565b9350611ee3818560208601611ea1565b611eec81611eaf565b840191505092915050565b5f608082019050611f0a5f830187611843565b611f176020830186611843565b611f246040830185611736565b8181036060830152611f368184611ebf565b905095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611f78826117b3565b9150611f83836117b3565b9250828203905081811115611f9b57611f9a611f41565b5b92915050565b7f56325f534c4950504147450000000000000000000000000000000000000000005f82015250565b5f611fd5600b83611a58565b9150611fe082611fa1565b602082019050919050565b5f6020820190508181035f83015261200281611fc9565b9050919050565b5f60808201905061201c5f830187611736565b6120296020830186611736565b61203660408301856119d5565b6120436060830184611736565b95945050505050565b61205581611bfa565b82525050565b61206481611601565b82525050565b61207381611706565b82525050565b5f60a08201905061208c5f830188611736565b612099602083018761204c565b6120a6604083018661205b565b6120b3606083018561206a565b81810360808301526120c58184611ebf565b90509695505050505050565b5f815190506120df8161160a565b92915050565b5f5f604083850312156120fb576120fa6115f9565b5b5f612108858286016120d1565b9250506020612119858286016120d1565b9150509250929050565b7f56335f504f535f44454c544100000000000000000000000000000000000000005f82015250565b5f612157600c83611a58565b915061216282612123565b602082019050919050565b5f6020820190508181035f8301526121848161214b565b9050919050565b5f61219582611601565b91507f800000000000000000000000000000000000000000000000000000000000000082036121c7576121c6611f41565b5b815f039050919050565b7f56335f534c4950504147450000000000000000000000000000000000000000005f82015250565b5f612205600b83611a58565b9150612210826121d1565b602082019050919050565b5f6020820190508181035f830152612232816121f9565b9050919050565b5f81905092915050565b5f61224d82611e87565b6122578185612239565b9350612267818560208601611ea1565b80840191505092915050565b5f61227e8284612243565b915081905092915050565b7f544f4b5f43414c4c5f4641494c000000000000000000000000000000000000005f82015250565b5f6122bd600d83611a58565b91506122c882612289565b602082019050919050565b5f6020820190508181035f8301526122ea816122b1565b9050919050565b5f815190506122ff81611c05565b92915050565b5f6020828403121561231a576123196115f9565b5b5f612327848285016122f1565b91505092915050565b7f544f4b5f46414c534500000000000000000000000000000000000000000000005f82015250565b5f612364600983611a58565b915061236f82612330565b602082019050919050565b5f6020820190508181035f83015261239181612358565b9050919050565b5f6123a282611706565b91506123ad83611706565b9250828203905073ffffffffffffffffffffffffffffffffffffffff8111156123d9576123d8611f41565b5b92915050565b5f6123e982611706565b91506123f483611706565b9250828201905073ffffffffffffffffffffffffffffffffffffffff8111156124205761241f611f41565b5b92915050565b5f6020828403121561243b5761243a6115f9565b5b5f612448848285016117d2565b91505092915050565b5f5f60408385031215612467576124666115f9565b5b5f6124748582860161195d565b925050602061248585828601611925565b9150509250929050565b61249881611706565b81146124a2575f5ffd5b50565b5f813590506124b38161248f565b92915050565b5f5f5f606084860312156124d0576124cf6115f9565b5b5f6124dd868287016124a5565b93505060206124ee8682870161195d565b92505060406124ff86828701611925565b915050925092509256fea264697066735822122082f554db65517b5d21eae03a3a0958ca8367b28503e90719f9c46672e94ef26464736f6c634300081e0033

Verified Source Code Full Match

Compiler: v0.8.30+commit.73712a01 EVM: prague Optimization: No
RustitrageExecutorOptimized.sol 338 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/*
 * RustitrageExecutorOptimized
 * ------------------------------------------------------------
 * This variant of the original RustitrageExecutor contract makes several
 * changes aimed at reducing gas consumption when executing multi‑hop swaps:
 *
 *  1. The `SwapParams` struct now carries a `zeroForOne` boolean. This
 *     indicates whether the hop swaps token0→token1 (`true`) or the
 *     opposite direction. By supplying this from off‑chain, the executor
 *     avoids reading `token0()`/`token1()` from Uniswap V2/V3 pools at
 *     runtime, saving an external call per hop.
 *  2. The `isAuthorizedFactory` storage mapping and its associated admin
 *     functions have been removed. Performing factory authorisation via
 *     storage reads costs additional gas. Callers should only pass
 *     trustworthy factory addresses in the `extraData` field. In the
 *     V3 callback we still verify the pool address via the factory
 *     interface but do not gate the call behind an allowlist.
 *  3. Loop increments are wrapped in `unchecked` blocks to avoid
 *     redundant overflow checks on the loop counter.
 *  4. Custom errors can be added later to further reduce gas, but for
 *     clarity this example uses brief revert strings.
 */

// ----------------- ERC20 + safe wrappers -----------------
interface IERC20 {
    function balanceOf(address) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
    function transfer(address to, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

library SafeERC20 {
    function _call(address token, bytes memory data) private returns (bytes memory) {
        (bool ok, bytes memory ret) = token.call(data);
        require(ok, "TOK_CALL_FAIL");
        if (ret.length > 0) require(abi.decode(ret, (bool)), "TOK_FALSE");
        return ret;
    }
    function safeTransfer(IERC20 t, address to, uint256 v) internal {
        _call(address(t), abi.encodeWithSelector(t.transfer.selector, to, v));
    }
    function safeTransferFrom(IERC20 t, address f, address to, uint256 v) internal {
        _call(address(t), abi.encodeWithSelector(t.transferFrom.selector, f, to, v));
    }
    function safeApprove(IERC20 t, address s, uint256 v) internal {
        _call(address(t), abi.encodeWithSelector(t.approve.selector, s, v));
    }
}

// ----------------- V2 -----------------
interface IUniswapV2Pair {
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}

// ----------------- V3 -----------------
interface IUniswapV3Pool {
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);
    function token0() external view returns (address);
    function token1() external view returns (address);
}

interface IUniswapV3SwapCallback {
    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
}
interface IPancakeV3SwapCallback {
    function pancakeV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
}
// Factory interface (Uniswap/Pancake style)
interface IV3FactoryLike {
    function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address);
}

// ----------------- DODO (DVM/DPP-like) -----------------
interface IDODOLike {
    function sellBaseToken(uint256 amount, uint256 minReceive, bytes calldata data) external returns (uint256);
    function sellQuoteToken(uint256 amount, uint256 minReceive, bytes calldata data) external returns (uint256);
    function _BASE_TOKEN_() external view returns (address);
    function _QUOTE_TOKEN_() external view returns (address);
}

// ----------------- Ownable (minimal) -----------------
abstract contract Ownable {
    address public owner;
    event OwnershipTransferred(address indexed prev, address indexed next);
    constructor() { owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); }
    modifier onlyOwner() { require(msg.sender == owner, "ONLY_OWNER"); _; }
    function transferOwnership(address next) external onlyOwner { require(next != address(0), "ZERO"); emit OwnershipTransferred(owner, next); owner = next; }
}

// ----------------- Executor -----------------
contract RustitrageExecutorOptimized is IUniswapV3SwapCallback, Ownable,IPancakeV3SwapCallback {
    using SafeERC20 for IERC20;

    // Pool type constants
    uint8 internal constant PT_V2   = 1;
    uint8 internal constant PT_V3   = 2;
    uint8 internal constant PT_DODO = 3;
    // add at top of contract
error UNAUTH_FACTORY();
error BAD_V3_POOL();
error NO_DELTA();

address immutable FACTORY_A; // e.g. Uniswap V3 factory (mainnet)
address immutable FACTORY_B; // e.g. Pancake V3 factory (optional)
address immutable FACTORY_C; // add more if needed


  constructor(address factoryA, address factoryB, address factoryC) {
    FACTORY_A = factoryA;
    FACTORY_B = factoryB;
    FACTORY_C = factoryC;
}

/// @dev pure/view check without storage reads
function _isAllowedFactory(address f) internal view returns (bool) {
    // zero addr means "skip factory check" for legacy hops
    if (f == address(0)) return false; // treat zero as NOT allowed here (we’ll gate separately)
    return (f == FACTORY_A) || (f == FACTORY_B) || (f == FACTORY_C);
}

    /// @notice parameters describing one hop of a multi‑hop swap
    struct SwapParams {
        address tokenIn;
        address tokenOut;
        uint256 amountIn;
        uint256 minAmountOut;
        address pool;
        uint8   poolType;
        bool    zeroForOne;
        bytes   extraData;
    }

    /**
     * @notice Execute a sequence of swaps. The caller is expected to ensure
     *         that the contract holds `hops[0].amountIn` of the first token.
     * @param hops An array of SwapParams describing each hop
     * @param minTotalOut Minimum amount of final output tokens required
     */
    function execute(SwapParams[] calldata hops, uint256 minTotalOut) external onlyOwner returns (uint256 outAmount) {
        require(hops.length > 0, "NO_HOPS");
        uint256 amountIn = hops[0].amountIn;
        for (uint256 i; i < hops.length; ) {
            SwapParams calldata p = hops[i];
            if (p.poolType == PT_V2) {
                amountIn = _swapV2(p.pool, p.tokenIn, p.tokenOut, amountIn, p.minAmountOut, p.zeroForOne);
            } else if (p.poolType == PT_V3) {
                amountIn = _swapV3(p.pool, p.tokenIn, p.tokenOut, amountIn, p.minAmountOut, p.zeroForOne, p.extraData);
            } else {
                revert("BAD_POOL_TYPE");
            }
            unchecked { ++i; }
        }
        outAmount = amountIn;
        require(outAmount >= minTotalOut, "TOTAL_SLIPPAGE");
      
    }

    // --- V2 swap ---
    /**
     * @dev Executes a Uniswap V2 style swap. The `zeroForOne` boolean controls
     *      whether tokenIn is token0 (true) or token1 (false). No external
     *      calls to token0()/token1() are made, so the caller must set
     *      `zeroForOne` correctly. If it is incorrect the swap may revert or
     *      produce the wrong token flow.
     */
    function _swapV2(
        address pair,
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 minOut,
        bool zeroForOne
    ) internal returns (uint256 amountOut) {
        // trust zeroForOne: do not call token0/token1
        uint256 balBefore = IERC20(tokenOut).balanceOf(address(this));
        IERC20(tokenIn).safeTransfer(pair, amountIn);
        uint amount0Out = zeroForOne ? 0 : minOut;
        uint amount1Out = zeroForOne ? minOut : 0;
        // call V2 swap
        IUniswapV2Pair(pair).swap(amount0Out, amount1Out, address(this), new bytes(0));
        // compute balance difference
        // swap returns funds directly, so we can check minOut by reading balance after
        // but reading balance twice is expensive; here we reuse minOut since
        // caller calculates next amountIn based on return value.
        // Strictly, we still read balance to compute amountOut.
        uint256 balAfter = IERC20(tokenOut).balanceOf(address(this));
        amountOut = balAfter - balBefore;
        require(amountOut >= minOut, "V2_SLIPPAGE");
    }

    // --- V3 swap ---
    /**
     * @dev Executes a Uniswap V3 style swap. The caller must supply
     *      zeroForOne to indicate the direction of the swap. The extraData
     *      parameter may contain:
     *        - empty: uses default sqrtPrice limits
     *        - 32 bytes: sqrtPriceLimitX96
     *        - 64 bytes: fee + factory
     *        - 96 bytes: sqrtPriceLimitX96 + fee + factory
     */
    function _swapV3(
        address pool,
        address tokenIn,
        address tokenOut,
        uint256 amountIn,
        uint256 minOut,
        bool zeroForOne,
        bytes calldata extra
    ) internal returns (uint256 amountOut) {
        (uint160 sqrtLimit, uint24 fee, address factory) = _parseV3Extra(extra, zeroForOne);
        bytes memory cb = abi.encode(tokenIn, tokenOut, fee, factory);
        int256 amntIn = int256(amountIn);
        (int256 a0, int256 a1) = IUniswapV3Pool(pool).swap(
            address(this),
            zeroForOne,
            amntIn,
            sqrtLimit,
            cb
        );
        int256 deltaOut = zeroForOne ? a1 : a0;
        require(deltaOut <= 0, "V3_POS_DELTA");
        amountOut = uint256(-deltaOut);
        require(amountOut >= minOut, "V3_SLIPPAGE");
    }

    // Extract sqrtPriceLimit, fee and factory from extra data. See header for details.
    function _parseV3Extra(bytes calldata extra, bool zeroForOne) internal pure returns (uint160 sqrtLimit, uint24 fee, address factory) {
        // default extremes: avoid hitting virtual pool limits
        uint160 defaultLimit = zeroForOne ? (type(uint160).min + 1) : (type(uint160).max - 1);
        sqrtLimit = defaultLimit;
        fee = 0;
        factory = address(0);
        if (extra.length == 0) {
            return (sqrtLimit, fee, factory);
        } else if (extra.length == 32) {
            uint256 raw256 = abi.decode(extra, (uint256));
            uint160 raw = uint160(raw256);
            sqrtLimit = _clampSqrtPriceLimit(raw);
        } else if (extra.length == 64) {
            (fee, factory) = abi.decode(extra, (uint24, address));
        } else if (extra.length == 96) {
            (sqrtLimit, fee, factory) = abi.decode(extra, (uint160, uint24, address));
            sqrtLimit = _clampSqrtPriceLimit(sqrtLimit);
        }
    }

    function _clampSqrtPriceLimit(uint160 x) internal pure returns (uint160) {
        if (x <= 1) return 1;
        if (x >= type(uint160).max) return type(uint160).max - 1;
        return x;
    }

    /**
     * @dev Uniswap V3 callback. Verifies the pool via the provided factory if
     *      one is supplied in extraData. Does not rely on a storage mapping for
     *      factory authorisation to save gas.
     */
function uniswapV3SwapCallback(
    int256 amount0Delta,
    int256 amount1Delta,
    bytes calldata data
) external override {
    if (!(amount0Delta > 0 || amount1Delta > 0)) revert NO_DELTA();

    (address tokenIn, address tokenOut, uint24 fee, address factory)
        = abi.decode(data, (address, address, uint24, address));

    // 1) If factory is supplied, it MUST be whitelisted immutably
    if (factory != address(0)) {
        if (!_isAllowedFactory(factory)) revert UNAUTH_FACTORY();

        // 2) Derive canonical pool from trusted factory and enforce msg.sender
        address expected = IV3FactoryLike(factory).getPool(tokenIn, tokenOut, fee);
        // also ensure pool actually exists
        if (expected == address(0) || msg.sender != expected) revert BAD_V3_POOL();
    } else {
        revert UNAUTH_FACTORY();
    }

    // 3) Pay the correct token to the pool that invoked us
    uint256 amountToPay = uint256(amount0Delta > 0 ? amount0Delta : amount1Delta);

    // These are cheap view calls on the pool; you can avoid one call if you already know zeroForOne
    address t0 = IUniswapV3Pool(msg.sender).token0();
    address payToken = amount0Delta > 0 ? t0 : IUniswapV3Pool(msg.sender).token1();

    IERC20(payToken).safeTransfer(msg.sender, amountToPay);

}
function pancakeV3SwapCallback(
    int256 amount0Delta,
    int256 amount1Delta,
    bytes calldata data
) external override {
    if (!(amount0Delta > 0 || amount1Delta > 0)) revert NO_DELTA();

    (address tokenIn, address tokenOut, uint24 fee, address factory)
        = abi.decode(data, (address, address, uint24, address));

    // 1) If factory is supplied, it MUST be whitelisted immutably
    if (factory != address(0)) {
        if (!_isAllowedFactory(factory)) revert UNAUTH_FACTORY();

        // 2) Derive canonical pool from trusted factory and enforce msg.sender
        address expected = IV3FactoryLike(factory).getPool(tokenIn, tokenOut, fee);
        // also ensure pool actually exists
        if (expected == address(0) || msg.sender != expected) revert BAD_V3_POOL();
    } else {
        revert UNAUTH_FACTORY();
    }

    // 3) Pay the correct token to the pool that invoked us
    uint256 amountToPay = uint256(amount0Delta > 0 ? amount0Delta : amount1Delta);

    // These are cheap view calls on the pool; you can avoid one call if you already know zeroForOne
    address t0 = IUniswapV3Pool(msg.sender).token0();
    address payToken = amount0Delta > 0 ? t0 : IUniswapV3Pool(msg.sender).token1();

    IERC20(payToken).safeTransfer(msg.sender, amountToPay);

}

    // --- Utilities ---
    function sweep(address token, address to) external onlyOwner {
        uint256 bal = IERC20(token).balanceOf(address(this));
        IERC20(token).safeTransfer(to, bal);
    }
}

Read Contract

owner 0x8da5cb5b → address

Write Contract 5 functions

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

execute 0x4bf9906e
tuple[] hops
uint256 minTotalOut
returns: uint256
pancakeV3SwapCallback 0x23a69e75
int256 amount0Delta
int256 amount1Delta
bytes data
sweep 0xb8dc491b
address token
address to
transferOwnership 0xf2fde38b
address next
uniswapV3SwapCallback 0xfa461e33
int256 amount0Delta
int256 amount1Delta
bytes data

Recent Transactions

No transactions found for this address