Address Contract Verified
Address
0x904B5aCb2f784e115555c82B1BefFdD366A6c0F1
Balance
0 ETH
Nonce
1
Code Size
19519 bytes
Creator
0xb64f2Dd7...20cA at tx 0x4622d80e...3668a4
Indexed Transactions
0
Contract Bytecode
19519 bytes
0x6080604052600436106100aa575f3560e01c806391dd73461161006357806391dd7346146101a75780639eaaec9a146101e3578063ca3e07f51461020b578063cd9ea34214610233578063d6b735b51461025d578063e086e5ec14610287576100b1565b80631ff1292f146100b5578063262f85cf146100dd578063688a7ffc14610105578063755e90bd1461012d57806389476069146101555780638da5cb5b1461017d576100b1565b366100b157005b5f5ffd5b3480156100c0575f5ffd5b506100db60048036038101906100d69190612f82565b61029d565b005b3480156100e8575f5ffd5b5061010360048036038101906100fe919061309b565b610349565b005b348015610110575f5ffd5b5061012b60048036038101906101269190613131565b610538565b005b348015610138575f5ffd5b50610153600480360381019061014e919061315c565b610659565b005b348015610160575f5ffd5b5061017b60048036038101906101769190613206565b610915565b005b348015610188575f5ffd5b50610191610bed565b60405161019e9190613240565b60405180910390f35b3480156101b2575f5ffd5b506101cd60048036038101906101c89190613259565b610c11565b6040516101da9190613314565b60405180910390f35b3480156101ee575f5ffd5b5061020960048036038101906102049190613389565b610d23565b005b348015610216575f5ffd5b50610231600480360381019061022c9190613486565b610f5d565b005b34801561023e575f5ffd5b506102476111e1565b60405161025491906135a6565b60405180910390f35b348015610268575f5ffd5b506102716111f3565b60405161027e91906135ce565b60405180910390f35b348015610292575f5ffd5b5061029b6111f9565b005b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461032d57336040517fdccef9640000000000000000000000000000000000000000000000000000000081526004016103249190613240565b60405180910390fd5b8060025f6101000a81548160ff02191690831515021790555050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103d957336040517fdccef9640000000000000000000000000000000000000000000000000000000081526004016103d09190613240565b60405180910390fd5b60015f5414610414576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550610426858383611448565b8573ffffffffffffffffffffffffffffffffffffffff167f591ad3206c771ad9f89e5fce3ba3fd39fe164da7093471fce70eaf468c495f3c8660405161046c91906135ce565b60405180910390a26e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff166348c894918787878787876040516020016104ba96959493929190613621565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016104e59190613314565b5f604051808303815f875af1158015610500573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906105289190613795565b5060015f81905550505050505050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105c857336040517fdccef9640000000000000000000000000000000000000000000000000000000081526004016105bf9190613240565b60405180910390fd5b6103e881111561060f57806040517fb2062bc300000000000000000000000000000000000000000000000000000000815260040161060691906135ce565b60405180910390fd5b5f6001549050816001819055507f369aaa64746f21909173e6b1331c9929562f5d22457e9dead997fec9dfa0b903818360405161064d9291906137dc565b60405180910390a15050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106e957336040517fdccef9640000000000000000000000000000000000000000000000000000000081526004016106e09190613240565b60405180910390fd5b60015f5414610724576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550804211156107725780426040517f1503f5f80000000000000000000000000000000000000000000000000000000081526004016107699291906137dc565b60405180910390fd5b61077d868484611448565b5f61078886866114f3565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146107fc5787816040517f1e843cba0000000000000000000000000000000000000000000000000000000081526004016107f3929190613803565b60405180910390fd5b8773ffffffffffffffffffffffffffffffffffffffff167f591ad3206c771ad9f89e5fce3ba3fd39fe164da7093471fce70eaf468c495f3c8860405161084291906135ce565b60405180910390a26e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff166348c8949160028a8a8a8a8a8a8a604051602001610895989796959493929190613845565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016108c09190613314565b5f604051808303815f875af11580156108db573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906109039190613795565b505060015f8190555050505050505050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109a557336040517fdccef96400000000000000000000000000000000000000000000000000000000815260040161099c9190613240565b60405180910390fd5b5f8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109df9190613240565b602060405180830381865afa1580156109fa573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a1e91906138cf565b90505f8103610a6457816040517fa6f42ee0000000000000000000000000000000000000000000000000000000008152600401610a5b9190613240565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca836040518363ffffffff1660e01b8152600401610abf9291906138fa565b6020604051808303815f875af1158015610adb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aff9190613935565b610b6457817f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca826040517fbf182be8000000000000000000000000000000000000000000000000000000008152600401610b5b93929190613960565b60405180910390fd5b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f892212fefec48d5ab9985161b9e69f149494b9970bd1981c3dbf712d63f0d59c83604051610be191906135ce565b60405180910390a35050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca81565b60606e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ca357336e04444c5dc75cb358380d2e3de08a906040517fb5efcdc3000000000000000000000000000000000000000000000000000000008152600401610c9a929190613803565b60405180910390fd5b5f610cae8484611563565b905060018160ff1611610cca57610cc584846115a3565b610d0b565b60028160ff1603610ce457610cdf848461170e565b610d0a565b60038160ff1603610cfe57610cf984846117d0565b610d09565b610d088484611942565b5b5b5b60405180602001604052805f81525091505092915050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610db357336040517fdccef964000000000000000000000000000000000000000000000000000000008152600401610daa9190613240565b60405180910390fd5b60015f5414610dee576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550610e00898383611448565b5f8686905003610e3c576040517f7b90211900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8973ffffffffffffffffffffffffffffffffffffffff167f591ad3206c771ad9f89e5fce3ba3fd39fe164da7093471fce70eaf468c495f3c8a604051610e8291906135ce565b60405180910390a26e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff166348c8949160018c8c8c8c8c8c8c8c8c8c604051602001610edb9b9a99989796959493929190613d5c565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401610f069190613314565b5f604051808303815f875af1158015610f21573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610f499190613795565b5060015f8190555050505050505050505050565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fed57336040517fdccef964000000000000000000000000000000000000000000000000000000008152600401610fe49190613240565b60405180910390fd5b60015f5414611028576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550804211156110765780426040517f1503f5f800000000000000000000000000000000000000000000000000000000815260040161106d9291906137dc565b60405180910390fd5b6110818a8484611448565b5f87879050036110bd576040517f7b90211900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a73ffffffffffffffffffffffffffffffffffffffff167f591ad3206c771ad9f89e5fce3ba3fd39fe164da7093471fce70eaf468c495f3c8b60405161110391906135ce565b60405180910390a26e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff166348c8949160038d8d8d8d8d8d8d8d8d8d8d60405160200161115e9c9b9a99989796959493929190613df3565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016111899190613314565b5f604051808303815f875af11580156111a4573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906111cc9190613795565b5060015f819055505050505050505050505050565b60025f9054906101000a900460ff1681565b60015481565b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461128957336040517fdccef9640000000000000000000000000000000000000000000000000000000081526004016112809190613240565b60405180910390fd5b5f4790505f81036112d1575f6040517fa6f42ee00000000000000000000000000000000000000000000000000000000081526004016112c89190613240565b60405180910390fd5b5f7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff168260405161131690613ec6565b5f6040518083038185875af1925050503d805f8114611350576040519150601f19603f3d011682016040523d82523d5f602084013e611355565b606091505b50509050806113bf575f7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca836040517fbf182be80000000000000000000000000000000000000000000000000000000081526004016113b693929190613960565b60405180910390fd5b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167f892212fefec48d5ab9985161b9e69f149494b9970bd1981c3dbf712d63f0d59c8460405161143c91906135ce565b60405180910390a35050565b60025f9054906101000a900460ff1615801561146357508282105b156114a75781836040517fd9a6273f00000000000000000000000000000000000000000000000000000000815260040161149e9291906137dc565b60405180910390fd5b6123288111156114ee57806040517fb2062bc30000000000000000000000000000000000000000000000000000000081526004016114e591906135ce565b60405180910390fd5b505050565b5f601483839050101561154057828290506040517fb88a513900000000000000000000000000000000000000000000000000000000815260040161153791906135ce565b60405180910390fd5b5f6014848490506115519190613f07565b90508084013560601c91505092915050565b5f60408383905010156115795760ff905061159d565b5f833590505f815f1c90506003811161159657809250505061159d565b60ff925050505b92915050565b5f5f5f5f5f5f5f88888101906115b99190614279565b9750975097509750975097509750505f5f90505b8451811015611606576115f98582815181106115ec576115eb61437e565b5b6020026020010151611b46565b80806001019150506115cd565b506e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff16630b0d9c098830896040518463ffffffff1660e01b815260040161165393929190614406565b5f604051808303815f87803b15801561166a575f5ffd5b505af115801561167c573d5f5f3e3d5ffd5b505050505f8690505f8651111561169b5761169886825f611d44565b90505b5f5f90505b85518110156116dd576116ce8682815181106116bf576116be61437e565b5b60200260200101518383611ead565b915080806001019150506116a0565b505f845111156116f5576116f284825f611d44565b90505b6117028888838686611fb4565b50505050505050505050565b5f5f5f5f5f5f87878101906117239190614465565b965096509650965096509650506e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff16630b0d9c098730886040518463ffffffff1660e01b815260040161177c93929190614406565b5f604051808303815f87803b158015611793575f5ffd5b505af11580156117a5573d5f5f3e3d5ffd5b505050505f6117b6858786856126d2565b90506117c58787838787611fb4565b505050505050505050565b5f5f5f5f5f5f5f5f89898101906117e7919061451e565b98509850985098509850985098509850505f5f90505b85518110156118365761182986828151811061181c5761181b61437e565b5b6020026020010151611b46565b80806001019150506117fd565b506e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff16630b0d9c0989308a6040518463ffffffff1660e01b815260040161188393929190614406565b5f604051808303815f87803b15801561189a575f5ffd5b505af11580156118ac573d5f5f3e3d5ffd5b505050505f8790505f875111156118cc576118c987825f856126d2565b90505b5f5f90505b865181101561190f576119008782815181106118f0576118ef61437e565b5b602002602001015183838661290e565b915080806001019150506118d1565b505f855111156119285761192585825f856126d2565b90505b6119358989838787611fb4565b5050505050505050505050565b5f5f5f5f5f86868101906119569190614636565b945094509450945094506e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff16630b0d9c098630876040518463ffffffff1660e01b81526004016119ac93929190614406565b5f604051808303815f87803b1580156119c3575f5ffd5b505af11580156119d5573d5f5f3e3d5ffd5b505050508473ffffffffffffffffffffffffffffffffffffffff1663095ea7b37368b3465833fb72a70ecdf485e0e4c7bd8665fc45866040518363ffffffff1660e01b8152600401611a289291906138fa565b6020604051808303815f875af1158015611a44573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a689190613935565b505f7368b3465833fb72a70ecdf485e0e4c7bd8665fc4573ffffffffffffffffffffffffffffffffffffffff1663b858183f60405180608001604052808781526020013073ffffffffffffffffffffffffffffffffffffffff168152602001888152602001868152506040518263ffffffff1660e01b8152600401611aed9190614770565b6020604051808303815f875af1158015611b09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b2d91906138cf565b9050611b3c8686838686611fb4565b5050505050505050565b6002815f0151511080611b5d5750600a815f015151115b15611ba357805f0151516040517fdab51b7b000000000000000000000000000000000000000000000000000000008152600401611b9a91906135ce565b60405180910390fd5b5f5f90505f5f90505b825f015151811015611cf9575f835f01518281518110611bcf57611bce61437e565b5b60200260200101515f01515103611c12576040517f20a2d33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825f01518181518110611c2857611c2761437e565b5b60200260200101516020015161ffff1682611c439190614790565b91505f611c6f845f01518381518110611c5f57611c5e61437e565b5b60200260200101515f0151612a17565b9050836020015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611ceb578360200151816040517fd67efa42000000000000000000000000000000000000000000000000000000008152600401611ce2929190613803565b60405180910390fd5b508080600101915050611bac565b506127108114611d4057806040517f7ce5ae2a000000000000000000000000000000000000000000000000000000008152600401611d3791906135ce565b60405180910390fd5b5050565b5f5f602085015160601c90508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b37368b3465833fb72a70ecdf485e0e4c7bd8665fc45866040518363ffffffff1660e01b8152600401611d9f9291906138fa565b6020604051808303815f875af1158015611dbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ddf9190613935565b507368b3465833fb72a70ecdf485e0e4c7bd8665fc4573ffffffffffffffffffffffffffffffffffffffff1663b858183f60405180608001604052808881526020013073ffffffffffffffffffffffffffffffffffffffff168152602001878152602001868152506040518263ffffffff1660e01b8152600401611e639190614770565b6020604051808303815f875af1158015611e7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ea391906138cf565b9150509392505050565b5f5f5f90505f5f90505b855f015151811015611f6b575f865f01518281518110611eda57611ed961437e565b5b602002602001015190505f6001885f015151611ef69190613f07565b8303611f0f578387611f089190613f07565b9050611f41565b612710826020015161ffff1688611f2691906147c3565b611f309190614831565b90508084611f3e9190614790565b93505b611f4f825f0151825f611d44565b85611f5a9190614790565b945050508080600101915050611eb7565b50827fccd9e96657edea088ab41d207c0da2d19bf034f7fe21da94ae238dfecd332361865f0151518685604051611fa493929190614861565b60405180910390a2509392505050565b7f4d3257edb95914b701655f9bf4b58e4b422017a7b94dad03a20dae00f4b1cbb7848484604051611fe793929190614861565b60405180910390a160025f9054906101000a900460ff1615801561200a57508383105b1561204e5782846040517f2c19b8b80000000000000000000000000000000000000000000000000000000081526004016120459291906137dc565b60405180910390fd5b5f8590506e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff1663a5841194826040518263ffffffff1660e01b815260040161209a9190614896565b5f604051808303815f87803b1580156120b1575f5ffd5b505af11580156120c3573d5f5f3e3d5ffd5b505050508573ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6e04444c5dc75cb358380d2e3de08a90876040518363ffffffff1660e01b81526004016121119291906138fa565b6020604051808303815f875af115801561212d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121519190613935565b6121a557856e04444c5dc75cb358380d2e3de08a90866040517fbf182be800000000000000000000000000000000000000000000000000000000815260040161219c93929190613960565b60405180910390fd5b6e04444c5dc75cb358380d2e3de08a9073ffffffffffffffffffffffffffffffffffffffff166311da60b46040518163ffffffff1660e01b81526004016020604051808303815f875af11580156121fe573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061222291906138cf565b508573ffffffffffffffffffffffffffffffffffffffff167f82f6d0f3da3d1bfe5bc1887cd923de88190c65eb50a9640dce78dc79c83e24248660405161226991906135ce565b60405180910390a2848411156126ca575f85856122869190613f07565b90505f6127106001548861229a91906147c3565b6122a49190614831565b905060025f9054906101000a900460ff161580156122c157508082105b156123055781816040517f4e88422a0000000000000000000000000000000000000000000000000000000081526004016122fc9291906137dc565b60405180910390fd5b5f8290505f8511156125385773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161461239557886040517fd75b5b9600000000000000000000000000000000000000000000000000000000815260040161238c9190613240565b60405180910390fd5b5f61271086856123a591906147c3565b6123af9190614831565b905080846123bd9190613f07565b915073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040161240c91906135ce565b5f604051808303815f87803b158015612423575f5ffd5b505af1158015612435573d5f5f3e3d5ffd5b505050505f4173ffffffffffffffffffffffffffffffffffffffff168260405161245e90613ec6565b5f6040518083038185875af1925050503d805f8114612498576040519150601f19603f3d011682016040523d82523d5f602084013e61249d565b606091505b50509050806124e55741826040517f459429a20000000000000000000000000000000000000000000000000000000081526004016124dc9291906148cf565b60405180910390fd5b4173ffffffffffffffffffffffffffffffffffffffff167f6bc2c2471fd11654297aaf9f411dcbf944df11ed61e6fb7aa4b8ee48c21820f8838560405161252d9291906137dc565b60405180910390a250505b5f811115612641578873ffffffffffffffffffffffffffffffffffffffff1663a9059cbb7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca836040518363ffffffff1660e01b815260040161259b9291906138fa565b6020604051808303815f875af11580156125b7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125db9190613935565b61264057887f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca826040517fbf182be800000000000000000000000000000000000000000000000000000000815260040161263793929190613960565b60405180910390fd5b5b7f000000000000000000000000b64f2dd75803930c5ba0043eab75dde78bf520ca73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167f4b813d5861c80e721479a2f2afbb6184e9dd8d7379578ddd46a6b430dfdb7d00836040516126be91906135ce565b60405180910390a35050505b505050505050565b5f602c8551101561271b5784516040517fb88a513900000000000000000000000000000000000000000000000000000000815260040161271291906135ce565b60405180910390fd5b5f60186014875161272c9190613f07565b61273691906148f6565b146127795784516040517fb88a513900000000000000000000000000000000000000000000000000000000815260040161277091906135ce565b60405180910390fd5b5f8490505f5f90505b86516018826127919190614790565b1015612901575f6127a28883612a7e565b90505f6127bb896014856127b69190614790565b612ae4565b90505f6127d48a6015866127cf9190614790565b612b3c565b90505f6127ed8b6018876127e89190614790565b612a7e565b90505f8b51601880886128009190614790565b61280a9190614790565b1015612816575f612818565b895b90505f60ff168460ff160361283b576128348583858a85612ba2565b96506128e8565b600160ff168460ff16036128725761286b737a250d5630b4cf539739df2c5dacb4c659f2488d86848a858e612d24565b96506128e7565b600260ff168460ff16036128a9576128a273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f86848a858e612d24565b96506128e6565b836040517fdd85b49d0000000000000000000000000000000000000000000000000000000081526004016128dd9190614926565b60405180910390fd5b5b5b6018866128f59190614790565b95505050505050612782565b8192505050949350505050565b5f5f5f90505f5f90505b865f0151518110156129cd575f875f0151828151811061293b5761293a61437e565b5b602002602001015190505f6001895f0151516129579190613f07565b83036129705783886129699190613f07565b90506129a2565b612710826020015161ffff168961298791906147c3565b6129919190614831565b9050808461299f9190614790565b93505b6129b1825f0151825f896126d2565b856129bc9190614790565b945050508080600101915050612918565b50837fccd9e96657edea088ab41d207c0da2d19bf034f7fe21da94ae238dfecd332361875f0151518785604051612a0693929190614861565b60405180910390a250949350505050565b5f601482511015612a605781516040517fb88a5139000000000000000000000000000000000000000000000000000000008152600401612a5791906135ce565b60405180910390fd5b612a778260148451612a729190613f07565b612a7e565b9050919050565b5f8251601483612a8e9190614790565b1115612ad25782516040517fb88a5139000000000000000000000000000000000000000000000000000000008152600401612ac991906135ce565b60405180910390fd5b8160208401015160601c905092915050565b5f82518210612b2b5782516040517fb88a5139000000000000000000000000000000000000000000000000000000008152600401612b2291906135ce565b60405180910390fd5b816020840101515f1a905092915050565b5f8251600383612b4c9190614790565b1115612b905782516040517fb88a5139000000000000000000000000000000000000000000000000000000008152600401612b8791906135ce565b60405180910390fd5b8160208401015160e81c905092915050565b5f8573ffffffffffffffffffffffffffffffffffffffff1663095ea7b37368b3465833fb72a70ecdf485e0e4c7bd8665fc45856040518363ffffffff1660e01b8152600401612bf29291906138fa565b6020604051808303815f875af1158015612c0e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c329190613935565b507368b3465833fb72a70ecdf485e0e4c7bd8665fc4573ffffffffffffffffffffffffffffffffffffffff1663b858183f604051806080016040528089888a604051602001612c83939291906149c6565b60405160208183030381529060405281526020013073ffffffffffffffffffffffffffffffffffffffff168152602001868152602001858152506040518263ffffffff1660e01b8152600401612cd99190614770565b6020604051808303815f875af1158015612cf5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d1991906138cf565b905095945050505050565b5f8573ffffffffffffffffffffffffffffffffffffffff1663095ea7b388866040518363ffffffff1660e01b8152600401612d609291906138fa565b6020604051808303815f875af1158015612d7c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da09190613935565b505f600267ffffffffffffffff811115612dbd57612dbc61367f565b5b604051908082528060200260200182016040528015612deb5781602001602082028036833780820191505090505b50905086815f81518110612e0257612e0161437e565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508581600181518110612e5157612e5061437e565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505f8873ffffffffffffffffffffffffffffffffffffffff166338ed173987878530896040518663ffffffff1660e01b8152600401612ecd959493929190614aaa565b5f604051808303815f875af1158015612ee8573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190612f109190614bc2565b905080600181518110612f2657612f2561437e565b5b6020026020010151925050509695505050505050565b5f604051905090565b5f5ffd5b5f5ffd5b5f8115159050919050565b612f6181612f4d565b8114612f6b575f5ffd5b50565b5f81359050612f7c81612f58565b92915050565b5f60208284031215612f9757612f96612f45565b5b5f612fa484828501612f6e565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612fd682612fad565b9050919050565b612fe681612fcc565b8114612ff0575f5ffd5b50565b5f8135905061300181612fdd565b92915050565b5f819050919050565b61301981613007565b8114613023575f5ffd5b50565b5f8135905061303481613010565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261305b5761305a61303a565b5b8235905067ffffffffffffffff8111156130785761307761303e565b5b60208301915083600182028301111561309457613093613042565b5b9250929050565b5f5f5f5f5f5f60a087890312156130b5576130b4612f45565b5b5f6130c289828a01612ff3565b96505060206130d389828a01613026565b955050604087013567ffffffffffffffff8111156130f4576130f3612f49565b5b61310089828a01613046565b9450945050606061311389828a01613026565b925050608061312489828a01613026565b9150509295509295509295565b5f6020828403121561314657613145612f45565b5b5f61315384828501613026565b91505092915050565b5f5f5f5f5f5f5f60c0888a03121561317757613176612f45565b5b5f6131848a828b01612ff3565b97505060206131958a828b01613026565b965050604088013567ffffffffffffffff8111156131b6576131b5612f49565b5b6131c28a828b01613046565b955095505060606131d58a828b01613026565b93505060806131e68a828b01613026565b92505060a06131f78a828b01613026565b91505092959891949750929550565b5f6020828403121561321b5761321a612f45565b5b5f61322884828501612ff3565b91505092915050565b61323a81612fcc565b82525050565b5f6020820190506132535f830184613231565b92915050565b5f5f6020838503121561326f5761326e612f45565b5b5f83013567ffffffffffffffff81111561328c5761328b612f49565b5b61329885828601613046565b92509250509250929050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6132e6826132a4565b6132f081856132ae565b93506133008185602086016132be565b613309816132cc565b840191505092915050565b5f6020820190508181035f83015261332c81846132dc565b905092915050565b5f5f83601f8401126133495761334861303a565b5b8235905067ffffffffffffffff8111156133665761336561303e565b5b60208301915083602082028301111561338257613381613042565b5b9250929050565b5f5f5f5f5f5f5f5f5f5f60e08b8d0312156133a7576133a6612f45565b5b5f6133b48d828e01612ff3565b9a505060206133c58d828e01613026565b99505060408b013567ffffffffffffffff8111156133e6576133e5612f49565b5b6133f28d828e01613046565b985098505060608b013567ffffffffffffffff81111561341557613414612f49565b5b6134218d828e01613334565b965096505060808b013567ffffffffffffffff81111561344457613443612f49565b5b6134508d828e01613046565b945094505060a06134638d828e01613026565b92505060c06134748d828e01613026565b9150509295989b9194979a5092959850565b5f5f5f5f5f5f5f5f5f5f5f6101008c8e0312156134a6576134a5612f45565b5b5f6134b38e828f01612ff3565b9b505060206134c48e828f01613026565b9a505060408c013567ffffffffffffffff8111156134e5576134e4612f49565b5b6134f18e828f01613046565b995099505060608c013567ffffffffffffffff81111561351457613513612f49565b5b6135208e828f01613334565b975097505060808c013567ffffffffffffffff81111561354357613542612f49565b5b61354f8e828f01613046565b955095505060a06135628e828f01613026565b93505060c06135738e828f01613026565b92505060e06135848e828f01613026565b9150509295989b509295989b9093969950565b6135a081612f4d565b82525050565b5f6020820190506135b95f830184613597565b92915050565b6135c881613007565b82525050565b5f6020820190506135e15f8301846135bf565b92915050565b828183375f83830152505050565b5f61360083856132ae565b935061360d8385846135e7565b613616836132cc565b840190509392505050565b5f60a0820190506136345f830189613231565b61364160208301886135bf565b81810360408301526136548186886135f5565b905061366360608301856135bf565b61367060808301846135bf565b979650505050505050565b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6136b5826132cc565b810181811067ffffffffffffffff821117156136d4576136d361367f565b5b80604052505050565b5f6136e6612f3c565b90506136f282826136ac565b919050565b5f67ffffffffffffffff8211156137115761371061367f565b5b61371a826132cc565b9050602081019050919050565b5f613739613734846136f7565b6136dd565b9050828152602081018484840111156137555761375461367b565b5b6137608482856132be565b509392505050565b5f82601f83011261377c5761377b61303a565b5b815161378c848260208601613727565b91505092915050565b5f602082840312156137aa576137a9612f45565b5b5f82015167ffffffffffffffff8111156137c7576137c6612f49565b5b6137d384828501613768565b91505092915050565b5f6040820190506137ef5f8301856135bf565b6137fc60208301846135bf565b9392505050565b5f6040820190506138165f830185613231565b6138236020830184613231565b9392505050565b5f60ff82169050919050565b61383f8161382a565b82525050565b5f60e0820190506138585f83018b613836565b613865602083018a613231565b61387260408301896135bf565b81810360608301526138858187896135f5565b905061389460808301866135bf565b6138a160a08301856135bf565b6138ae60c08301846135bf565b9998505050505050505050565b5f815190506138c981613010565b92915050565b5f602082840312156138e4576138e3612f45565b5b5f6138f1848285016138bb565b91505092915050565b5f60408201905061390d5f830185613231565b61391a60208301846135bf565b9392505050565b5f8151905061392f81612f58565b92915050565b5f6020828403121561394a57613949612f45565b5b5f61395784828501613921565b91505092915050565b5f6060820190506139735f830186613231565b6139806020830185613231565b61398d60408301846135bf565b949350505050565b5f82825260208201905092915050565b5f819050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126139d6576139d56139b6565b5b83810192508235915060208301925067ffffffffffffffff8211156139fe576139fd6139ae565b5b602082023603831315613a1457613a136139b2565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b5f5f83356001602003843603038112613a5157613a506139b6565b5b83810192508235915060208301925067ffffffffffffffff821115613a7957613a786139ae565b5b600182023603831315613a8f57613a8e6139b2565b5b509250929050565b5f82825260208201905092915050565b5f613ab28385613a97565b9350613abf8385846135e7565b613ac8836132cc565b840190509392505050565b5f61ffff82169050919050565b613ae981613ad3565b8114613af3575f5ffd5b50565b5f81359050613b0481613ae0565b92915050565b5f613b186020840184613af6565b905092915050565b613b2981613ad3565b82525050565b5f60408301613b405f840184613a35565b8583035f870152613b52838284613aa7565b92505050613b636020840184613b0a565b613b706020860182613b20565b508091505092915050565b5f613b868383613b2f565b905092915050565b5f82356001604003833603038112613ba957613ba86139b6565b5b82810191505092915050565b5f602082019050919050565b5f613bcc8385613a1c565b935083602084028501613bde84613a2c565b805f5b87811015613c21578484038952613bf88284613b8e565b613c028582613b7b565b9450613c0d83613bb5565b925060208a01995050600181019050613be1565b50829750879450505050509392505050565b5f613c416020840184612ff3565b905092915050565b613c5281612fcc565b82525050565b5f60408301613c695f8401846139ba565b8583035f870152613c7b838284613bc1565b92505050613c8c6020840184613c33565b613c996020860182613c49565b508091505092915050565b5f613caf8383613c58565b905092915050565b5f82356001604003833603038112613cd257613cd16139b6565b5b82810191505092915050565b5f602082019050919050565b5f613cf58385613995565b935083602084028501613d07846139a5565b805f5b87811015613d4a578484038952613d218284613cb7565b613d2b8582613ca4565b9450613d3683613cde565b925060208a01995050600181019050613d0a565b50829750879450505050509392505050565b5f61010082019050613d705f83018e613597565b613d7d602083018d613231565b613d8a604083018c6135bf565b8181036060830152613d9d818a8c6135f5565b90508181036080830152613db281888a613cea565b905081810360a0830152613dc78186886135f5565b9050613dd660c08301856135bf565b613de360e08301846135bf565b9c9b505050505050505050505050565b5f61012082019050613e075f83018f613836565b613e14602083018e613231565b613e21604083018d6135bf565b8181036060830152613e34818b8d6135f5565b90508181036080830152613e4981898b613cea565b905081810360a0830152613e5e8187896135f5565b9050613e6d60c08301866135bf565b613e7a60e08301856135bf565b613e886101008301846135bf565b9d9c50505050505050505050505050565b5f81905092915050565b50565b5f613eb15f83613e99565b9150613ebc82613ea3565b5f82019050919050565b5f613ed082613ea6565b9150819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613f1182613007565b9150613f1c83613007565b9250828203905081811115613f3457613f33613eda565b5b92915050565b5f613f4482612fad565b9050919050565b613f5481613f3a565b8114613f5e575f5ffd5b50565b5f81359050613f6f81613f4b565b92915050565b5f613f87613f82846136f7565b6136dd565b905082815260208101848484011115613fa357613fa261367b565b5b613fae8482856135e7565b509392505050565b5f82601f830112613fca57613fc961303a565b5b8135613fda848260208601613f75565b91505092915050565b5f67ffffffffffffffff821115613ffd57613ffc61367f565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b5f67ffffffffffffffff8211156140305761402f61367f565b5b602082029050602081019050919050565b5f604082840312156140565761405561400e565b5b61406060406136dd565b90505f82013567ffffffffffffffff81111561407f5761407e614012565b5b61408b84828501613fb6565b5f83015250602061409e84828501613af6565b60208301525092915050565b5f6140bc6140b784614016565b6136dd565b905080838252602082019050602084028301858111156140df576140de613042565b5b835b8181101561412657803567ffffffffffffffff8111156141045761410361303a565b5b8086016141118982614041565b855260208501945050506020810190506140e1565b5050509392505050565b5f82601f8301126141445761414361303a565b5b81356141548482602086016140aa565b91505092915050565b5f604082840312156141725761417161400e565b5b61417c60406136dd565b90505f82013567ffffffffffffffff81111561419b5761419a614012565b5b6141a784828501614130565b5f8301525060206141ba84828501612ff3565b60208301525092915050565b5f6141d86141d384613fe3565b6136dd565b905080838252602082019050602084028301858111156141fb576141fa613042565b5b835b8181101561424257803567ffffffffffffffff8111156142205761421f61303a565b5b80860161422d898261415d565b855260208501945050506020810190506141fd565b5050509392505050565b5f82601f8301126142605761425f61303a565b5b81356142708482602086016141c6565b91505092915050565b5f5f5f5f5f5f5f5f610100898b03121561429657614295612f45565b5b5f6142a38b828c01612f6e565b98505060206142b48b828c01613f61565b97505060406142c58b828c01613026565b965050606089013567ffffffffffffffff8111156142e6576142e5612f49565b5b6142f28b828c01613fb6565b955050608089013567ffffffffffffffff81111561431357614312612f49565b5b61431f8b828c0161424c565b94505060a089013567ffffffffffffffff8111156143405761433f612f49565b5b61434c8b828c01613fb6565b93505060c061435d8b828c01613026565b92505060e061436e8b828c01613026565b9150509295985092959890939650565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b5f6143ce6143c96143c484612fad565b6143ab565b612fad565b9050919050565b5f6143df826143b4565b9050919050565b5f6143f0826143d5565b9050919050565b614400816143e6565b82525050565b5f6060820190506144195f8301866143f7565b6144266020830185613231565b61443360408301846135bf565b949350505050565b6144448161382a565b811461444e575f5ffd5b50565b5f8135905061445f8161443b565b92915050565b5f5f5f5f5f5f5f60e0888a0312156144805761447f612f45565b5b5f61448d8a828b01614451565b975050602061449e8a828b01613f61565b96505060406144af8a828b01613026565b955050606088013567ffffffffffffffff8111156144d0576144cf612f49565b5b6144dc8a828b01613fb6565b94505060806144ed8a828b01613026565b93505060a06144fe8a828b01613026565b92505060c061450f8a828b01613026565b91505092959891949750929550565b5f5f5f5f5f5f5f5f5f6101208a8c03121561453c5761453b612f45565b5b5f6145498c828d01614451565b995050602061455a8c828d01613f61565b985050604061456b8c828d01613026565b97505060608a013567ffffffffffffffff81111561458c5761458b612f49565b5b6145988c828d01613fb6565b96505060808a013567ffffffffffffffff8111156145b9576145b8612f49565b5b6145c58c828d0161424c565b95505060a08a013567ffffffffffffffff8111156145e6576145e5612f49565b5b6145f28c828d01613fb6565b94505060c06146038c828d01613026565b93505060e06146148c828d01613026565b9250506101006146268c828d01613026565b9150509295985092959850929598565b5f5f5f5f5f60a0868803121561464f5761464e612f45565b5b5f61465c88828901613f61565b955050602061466d88828901613026565b945050604086013567ffffffffffffffff81111561468e5761468d612f49565b5b61469a88828901613fb6565b93505060606146ab88828901613026565b92505060806146bc88828901613026565b9150509295509295909350565b5f6146d3826132a4565b6146dd8185613a97565b93506146ed8185602086016132be565b6146f6816132cc565b840191505092915050565b61470a81613007565b82525050565b5f608083015f8301518482035f86015261472a82826146c9565b915050602083015161473f6020860182613c49565b5060408301516147526040860182614701565b5060608301516147656060860182614701565b508091505092915050565b5f6020820190508181035f8301526147888184614710565b905092915050565b5f61479a82613007565b91506147a583613007565b92508282019050808211156147bd576147bc613eda565b5b92915050565b5f6147cd82613007565b91506147d883613007565b92508282026147e681613007565b915082820484148315176147fd576147fc613eda565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61483b82613007565b915061484683613007565b92508261485657614855614804565b5b828204905092915050565b5f6060820190506148745f8301866135bf565b61488160208301856135bf565b61488e60408301846135bf565b949350505050565b5f6020820190506148a95f8301846143f7565b92915050565b5f6148b9826143d5565b9050919050565b6148c9816148af565b82525050565b5f6040820190506148e25f8301856148c0565b6148ef60208301846135bf565b9392505050565b5f61490082613007565b915061490b83613007565b92508261491b5761491a614804565b5b828206905092915050565b5f6020820190506149395f830184613836565b92915050565b5f8160601b9050919050565b5f6149558261493f565b9050919050565b5f6149668261494b565b9050919050565b61497e61497982612fcc565b61495c565b82525050565b5f62ffffff82169050919050565b5f8160e81b9050919050565b5f6149a882614992565b9050919050565b6149c06149bb82614984565b61499e565b82525050565b5f6149d1828661496d565b6014820191506149e182856149af565b6003820191506149f1828461496d565b601482019150819050949350505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f614a368383613c49565b60208301905092915050565b5f602082019050919050565b5f614a5882614a02565b614a628185614a0c565b9350614a6d83614a1c565b805f5b83811015614a9d578151614a848882614a2b565b9750614a8f83614a42565b925050600181019050614a70565b5085935050505092915050565b5f60a082019050614abd5f8301886135bf565b614aca60208301876135bf565b8181036040830152614adc8186614a4e565b9050614aeb6060830185613231565b614af860808301846135bf565b9695505050505050565b5f67ffffffffffffffff821115614b1c57614b1b61367f565b5b602082029050602081019050919050565b5f614b3f614b3a84614b02565b6136dd565b90508083825260208201905060208402830185811115614b6257614b61613042565b5b835b81811015614b8b5780614b7788826138bb565b845260208401935050602081019050614b64565b5050509392505050565b5f82601f830112614ba957614ba861303a565b5b8151614bb9848260208601614b2d565b91505092915050565b5f60208284031215614bd757614bd6612f45565b5b5f82015167ffffffffffffffff811115614bf457614bf3612f49565b5b614c0084828501614b95565b9150509291505056fea264697066735822122072573795afda81b089d6da1620c46b34410f278ef7c783b160ad9b5eb698e58864736f6c63430008210033
Verified Source Code Full Match
Compiler: v0.8.33+commit.64118f21
EVM: osaka
Optimization: No
Flash3LegsSecureV4.sol 691 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
// =============================================================================
// ADDRESSES
// =============================================================================
address constant UNISWAP_V4_POOL_MANAGER = 0x000000000004444c5dc75cB358380D2e3dE08A90;
address constant SWAP_ROUTER_02 = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45;
address constant SWAP_ROUTER_V2 = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address constant SUSHISWAP_ROUTER = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F;
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
/**
* @title UniswapV4FlashLoanArbitrage
* @notice V4 flash loans (zero fee) + V3/V2/Sushi multi-DEX swaps
* @dev VERSION: 3.4.0 (size-optimized)
*/
contract UniswapV4FlashLoanArbitrage {
struct ForkBranch {
bytes path;
uint16 proportionBps;
}
struct ForkPoint {
ForkBranch[] branches;
address convergenceToken;
}
// =============================================================================
// STATE
// =============================================================================
address public immutable owner;
IPoolManager private constant poolManager = IPoolManager(UNISWAP_V4_POOL_MANAGER);
ISwapRouter02 private constant router = ISwapRouter02(SWAP_ROUTER_02);
uint256 private _locked = 1;
uint256 public minProfitBasisPoints = 10;
bool public testMode = false;
uint256 private constant BASIS_POINTS = 10000;
uint256 private constant HOP_SIZE = 24;
uint8 private constant DEX_V3 = 0;
uint8 private constant DEX_V2 = 1;
uint8 private constant DEX_SUSHI = 2;
// =============================================================================
// EVENTS
// =============================================================================
event FlashLoanInitiated(address indexed token, uint256 amount);
event SwapExecuted(uint256 amountIn, uint256 amountOut, uint256 slippageProtection);
event FlashLoanRepaid(address indexed token, uint256 amount);
event ProfitRealized(address indexed token, uint256 profit, address indexed recipient);
event TokensWithdrawn(address indexed token, uint256 amount, address indexed recipient);
event MinProfitUpdated(uint256 oldValue, uint256 newValue);
event ForkExecuted(uint256 indexed forkIndex, uint256 branchCount, uint256 inputAmount, uint256 outputAmount);
event BuilderTipPaid(address indexed builder, uint256 tipAmount, uint256 profitAfterTip);
// =============================================================================
// ERRORS
// =============================================================================
error UnauthorizedAccess(address caller);
error InvalidCallback(address caller, address expected);
error InsufficientOutput(uint256 actual, uint256 required);
error InsufficientProfit(uint256 actual, uint256 minimum);
error NoTokensToWithdraw(address token);
error InvalidProfitThreshold(uint256 bps);
error InvalidSlippage(uint256 minOutput, uint256 payback);
error TransferFailed(address token, address to, uint256 amount);
error ReentrancyDetected();
error InvalidProportions(uint256 totalBps);
error InvalidBranchCount(uint256 count);
error InvalidConvergenceToken(address expected, address actual);
error EmptyPath();
error PathTooShort(uint256 length);
error NoForkPoints();
error CoinbasePaymentFailed(address coinbase, uint256 amount);
error CoinbasePaymentRequiresWETH(address actualToken);
error InvalidDexType(uint8 dexType);
error DeadlineExpired(uint256 deadline, uint256 currentTime);
error PathNotCircular(address flashToken, address finalToken);
// =============================================================================
// CONSTRUCTOR & MODIFIERS
// =============================================================================
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
if (msg.sender != owner) revert UnauthorizedAccess(msg.sender);
_;
}
modifier nonReentrant() {
if (_locked != 1) revert ReentrancyDetected();
_locked = 2;
_;
_locked = 1;
}
// =============================================================================
// ENTRY POINTS
// =============================================================================
function executeFlashLoanArbitrage(
address flashToken,
uint256 flashAmount,
bytes calldata encodedPath,
uint256 minAmountOut,
uint256 tipBps
) external onlyOwner nonReentrant {
_validateEntry(flashAmount, minAmountOut, tipBps);
emit FlashLoanInitiated(flashToken, flashAmount);
poolManager.unlock(abi.encode(flashToken, flashAmount, encodedPath, minAmountOut, tipBps));
}
function executeFlashLoanArbitrageWithForks(
address flashToken,
uint256 flashAmount,
bytes calldata preForkPath,
ForkPoint[] calldata forkPoints,
bytes calldata postForkPath,
uint256 minAmountOut,
uint256 tipBps
) external onlyOwner nonReentrant {
_validateEntry(flashAmount, minAmountOut, tipBps);
if (forkPoints.length == 0) revert NoForkPoints();
emit FlashLoanInitiated(flashToken, flashAmount);
poolManager.unlock(abi.encode(
true, flashToken, flashAmount, preForkPath, forkPoints, postForkPath, minAmountOut, tipBps
));
}
function executeFlashLoanArbitrageMultiDex(
address flashToken,
uint256 flashAmount,
bytes calldata encodedPath,
uint256 minAmountOut,
uint256 tipBps,
uint256 deadline
) external onlyOwner nonReentrant {
if (block.timestamp > deadline) revert DeadlineExpired(deadline, block.timestamp);
_validateEntry(flashAmount, minAmountOut, tipBps);
address finalToken = _extractLastTokenCalldata(encodedPath);
if (finalToken != flashToken) revert PathNotCircular(flashToken, finalToken);
emit FlashLoanInitiated(flashToken, flashAmount);
poolManager.unlock(abi.encode(
uint8(2), flashToken, flashAmount, encodedPath, minAmountOut, tipBps, deadline
));
}
function executeFlashLoanArbitrageMultiDexWithForks(
address flashToken,
uint256 flashAmount,
bytes calldata preForkPath,
ForkPoint[] calldata forkPoints,
bytes calldata postForkPath,
uint256 minAmountOut,
uint256 tipBps,
uint256 deadline
) external onlyOwner nonReentrant {
if (block.timestamp > deadline) revert DeadlineExpired(deadline, block.timestamp);
_validateEntry(flashAmount, minAmountOut, tipBps);
if (forkPoints.length == 0) revert NoForkPoints();
emit FlashLoanInitiated(flashToken, flashAmount);
poolManager.unlock(abi.encode(
uint8(3), flashToken, flashAmount, preForkPath, forkPoints, postForkPath,
minAmountOut, tipBps, deadline
));
}
function _validateEntry(uint256 flashAmount, uint256 minAmountOut, uint256 tipBps) private view {
if (!testMode && minAmountOut < flashAmount) revert InvalidSlippage(minAmountOut, flashAmount);
if (tipBps > 9000) revert InvalidProfitThreshold(tipBps);
}
// =============================================================================
// V4 UNLOCK CALLBACK
// =============================================================================
function unlockCallback(bytes calldata data) external returns (bytes memory) {
if (msg.sender != address(poolManager)) {
revert InvalidCallback(msg.sender, address(poolManager));
}
uint8 callbackType = _getCallbackType(data);
if (callbackType <= 1) {
_executeForkArbitrage(data);
} else if (callbackType == 2) {
_executeSimpleArbitrageMultiDex(data);
} else if (callbackType == 3) {
_executeForkArbitrageMultiDex(data);
} else {
_executeSimpleArbitrage(data);
}
return "";
}
// =============================================================================
// SHARED SETTLE + PROFIT DISTRIBUTION
// =============================================================================
function _settleAndDistribute(
address flashToken,
uint256 flashAmount,
uint256 amountOut,
uint256 minAmountOut,
uint256 tipBps
) private {
emit SwapExecuted(flashAmount, amountOut, minAmountOut);
if (!testMode && amountOut < flashAmount) {
revert InsufficientOutput(amountOut, flashAmount);
}
// Settle debt to V4
Currency currency = Currency.wrap(flashToken);
poolManager.sync(currency);
if (!IERC20(flashToken).transfer(address(poolManager), flashAmount)) {
revert TransferFailed(flashToken, address(poolManager), flashAmount);
}
poolManager.settle();
emit FlashLoanRepaid(flashToken, flashAmount);
// Distribute profit
if (amountOut > flashAmount) {
uint256 profit = amountOut - flashAmount;
uint256 minProfit = (flashAmount * minProfitBasisPoints) / BASIS_POINTS;
if (!testMode && profit < minProfit) {
revert InsufficientProfit(profit, minProfit);
}
uint256 ownerProfit = profit;
// Pay builder tip if specified (requires WETH)
if (tipBps > 0) {
if (flashToken != WETH) revert CoinbasePaymentRequiresWETH(flashToken);
uint256 tipAmount = (profit * tipBps) / BASIS_POINTS;
ownerProfit = profit - tipAmount;
IWETH(WETH).withdraw(tipAmount);
(bool tipSuccess, ) = block.coinbase.call{value: tipAmount}("");
if (!tipSuccess) revert CoinbasePaymentFailed(block.coinbase, tipAmount);
emit BuilderTipPaid(block.coinbase, tipAmount, ownerProfit);
}
if (ownerProfit > 0) {
if (!IERC20(flashToken).transfer(owner, ownerProfit)) {
revert TransferFailed(flashToken, owner, ownerProfit);
}
}
emit ProfitRealized(flashToken, ownerProfit, owner);
}
}
// =============================================================================
// EXECUTION LOGIC
// =============================================================================
function _executeSimpleArbitrage(bytes calldata data) private {
(
address flashToken,
uint256 flashAmount,
bytes memory encodedPath,
uint256 minAmountOut,
uint256 tipBps
) = abi.decode(data, (address, uint256, bytes, uint256, uint256));
poolManager.take(Currency.wrap(flashToken), address(this), flashAmount);
IERC20(flashToken).approve(address(router), flashAmount);
uint256 amountOut = router.exactInput(ISwapRouter02.ExactInputParams({
path: encodedPath,
recipient: address(this),
amountIn: flashAmount,
amountOutMinimum: minAmountOut
}));
_settleAndDistribute(flashToken, flashAmount, amountOut, minAmountOut, tipBps);
}
function _executeForkArbitrage(bytes calldata data) private {
(
,
address flashToken,
uint256 flashAmount,
bytes memory preForkPath,
ForkPoint[] memory forkPoints,
bytes memory postForkPath,
uint256 minAmountOut,
uint256 tipBps
) = abi.decode(data, (bool, address, uint256, bytes, ForkPoint[], bytes, uint256, uint256));
// Re-validate fork points in callback
for (uint256 i = 0; i < forkPoints.length; i++) {
_validateForkPoint(forkPoints[i]);
}
poolManager.take(Currency.wrap(flashToken), address(this), flashAmount);
uint256 currentAmount = flashAmount;
if (preForkPath.length > 0) {
currentAmount = _executeV3SwapPath(preForkPath, currentAmount, 0);
}
for (uint256 i = 0; i < forkPoints.length; i++) {
currentAmount = _executeForkPointV3(forkPoints[i], currentAmount, i);
}
if (postForkPath.length > 0) {
currentAmount = _executeV3SwapPath(postForkPath, currentAmount, 0);
}
_settleAndDistribute(flashToken, flashAmount, currentAmount, minAmountOut, tipBps);
}
function _executeSimpleArbitrageMultiDex(bytes calldata data) private {
(
,
address flashToken,
uint256 flashAmount,
bytes memory encodedPath,
uint256 minAmountOut,
uint256 tipBps,
uint256 deadline
) = abi.decode(data, (uint8, address, uint256, bytes, uint256, uint256, uint256));
poolManager.take(Currency.wrap(flashToken), address(this), flashAmount);
uint256 amountOut = _executeMultiDexPath(encodedPath, flashAmount, minAmountOut, deadline);
_settleAndDistribute(flashToken, flashAmount, amountOut, minAmountOut, tipBps);
}
function _executeForkArbitrageMultiDex(bytes calldata data) private {
(
,
address flashToken,
uint256 flashAmount,
bytes memory preForkPath,
ForkPoint[] memory forkPoints,
bytes memory postForkPath,
uint256 minAmountOut,
uint256 tipBps,
uint256 deadline
) = abi.decode(data, (uint8, address, uint256, bytes, ForkPoint[], bytes, uint256, uint256, uint256));
// Re-validate fork points in callback
for (uint256 i = 0; i < forkPoints.length; i++) {
_validateForkPoint(forkPoints[i]);
}
poolManager.take(Currency.wrap(flashToken), address(this), flashAmount);
uint256 currentAmount = flashAmount;
if (preForkPath.length > 0) {
currentAmount = _executeMultiDexPath(preForkPath, currentAmount, 0, deadline);
}
for (uint256 i = 0; i < forkPoints.length; i++) {
currentAmount = _executeForkPointMultiDex(forkPoints[i], currentAmount, i, deadline);
}
if (postForkPath.length > 0) {
currentAmount = _executeMultiDexPath(postForkPath, currentAmount, 0, deadline);
}
_settleAndDistribute(flashToken, flashAmount, currentAmount, minAmountOut, tipBps);
}
// =============================================================================
// FORK VALIDATION (unified)
// =============================================================================
/// @dev Works for both V3 and multiDex paths since both end with a 20-byte token
function _validateForkPoint(ForkPoint memory forkPoint) private pure {
if (forkPoint.branches.length < 2 || forkPoint.branches.length > 10) {
revert InvalidBranchCount(forkPoint.branches.length);
}
uint256 totalBps = 0;
for (uint256 i = 0; i < forkPoint.branches.length; i++) {
if (forkPoint.branches[i].path.length == 0) revert EmptyPath();
totalBps += forkPoint.branches[i].proportionBps;
address branchEndToken = _extractLastToken(forkPoint.branches[i].path);
if (branchEndToken != forkPoint.convergenceToken) {
revert InvalidConvergenceToken(forkPoint.convergenceToken, branchEndToken);
}
}
if (totalBps != BASIS_POINTS) revert InvalidProportions(totalBps);
}
// =============================================================================
// FORK EXECUTION
// =============================================================================
function _executeForkPointV3(
ForkPoint memory forkPoint,
uint256 amountIn,
uint256 forkIndex
) private returns (uint256 totalOutput) {
uint256 totalDistributed = 0;
for (uint256 i = 0; i < forkPoint.branches.length; i++) {
ForkBranch memory branch = forkPoint.branches[i];
uint256 branchAmount;
if (i == forkPoint.branches.length - 1) {
branchAmount = amountIn - totalDistributed;
} else {
branchAmount = (amountIn * branch.proportionBps) / BASIS_POINTS;
totalDistributed += branchAmount;
}
totalOutput += _executeV3SwapPath(branch.path, branchAmount, 0);
}
emit ForkExecuted(forkIndex, forkPoint.branches.length, amountIn, totalOutput);
}
function _executeForkPointMultiDex(
ForkPoint memory forkPoint,
uint256 amountIn,
uint256 forkIndex,
uint256 deadline
) private returns (uint256 totalOutput) {
uint256 totalDistributed = 0;
for (uint256 i = 0; i < forkPoint.branches.length; i++) {
ForkBranch memory branch = forkPoint.branches[i];
uint256 branchAmount;
if (i == forkPoint.branches.length - 1) {
branchAmount = amountIn - totalDistributed;
} else {
branchAmount = (amountIn * branch.proportionBps) / BASIS_POINTS;
totalDistributed += branchAmount;
}
totalOutput += _executeMultiDexPath(branch.path, branchAmount, 0, deadline);
}
emit ForkExecuted(forkIndex, forkPoint.branches.length, amountIn, totalOutput);
}
// =============================================================================
// SWAP EXECUTION
// =============================================================================
function _executeV3SwapPath(
bytes memory path,
uint256 amountIn,
uint256 minAmountOut
) private returns (uint256 amountOut) {
address tokenIn;
assembly {
tokenIn := shr(96, mload(add(path, 32)))
}
IERC20(tokenIn).approve(address(router), amountIn);
amountOut = router.exactInput(ISwapRouter02.ExactInputParams({
path: path,
recipient: address(this),
amountIn: amountIn,
amountOutMinimum: minAmountOut
}));
}
function _executeMultiDexPath(
bytes memory path,
uint256 amountIn,
uint256 minAmountOut,
uint256 deadline
) private returns (uint256 amountOut) {
if (path.length < 44) revert PathTooShort(path.length);
if ((path.length - 20) % HOP_SIZE != 0) revert PathTooShort(path.length);
uint256 currentAmount = amountIn;
uint256 offset = 0;
while (offset + HOP_SIZE < path.length) {
address tokenIn = _extractTokenAt(path, offset);
uint8 dexType = _extractDexTypeAt(path, offset + 20);
uint24 fee = _extractFeeAt(path, offset + 21);
address tokenOut = _extractTokenAt(path, offset + HOP_SIZE);
// Only enforce minAmountOut on last hop
uint256 hopMinOut = (offset + HOP_SIZE + HOP_SIZE >= path.length) ? minAmountOut : 0;
if (dexType == DEX_V3) {
currentAmount = _swapV3Single(tokenIn, tokenOut, fee, currentAmount, hopMinOut);
} else if (dexType == DEX_V2) {
currentAmount = _swapV2Style(SWAP_ROUTER_V2, tokenIn, tokenOut, currentAmount, hopMinOut, deadline);
} else if (dexType == DEX_SUSHI) {
currentAmount = _swapV2Style(SUSHISWAP_ROUTER, tokenIn, tokenOut, currentAmount, hopMinOut, deadline);
} else {
revert InvalidDexType(dexType);
}
offset += HOP_SIZE;
}
return currentAmount;
}
function _swapV3Single(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint256 minAmountOut
) private returns (uint256 amountOut) {
IERC20(tokenIn).approve(address(router), amountIn);
amountOut = router.exactInput(ISwapRouter02.ExactInputParams({
path: abi.encodePacked(tokenIn, fee, tokenOut),
recipient: address(this),
amountIn: amountIn,
amountOutMinimum: minAmountOut
}));
}
/// @dev Unified V2/SushiSwap swap - they share the same router interface
function _swapV2Style(
address routerAddr,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minAmountOut,
uint256 deadline
) private returns (uint256 amountOut) {
IERC20(tokenIn).approve(routerAddr, amountIn);
address[] memory path = new address[](2);
path[0] = tokenIn;
path[1] = tokenOut;
uint256[] memory amounts = IUniswapV2Router02(routerAddr).swapExactTokensForTokens(
amountIn, minAmountOut, path, address(this), deadline
);
amountOut = amounts[1];
}
// =============================================================================
// PATH EXTRACTION HELPERS
// =============================================================================
function _extractTokenAt(bytes memory path, uint256 offset) private pure returns (address token) {
if (offset + 20 > path.length) revert PathTooShort(path.length);
assembly {
token := shr(96, mload(add(add(path, 32), offset)))
}
}
function _extractLastToken(bytes memory path) private pure returns (address) {
if (path.length < 20) revert PathTooShort(path.length);
return _extractTokenAt(path, path.length - 20);
}
function _extractLastTokenCalldata(bytes calldata path) private pure returns (address tokenAddress) {
if (path.length < 20) revert PathTooShort(path.length);
uint256 lastTokenOffset = path.length - 20;
assembly {
tokenAddress := shr(96, calldataload(add(path.offset, lastTokenOffset)))
}
}
function _extractDexTypeAt(bytes memory path, uint256 offset) private pure returns (uint8 dexType) {
if (offset >= path.length) revert PathTooShort(path.length);
assembly {
dexType := byte(0, mload(add(add(path, 32), offset)))
}
}
function _extractFeeAt(bytes memory path, uint256 offset) private pure returns (uint24 fee) {
if (offset + 3 > path.length) revert PathTooShort(path.length);
assembly {
fee := shr(232, mload(add(add(path, 32), offset)))
}
}
function _getCallbackType(bytes calldata data) private pure returns (uint8) {
if (data.length < 64) return 255;
bytes32 firstWord;
assembly {
firstWord := calldataload(data.offset)
}
uint256 val = uint256(firstWord);
if (val <= 3) return uint8(val);
return 255;
}
// =============================================================================
// ADMIN FUNCTIONS
// =============================================================================
function withdrawToken(address token) external onlyOwner {
uint256 balance = IERC20(token).balanceOf(address(this));
if (balance == 0) revert NoTokensToWithdraw(token);
if (!IERC20(token).transfer(owner, balance)) {
revert TransferFailed(token, owner, balance);
}
emit TokensWithdrawn(token, balance, owner);
}
function setMinProfitBasisPoints(uint256 bps) external onlyOwner {
if (bps > 1000) revert InvalidProfitThreshold(bps);
uint256 oldValue = minProfitBasisPoints;
minProfitBasisPoints = bps;
emit MinProfitUpdated(oldValue, bps);
}
function setTestMode(bool enabled) external onlyOwner {
testMode = enabled;
}
function withdrawETH() external onlyOwner {
uint256 balance = address(this).balance;
if (balance == 0) revert NoTokensToWithdraw(address(0));
(bool success, ) = owner.call{value: balance}("");
if (!success) revert TransferFailed(address(0), owner, balance);
emit TokensWithdrawn(address(0), balance, owner);
}
receive() external payable {}
}
// =============================================================================
// INTERFACES
// =============================================================================
interface IPoolManager {
function unlock(bytes calldata data) external returns (bytes memory);
function take(Currency currency, address to, uint256 amount) external;
function sync(Currency currency) external;
function settle() external payable returns (uint256);
}
type Currency is address;
interface ISwapRouter02 {
struct ExactInputParams {
bytes path;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params)
external
payable
returns (uint256 amountOut);
}
interface IUniswapV2Router02 {
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
}
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
}
interface IWETH {
function deposit() external payable;
function withdraw(uint256 amount) external;
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
}
Read Contract
minProfitBasisPoints 0xd6b735b5 → uint256
owner 0x8da5cb5b → address
testMode 0xcd9ea342 → bool
Write Contract 9 functions
These functions modify contract state and require a wallet transaction to execute.
executeFlashLoanArbitrage 0x262f85cf
address flashToken
uint256 flashAmount
bytes encodedPath
uint256 minAmountOut
uint256 tipBps
executeFlashLoanArbitrageMultiDex 0x755e90bd
address flashToken
uint256 flashAmount
bytes encodedPath
uint256 minAmountOut
uint256 tipBps
uint256 deadline
executeFlashLoanArbitrageMultiDexWithForks 0x6ab16db9
address flashToken
uint256 flashAmount
bytes preForkPath
tuple[] forkPoints
bytes postForkPath
uint256 minAmountOut
uint256 tipBps
uint256 deadline
executeFlashLoanArbitrageWithForks 0x90445433
address flashToken
uint256 flashAmount
bytes preForkPath
tuple[] forkPoints
bytes postForkPath
uint256 minAmountOut
uint256 tipBps
setMinProfitBasisPoints 0x688a7ffc
uint256 bps
setTestMode 0x1ff1292f
bool enabled
unlockCallback 0x91dd7346
bytes data
returns: bytes
withdrawETH 0xe086e5ec
No parameters
withdrawToken 0x89476069
address token
Recent Transactions
No transactions found for this address