Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0xbc3Fc959FeF3F12a41738f406c02198cdeE7481F
Balance 0 ETH
Nonce 1
Code Size 15293 bytes
Indexed Transactions 0 (1 on-chain, 1.6% indexed)
External Etherscan · Sourcify

Contract Bytecode

15293 bytes
Copy Bytecode
0x608060405260043610610062575f3560e01c80638cedca71116100415780638cedca71146100a1578063921daec0146100e4578063c579d490146100f7575f80fd5b80623316b6146100665780630c2c87501461007b578063422fa60c1461008e575b5f80fd5b6100796100743660046126b0565b610116565b005b6100796100893660046126fc565b61042a565b61007961009c366004612a1e565b610439565b3480156100ac575f80fd5b506100c873ccf3d848e08b94478ed8f46ffead3008faf581fd81565b6040516001600160a01b03909116815260200160405180910390f35b6100796100f2366004612b34565b6106f3565b348015610102575f80fd5b50610079610111366004612b8a565b6107bc565b6040517f93b188540000000000000000000000000000000000000000000000000000000081527f91bfbd870000000000000000000000000000000000000000000000000000000060048201525f9073287778f121f134c66212fb16c9b53ec991d32f5b906393b1885490602401602060405180830381865afa15801561019e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101c29190612bd8565b9050336001600160a01b0382161461020d576040517fc45d9b2e0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b61021d60a0830160808401612bf3565b156102385761023361022e84612d98565b6108e5565b505050565b5f80826001600160a01b031663b0ade5d26040518163ffffffff1660e01b81526004015f60405180830381865afa158015610275573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261029c9190810190612ed1565b8060200190518101906102af9190612f03565b50915091506102c18561022e90612d98565b815f036102cf575050505050565b5f6102ef836102e46040880160208901613032565b876040013585610ac1565b90508435811115610336576040517fe0d316950000000000000000000000000000000000000000000000000000000081528535600482015260248101829052604401610204565b5f306001600160a01b031663a0e67e2b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610372573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261039991908101906130b2565b905080516001036103e7576103e5815f815181106103b9576103b96130e4565b6020026020010151838860200160208101906103d59190613032565b6001600160a01b03169190610bcb565b505b610420730ed7f3223266ca1694f85c23abe06e614af3a4798361041060408a0160208b01613032565b6001600160a01b03169190610c57565b5050505050505050565b61043661022e82612d98565b50565b61047b6040518060c00160405280606081526020015f6001600160a01b031681526020016060815260200160608152602001606081526020015f151581525090565b8151602083015167ffffffffffffffff9091169015610529576040517fe7560f0a000000000000000000000000000000000000000000000000000000008152600481018290526024810185905273223c6ade533851df03219f6e3d8b763bd47f84cf9063e7560f0a90604401602060405180830381865afa158015610502573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052691906130f8565b90505b6040517fcfc0cc340000000000000000000000000000000000000000000000000000000081526004810182905273f52551f95ec4a2b4299dcc42fbbc576718dbf9339063cfc0cc34906024015f60405180830381865afa15801561058f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105b69190810190613256565b9150505f806105dd838589898e731612fc28ee0ab882ec99842cde0fc77ff0691e90610d83565b915091508161061b576040517fdcc0991a00000000000000000000000000000000000000000000000000000000815260048101829052602401610204565b8260a0015161069e576040517fe33cace6000000000000000000000000000000000000000000000000000000008152600481018b9052731612fc28ee0ab882ec99842cde0fc77ff0691e909063e33cace6906024015f604051808303815f87803b158015610687575f80fd5b505af1158015610699573d5f803e3d5ffd5b505050505b6040805160a08101909152835181525f90602081016106bd8b8d613349565b81526060808801516020830152868101516040830152608087015191015290506106e6816108e5565b5050505050505050505050565b5f6107016060840184613355565b905067ffffffffffffffff81111561071b5761071b612776565b604051908082528060200260200182016040528015610744578160200160208202803683370190505b50905081815f8151811061075a5761075a6130e4565b602090810291909101015260015b6107756060850185613355565b90508110156107b65761079161078a85612d98565b82846110a9565b8282815181106107a3576107a36130e4565b6020908102919091010152600101610768565b50505050565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610816573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061083a9190612bd8565b6001600160a01b03161461087a576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee036108d1576040516001600160a01b0383169082156108fc029083905f818181858888f193505050501580156107b6573d5f803e3d5ffd5b6102336001600160a01b038416838361120f565b5f73287778f121f134c66212fb16c9b53ec991d32f5b6001600160a01b03166393b1885483606001515f8151811061091f5761091f6130e4565b60200260200101516040518263ffffffff1660e01b815260040161095391906001600160e01b031991909116815260200190565b602060405180830381865afa15801561096e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109929190612bd8565b90505f82606001515167ffffffffffffffff8111156109b3576109b3612776565b6040519080825280602002602001820160405280156109dc578160200160208202803683370190505b5090506109e8826112a0565b156109fd576109f883838361130f565b610a3e565b5f5b836060015151811015610a3c57610a178482846110a9565b828281518110610a2957610a296130e4565b60209081029190910101526001016109ff565b505b82516040517f05fedae500000000000000000000000000000000000000000000000000000000815273ce7a977cac4a481bc84ac06b2da0df614e621cf3916305fedae591610a8f91906004016133c6565b5f604051808303815f87803b158015610aa6575f80fd5b505af1158015610ab8573d5f803e3d5ffd5b50505050505050565b5f45851115610ace574594505b81610ad93a876133ec565b610ae39190613403565b90506001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214610bc3575f610b1c856001600160a01b031661148a565b90506012811115610b5c576040517f1e3728a400000000000000000000000000000000000000000000000000000000815260048101829052602401610204565b835f03610b95576040517fb88ea7f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ba0816012613416565b610bab90600a613509565b610bb5838661151e565b610bbf9190613514565b9150505b949350505050565b5f5f198203610be157610bde8484611556565b91505b6001600160a01b03831615801590610c0257506001600160a01b0383163014155b8015610c2b57506001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015610c3657508115155b15610c5057610c506001600160a01b03851684308561160e565b5092915050565b5f5f198203610c6d57610c6a8430611556565b91505b6001600160a01b03831615801590610c8e57506001600160a01b0383163014155b8015610c9957508115155b15610c50576001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610cdb57610cd66001600160a01b038516848461120f565b610c50565b5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114610d24576040519150601f19603f3d011682016040523d82523d5f602084013e610d29565b606091505b5050905080610d7a5760405162461bcd60e51b815260206004820152600d60248201527f4574682073656e64206661696c000000000000000000000000000000000000006044820152606401610204565b50909392505050565b60408601515f9081908180805b83518110156110945773287778f121f134c66212fb16c9b53ec991d32f5b6001600160a01b03166393b18854858381518110610dce57610dce6130e4565b60200260200101516040518263ffffffff1660e01b8152600401610e0291906001600160e01b031991909116815260200190565b602060405180830381865afa158015610e1d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e419190612bd8565b9150816001600160a01b03166391a973c68b8b84818110610e6457610e646130e4565b9050602002810190610e769190613533565b8e604001518581518110610e8c57610e8c6130e4565b60200260200101516040518463ffffffff1660e01b8152600401610eb293929190613576565b6020604051808303815f875af1158015610ece573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef291906135b2565b925082610f07575f9550935061109e92505050565b816001600160a01b031663ab9772ac6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f43573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6791906135b2565b1561108c57816001600160a01b0316637c331ddb8c604001518381518110610f9157610f916130e4565b60200260200101516040518263ffffffff1660e01b8152600401610fb591906133c6565b5f60405180830381865afa158015610fcf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ff69190810190612ed1565b8b60400151828151811061100c5761100c6130e4565b60209081029190910101526040517ff14283c20000000000000000000000000000000000000000000000000000000081526001600160a01b0388169063f14283c29061105e908b908f90600401613652565b5f604051808303815f87803b158015611075575f80fd5b505af1158015611087573d5f803e3d5ffd5b505050505b600101610d90565b6001955093505050505b965096945050505050565b5f8073287778f121f134c66212fb16c9b53ec991d32f5b6001600160a01b03166393b18854866060015186815181106110e4576110e46130e4565b60200260200101516040518263ffffffff1660e01b815260040161111891906001600160e01b031991909116815260200190565b602060405180830381865afa158015611133573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111579190612bd8565b905061120681638df50f7460e01b8760200151878151811061117b5761117b6130e4565b602002602001015188604001518960800151898151811061119e5761119e6130e4565b6020026020010151886040516024016111ba94939291906136eb565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915261165f565b95945050505050565b6040516001600160a01b0383166024820152604481018290526102339084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915261168f565b5f8060ff16826001600160a01b031663247492f86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113059190613756565b60ff161492915050565b5f61131930611775565b905061132581846117e2565b5f84306040516020016113399291906137bc565b60405160208183030381529060405290505f85602001515f81518110611361576113616130e4565b602002602001015180602001905181019061137c91906138f8565b60c08101839052604051909150611397908290602001613a0e565b60405160208183030381529060405286602001515f815181106113bc576113bc6130e4565b6020026020010181905250846001600160a01b0316638df50f7487602001515f815181106113ec576113ec6130e4565b6020026020010151886040015189608001515f8151811061140f5761140f6130e4565b6020026020010151886040518563ffffffff1660e01b815260040161143794939291906136eb565b6020604051808303815f875af1158015611453573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061147791906130f8565b506114828386611854565b505050505050565b5f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038316016114b857506012919050565b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114f4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061151891906130f8565b92915050565b5f8161154561153585670de0b6b3a76400006118c2565b611540600286613514565b6118cd565b61154f9190613514565b9392505050565b5f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0384160161158d57506001600160a01b03811631611518565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa1580156115ea573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061154f91906130f8565b6040516001600160a01b03808516602483015283166044820152606481018290526107b69085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611254565b5f6001600160a01b038316611672575f80fd5b60205f835160208501866113885a03f45f51915080610c50575f80fd5b5f6116e3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166118d89092919063ffffffff16565b905080515f148061170357508080602001905181019061170391906135b2565b6102335760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610204565b5f61177f826118e6565b1561178b57505f919050565b6117948261197b565b156117a157506002919050565b7f15b0c1a13812f0fce8291b8e7786ece58e0daab08d489cdfe2899fdac4f660456001600160a01b0383163f036117da57506003919050565b506001919050565b5f8260038111156117f5576117f5613742565b036118075761180381611a22565b5050565b600282600381111561181b5761181b613742565b036118295761180381611c6c565b600382600381111561183d5761183d613742565b0361184b5761180381611d47565b61180381611e7e565b5f82600381111561186757611867613742565b036118755761180381611f46565b600282600381111561188957611889613742565b036118975761180381612018565b60038260038111156118ab576118ab613742565b036118b957611803816120c8565b611803816121da565b5f61154f82846133ec565b5f61154f8284613403565b6060610bc384845f85612589565b6040517f297103880000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201525f9073a26e15c895efc0616177b7c1e7270a4c7d51c99790632971038890602401602060405180830381865afa158015611957573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061151891906135b2565b6040517f6cfaf5e90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201525f90734c8a1beb8a87765788946d6b19c6c6355194abeb90636cfaf5e990602401602060405180830381865afa1580156119ec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a109190613b02565b67ffffffffffffffff16151592915050565b5f306001600160a01b031663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a839190612bd8565b9050806001600160a01b038116611b7a57735a15566417e6c1c9546523066500bddbc53f88c76001600160a01b03166365688cc96040518163ffffffff1660e01b81526004016020604051808303815f875af1158015611ae5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b099190612bd8565b6040517f7a9e5e4b0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201529091503090637a9e5e4b906024015f604051808303815f87803b158015611b63575f80fd5b505af1158015611b75573d5f803e3d5ffd5b505050505b6040517fb70096130000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152306024830152631cff79cd60e01b604483015282169063b700961390606401602060405180830381865afa158015611bea573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c0e91906135b2565b610233576040517fcbeea68c0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152306024830152631cff79cd60e01b604483015282169063cbeea68c90606401610a8f565b604051632520e7ff60e01b81526001600160a01b03821660048201523090632520e7ff90602401602060405180830381865afa158015611cae573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd291906135b2565b610436576040517f5bfa1b680000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201523090635bfa1b68906024015b5f604051808303815f87803b158015611d2e575f80fd5b505af1158015611d40573d5f803e3d5ffd5b5050505050565b5f306001600160a01b0316637ceab3b16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611da89190612bd8565b6040516350be256160e11b81523060048201526001600160a01b0384811660248301529192509082169063a17c4ac290604401602060405180830381865afa158015611df6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e1a91906135b2565b611803576040516331568f3d60e21b81526001600160a01b0383811660048301523060248301526001604483015282169063c55a3cf4906064015b5f604051808303815f87803b158015611e6c575f80fd5b505af1158015611482573d5f803e3d5ffd5b6040517f2d9ad53d0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201523090632d9ad53d90602401602060405180830381865afa158015611ed9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efd91906135b2565b610436576040517f610b59250000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152309063610b592590602401611d17565b5f306001600160a01b031663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f83573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa79190612bd8565b90506001600160a01b038116611fbb575050565b6040517f2bc3217d0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152306024830152631cff79cd60e01b6044830152829190821690632bc3217d90606401610a8f565b604051632520e7ff60e01b81526001600160a01b03821660048201523090632520e7ff90602401602060405180830381865afa15801561205a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061207e91906135b2565b15610436576040517fe6c09edf0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152309063e6c09edf90602401611d17565b5f306001600160a01b0316637ceab3b16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612105573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121299190612bd8565b6040516350be256160e11b81523060048201526001600160a01b0384811660248301529192509082169063a17c4ac290604401602060405180830381865afa158015612177573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061219b91906135b2565b15611803576040516331568f3d60e21b81526001600160a01b0383811660048301523060248301525f604483015282169063c55a3cf490606401611e55565b604051636617c22960e11b815260016004820181905260026024830152905f90309063cc2f8452906044015f60405180830381865afa15801561221f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122469190810190613b1d565b50905080515f03612275576040516311db1af760e11b81526001600160a01b0384166004820152602401610204565b826001600160a01b0316815f81518110612291576122916130e4565b60200260200101516001600160a01b0316036122da57604051637004e7ef60e11b8152600160048201526001600160a01b0384166024820152309063e009cfde90604401610a8f565b8051600103612307576040516311db1af760e11b81526001600160a01b0384166004820152602401610204565b826001600160a01b031681600181518110612324576123246130e4565b60200260200101516001600160a01b03160361239657306001600160a01b031663e009cfde825f8151811061235b5761235b6130e4565b6020026020010151856040518363ffffffff1660e01b8152600401610a8f9291906001600160a01b0392831681529116602082015260400190565b806001815181106123a9576123a96130e4565b6020908102919091010151604051636617c22960e11b81526001600160a01b038216600482015260086024820152909250309063cc2f8452906044015f60405180830381865afa1580156123ff573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526124269190810190613b1d565b5080519091501561256557826001600160a01b0316815f8151811061244d5761244d6130e4565b60200260200101516001600160a01b03160361249757604051637004e7ef60e11b81526001600160a01b03808416600483015284166024820152309063e009cfde90604401610a8f565b60015b815181101561256357836001600160a01b03168282815181106124bf576124bf6130e4565b60200260200101516001600160a01b03160361255b573063e009cfde836124e7600185613416565b815181106124f7576124f76130e4565b6020026020010151866040518363ffffffff1660e01b81526004016125329291906001600160a01b0392831681529116602082015260400190565b5f604051808303815f87803b158015612549575f80fd5b505af1158015610420573d5f803e3d5ffd5b60010161249a565b505b6040516311db1af760e11b81526001600160a01b0384166004820152602401610204565b606061259485612662565b6125ca576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80866001600160a01b031685876040516125e59190613b6c565b5f6040518083038185875af1925050503d805f811461261f576040519150601f19603f3d011682016040523d82523d5f602084013e612624565b606091505b50915091508115612638579150610bc39050565b8051156126485780518082602001fd5b8360405162461bcd60e51b815260040161020491906133c6565b5f813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610bc3575050151592915050565b5f60a082840312156126aa575f80fd5b50919050565b5f8060c083850312156126c1575f80fd5b823567ffffffffffffffff8111156126d7575f80fd5b6126e38582860161269a565b9250506126f3846020850161269a565b90509250929050565b5f6020828403121561270c575f80fd5b813567ffffffffffffffff811115612722575f80fd5b610bc38482850161269a565b5f8083601f84011261273e575f80fd5b50813567ffffffffffffffff811115612755575f80fd5b6020830191508360208260051b850101111561276f575f80fd5b9250929050565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156127ad576127ad612776565b60405290565b60405160a0810167ffffffffffffffff811182821017156127ad576127ad612776565b6040516060810167ffffffffffffffff811182821017156127ad576127ad612776565b60405160c0810167ffffffffffffffff811182821017156127ad576127ad612776565b60405160e0810167ffffffffffffffff811182821017156127ad576127ad612776565b604051601f8201601f1916810167ffffffffffffffff8111828210171561286857612868612776565b604052919050565b67ffffffffffffffff81168114610436575f80fd5b8015158114610436575f80fd5b5f67ffffffffffffffff8211156128ab576128ab612776565b5060051b60200190565b5f67ffffffffffffffff8211156128ce576128ce612776565b50601f01601f191660200190565b5f6128ee6128e9846128b5565b61283f565b9050828152838383011115612901575f80fd5b828260208301375f602084830101529392505050565b5f6129246128e984612892565b8381529050602080820190600585901b840186811115612942575f80fd5b845b8181101561298e57803567ffffffffffffffff811115612962575f80fd5b8601601f81018913612972575f80fd5b6129808982358684016128dc565b855250928201928201612944565b505050509392505050565b5f82601f8301126129a8575f80fd5b61154f83833560208501612917565b5f82601f8301126129c6575f80fd5b813560206129d66128e983612892565b8083825260208201915060208460051b8701019350868411156129f7575f80fd5b602086015b84811015612a1357803583529183019183016129fc565b509695505050505050565b5f805f805f805f60a0888a031215612a34575f80fd5b87359650602088013567ffffffffffffffff80821115612a52575f80fd5b612a5e8b838c0161272e565b909850965060408a0135915080821115612a76575f80fd5b612a828b838c0161272e565b909650945060608a0135935060808a0135915080821115612aa1575f80fd5b908901906080828c031215612ab4575f80fd5b612abc61278a565b8235612ac781612870565b81526020830135612ad781612885565b6020820152604083013582811115612aed575f80fd5b612af98d828601612999565b604083015250606083013582811115612b10575f80fd5b612b1c8d8286016129b7565b60608301525080935050505092959891949750929550565b5f8060408385031215612b45575f80fd5b823567ffffffffffffffff811115612b5b575f80fd5b612b678582860161269a565b95602094909401359450505050565b6001600160a01b0381168114610436575f80fd5b5f805f60608486031215612b9c575f80fd5b8335612ba781612b76565b92506020840135612bb781612b76565b929592945050506040919091013590565b8051612bd381612b76565b919050565b5f60208284031215612be8575f80fd5b815161154f81612b76565b5f60208284031215612c03575f80fd5b813561154f81612885565b5f82601f830112612c1d575f80fd5b61154f838335602085016128dc565b6001600160e01b031981168114610436575f80fd5b5f82601f830112612c50575f80fd5b81356020612c606128e983612892565b8083825260208201915060208460051b870101935086841115612c81575f80fd5b602086015b84811015612a13578035612c9981612c2c565b8352918301918301612c86565b60ff81168114610436575f80fd5b5f82601f830112612cc3575f80fd5b81356020612cd36128e983612892565b828152600592831b8501820192828201919087851115612cf1575f80fd5b8387015b85811015612d8b57803567ffffffffffffffff811115612d13575f80fd5b8801603f81018a13612d23575f80fd5b858101356040612d356128e983612892565b82815291851b8301810191888101908d841115612d50575f80fd5b938201935b83851015612d7a5784359250612d6a83612ca6565b8282529389019390890190612d55565b885250505093850193508401612cf5565b5090979650505050505050565b5f60a08236031215612da8575f80fd5b612db06127b3565b823567ffffffffffffffff80821115612dc7575f80fd5b612dd336838701612c0e565b83526020850135915080821115612de8575f80fd5b612df436838701612999565b60208401526040850135915080821115612e0c575f80fd5b612e18368387016129b7565b60408401526060850135915080821115612e30575f80fd5b612e3c36838701612c41565b60608401526080850135915080821115612e54575f80fd5b50612e6136828601612cb4565b60808301525092915050565b5f5b83811015612e87578181015183820152602001612e6f565b50505f910152565b5f82601f830112612e9e575f80fd5b8151612eac6128e9826128b5565b818152846020838601011115612ec0575f80fd5b610bc3826020830160208701612e6d565b5f60208284031215612ee1575f80fd5b815167ffffffffffffffff811115612ef7575f80fd5b610bc384828501612e8f565b5f805f60608486031215612f15575f80fd5b8351925060208401519150604084015167ffffffffffffffff80821115612f3a575f80fd5b9085019060608288031215612f4d575f80fd5b612f556127d6565b8251612f6081612b76565b8152602083015182811115612f73575f80fd5b612f7f89828601612e8f565b602083015250604083015182811115612f96575f80fd5b929092019160c08389031215612faa575f80fd5b612fb26127f9565b8351612fbd81612b76565b81526020840151612fcd81612b76565b60208201526040840151612fe081612b76565b80604083015250606084015160608201526080840151608082015260a08401518381111561300c575f80fd5b6130188a828701612e8f565b60a083015250806040830152508093505050509250925092565b5f60208284031215613042575f80fd5b813561154f81612b76565b5f82601f83011261305c575f80fd5b8151602061306c6128e983612892565b8083825260208201915060208460051b87010193508684111561308d575f80fd5b602086015b84811015612a135780516130a581612b76565b8352918301918301613092565b5f602082840312156130c2575f80fd5b815167ffffffffffffffff8111156130d8575f80fd5b610bc38482850161304d565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613108575f80fd5b5051919050565b5f82601f83011261311e575f80fd5b8151602061312e6128e983612892565b8083825260208201915060208460051b87010193508684111561314f575f80fd5b602086015b84811015612a1357805161316781612c2c565b8352918301918301613154565b5f82601f830112613183575f80fd5b815160206131936128e983612892565b828152600592831b85018201928282019190878511156131b1575f80fd5b8387015b85811015612d8b57805167ffffffffffffffff8111156131d3575f80fd5b8801603f81018a136131e3575f80fd5b8581015160406131f56128e983612892565b82815291851b8301810191888101908d841115613210575f80fd5b938201935b8385101561323a578451925061322a83612ca6565b8282529389019390890190613215565b8852505050938501935084016131b5565b8051612bd381612885565b5f60208284031215613266575f80fd5b815167ffffffffffffffff8082111561327d575f80fd5b9083019060c08286031215613290575f80fd5b6132986127f9565b8251828111156132a6575f80fd5b6132b287828601612e8f565b8252506132c160208401612bc8565b60208201526040830151828111156132d7575f80fd5b6132e38782860161310f565b6040830152506060830151828111156132fa575f80fd5b6133068782860161310f565b60608301525060808301518281111561331d575f80fd5b61332987828601613174565b60808301525061333b60a0840161324b565b60a082015295945050505050565b5f61154f368484612917565b5f808335601e1984360301811261336a575f80fd5b83018035915067ffffffffffffffff821115613384575f80fd5b6020019150600581901b360382131561276f575f80fd5b5f81518084526133b2816020860160208601612e6d565b601f01601f19169290920160200192915050565b602081525f61154f602083018461339b565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417611518576115186133d8565b80820180821115611518576115186133d8565b81810381811115611518576115186133d8565b600181815b8085111561346357815f1904821115613449576134496133d8565b8085161561345657918102915b93841c939080029061342e565b509250929050565b5f8261347957506001611518565b8161348557505f611518565b816001811461349b57600281146134a5576134c1565b6001915050611518565b60ff8411156134b6576134b66133d8565b50506001821b611518565b5060208310610133831016604e8410600b84101617156134e4575081810a611518565b6134ee8383613429565b805f1904821115613501576135016133d8565b029392505050565b5f61154f838361346b565b5f8261352e57634e487b7160e01b5f52601260045260245ffd5b500490565b5f808335601e19843603018112613548575f80fd5b83018035915067ffffffffffffffff821115613562575f80fd5b60200191503681900382131561276f575f80fd5b60408152826040820152828460608301375f606084830101525f601f19601f85011682016060838203016020840152610bbf606082018561339b565b5f602082840312156135c2575f80fd5b815161154f81612885565b5f8282518085526020808601955060208260051b840101602086015f5b84811015612d8b57601f1986840301895261360683835161339b565b988401989250908301906001016135ea565b5f815180845260208085019450602084015f5b838110156136475781518752958201959082019060010161362b565b509495945050505050565b8281526040602082015267ffffffffffffffff82511660408201526020820151151560608201525f604083015160808084015261369260c08401826135cd565b90506060840151603f198483030160a08501526136af8282613618565b9695505050505050565b5f815180845260208085019450602084015f5b8381101561364757815160ff16875295820195908201906001016136cc565b608081525f6136fd608083018761339b565b828103602084015261370f8187613618565b9050828103604084015261372381866136b9565b905082810360608401526137378185613618565b979650505050505050565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215613766575f80fd5b815161154f81612ca6565b5f8282518085526020808601955060208260051b840101602086015f5b84811015612d8b57601f198684030189526137aa8383516136b9565b9884019892509083019060010161378e565b604081525f835160a060408401526137d760e084018261339b565b9050602080860151603f19808685030160608701526137f684836135cd565b935060408801519150808685030160808701526138138483613618565b6060890151878203830160a0890152805180835290850195505f9350908401905b8084101561385e5785516001600160e01b0319168252948401946001939093019290840190613834565b5060808901519450818782030160c088015261387a8186613771565b9550505050613893818501866001600160a01b03169052565b50509392505050565b5f82601f8301126138ab575f80fd5b815160206138bb6128e983612892565b8083825260208201915060208460051b8701019350868411156138dc575f80fd5b602086015b84811015612a1357805183529183019183016138e1565b5f60208284031215613908575f80fd5b815167ffffffffffffffff8082111561391f575f80fd5b9083019060e08286031215613932575f80fd5b61393a61281c565b825182811115613948575f80fd5b6139548782860161304d565b825250602083015182811115613968575f80fd5b6139748782860161389c565b60208301525060408301518281111561398b575f80fd5b6139978782860161389c565b6040830152506139a960608401612bc8565b60608201526139ba60808401612bc8565b608082015260a0830151828111156139d0575f80fd5b6139dc87828601612e8f565b60a08301525060c0830151828111156139f3575f80fd5b6139ff87828601612e8f565b60c08301525095945050505050565b6020808252825160e083830152805161010084018190525f929182019083906101208601905b80831015613a5d5783516001600160a01b03168252928401926001929092019190840190613a34565b50838701519350601f19925082868203016040870152613a7d8185613618565b93505050604085015181858403016060860152613a9a8382613618565b9250506060850151613ab760808601826001600160a01b03169052565b5060808501516001600160a01b03811660a08601525060a0850151818584030160c0860152613ae6838261339b565b92505060c0850151818584030160e08601526136af838261339b565b5f60208284031215613b12575f80fd5b815161154f81612870565b5f8060408385031215613b2e575f80fd5b825167ffffffffffffffff811115613b44575f80fd5b613b508582860161304d565b9250506020830151613b6181612b76565b809150509250929050565b5f8251613b7d818460208701612e6d565b919091019291505056fea2646970667358221220edfcca746cbbdd4fb3de47260f6ff4d0c3fda9a7863ba672133340550a5606c164736f6c63430008180033

Verified Source Code Partial Match

Compiler: v0.8.24+commit.e11b9ed9 EVM: cancun Optimization: Yes (1000 runs)
RecipeExecutor.sol 2188 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;










library Address {
    //insufficient balance
    error InsufficientBalance(uint256 available, uint256 required);
    //unable to send value, recipient may have reverted
    error SendingValueFail();
    //insufficient balance for call
    error InsufficientBalanceForCall(uint256 available, uint256 required);
    //call to non-contract
    error NonContractCall();

    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            codehash := extcodehash(account)
        }
        return (codehash != accountHash && codehash != 0x0);
    }

    function sendValue(address payable recipient, uint256 amount) internal {
        uint256 balance = address(this).balance;
        if (balance < amount) {
            revert InsufficientBalance(balance, amount);
        }

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success,) = recipient.call{ value: amount }("");
        if (!(success)) {
            revert SendingValueFail();
        }
    }

    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    function functionCall(address target, bytes memory data, string memory errorMessage)
        internal
        returns (bytes memory)
    {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    function functionCallWithValue(address target, bytes memory data, uint256 value)
        internal
        returns (bytes memory)
    {
        return functionCallWithValue(
            target, data, value, "Address: low-level call with value failed"
        );
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        uint256 balance = address(this).balance;
        if (balance < value) {
            revert InsufficientBalanceForCall(balance, value);
        }
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 weiValue,
        string memory errorMessage
    ) private returns (bytes memory) {
        if (!(isContract(target))) {
            revert NonContractCall();
        }

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}







interface IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint256 digits);
    function totalSupply() external view returns (uint256 supply);

    function balanceOf(address _owner) external view returns (uint256 balance);

    function transfer(address _to, uint256 _value) external returns (bool success);

    function transferFrom(address _from, address _to, uint256 _value)
        external
        returns (bool success);

    function approve(address _spender, uint256 _value) external returns (bool success);

    function allowance(address _owner, address _spender) external view returns (uint256 remaining);

    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}











library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(
            token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
        );
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
     * 0 before setting it to a non-zero value.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

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

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata =
            address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(
            returndata.length == 0 || abi.decode(returndata, (bool)),
            "SafeERC20: ERC20 operation did not succeed"
        );
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

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







contract MainnetActionsUtilAddresses {
    address internal constant DFS_REG_CONTROLLER_ADDR = 0xF8f8B3C98Cf2E63Df3041b73f80F362a4cf3A576;
    address internal constant REGISTRY_ADDR = 0x287778F121F134C66212FB16c9b53eC991D32f5b;
    address internal constant DFS_LOGGER_ADDR = 0xcE7a977Cac4a481bc84AC06b2Da0df614e621cf3;
    address internal constant SUB_STORAGE_ADDR = 0x1612fc28Ee0AB882eC99842Cde0Fc77ff0691e90;
    address internal constant PROXY_AUTH_ADDR = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70;
    address internal constant LSV_PROXY_REGISTRY_ADDRESS =
        0xa8a3c86c4A2DcCf350E84D2b3c46BDeBc711C16e;
    address internal constant TRANSIENT_STORAGE = 0x2F7Ef2ea5E8c97B8687CA703A0e50Aa5a49B7eb2;
    address internal constant TRANSIENT_STORAGE_CANCUN = 0x0304E27cccE28bAB4d78C6cb7AfD4cd01c87c1e4;
}







contract ActionsUtilHelper is MainnetActionsUtilAddresses { }







contract MainnetAuthAddresses {
    address internal constant ADMIN_VAULT_ADDR = 0xCCf3d848e08b94478Ed8f46fFead3008faF581fD;
    address internal constant DSGUARD_FACTORY_ADDRESS = 0x5a15566417e6C1c9546523066500bDDBc53F88C7;
    address internal constant ADMIN_ADDR = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9; // USED IN ADMIN VAULT CONSTRUCTOR
    address internal constant PROXY_AUTH_ADDRESS = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70;
    address internal constant MODULE_AUTH_ADDRESS = 0x7407974DDBF539e552F1d051e44573090912CC3D;
}







contract AuthHelper is MainnetAuthAddresses { }







interface IAdminVault {
    function owner() external view returns (address);
    function admin() external view returns (address);
    function changeOwner(address _owner) external;
    function changeAdmin(address _admin) external;
}











contract AdminAuth is AuthHelper {
    using SafeERC20 for IERC20;

    IAdminVault public constant adminVault = IAdminVault(ADMIN_VAULT_ADDR);

    error SenderNotOwner();
    error SenderNotAdmin();

    modifier onlyOwner() {
        if (adminVault.owner() != msg.sender) {
            revert SenderNotOwner();
        }
        _;
    }

    modifier onlyAdmin() {
        if (adminVault.admin() != msg.sender) {
            revert SenderNotAdmin();
        }
        _;
    }

    /// @notice withdraw stuck funds
    function withdrawStuckFunds(address _token, address _receiver, uint256 _amount)
        public
        onlyOwner
    {
        if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
            payable(_receiver).transfer(_amount);
        } else {
            IERC20(_token).safeTransfer(_receiver, _amount);
        }
    }
}







interface IDFSRegistry {
    function getAddr(bytes4 _id) external view returns (address);

    function addNewContract(bytes32 _id, address _contractAddr, uint256 _waitPeriod) external;

    function startContractChange(bytes32 _id, address _newContractAddr) external;

    function approveContractChange(bytes32 _id) external;

    function cancelContractChange(bytes32 _id) external;

    function changeWaitPeriod(bytes32 _id, uint256 _newWaitPeriod) external;
}







contract DefisaverLogger {
    event RecipeEvent(address indexed caller, string indexed logName);

    event ActionDirectEvent(address indexed caller, string indexed logName, bytes data);

    function logRecipeEvent(string memory _logName) public {
        emit RecipeEvent(msg.sender, _logName);
    }

    function logActionDirectEvent(string memory _logName, bytes memory _data) public {
        emit ActionDirectEvent(msg.sender, _logName, _data);
    }
}







interface IDSProxy {
    function execute(bytes memory _code, bytes memory _data)
        external
        payable
        returns (address, bytes32);

    function execute(address _target, bytes memory _data) external payable returns (bytes32);

    function setCache(address _cacheAddr) external payable returns (bool);

    function owner() external view returns (address);

    function guard() external view returns (address);
}







interface IDSProxyFactory {
    function isProxy(address _proxy) external view returns (bool);
    function build(address owner) external returns (IDSProxy proxy);
    function build() external returns (IDSProxy proxy);
}






interface IInstaList {
    struct AccountLink {
        address first;
        address last;
        uint64 count;
    }

    struct AccountList {
        address prev;
        address next;
    }

    struct UserLink {
        uint64 first;
        uint64 last;
        uint64 count;
    }

    struct UserList {
        uint64 prev;
        uint64 next;
    }

    function accountAddr(uint64 _id) external view returns (address);
    function accountID(address _addr) external view returns (uint64);
    function accountLink(uint64 _id) external view returns (AccountLink memory);
    function accountList(uint64 _id, address _user) external view returns (AccountList memory);
    function userLink(address _user) external view returns (UserLink memory);
    function userList(address _user, uint64 _id) external view returns (UserList memory);
}







interface ISafe {
    enum Operation {
        Call,
        DelegateCall
    }

    function setup(
        address[] calldata _owners,
        uint256 _threshold,
        address to,
        bytes calldata data,
        address fallbackHandler,
        address paymentToken,
        uint256 payment,
        address payable paymentReceiver
    ) external;

    function execTransaction(
        address to,
        uint256 value,
        bytes calldata data,
        Operation operation,
        uint256 safeTxGas,
        uint256 baseGas,
        uint256 gasPrice,
        address gasToken,
        address payable refundReceiver,
        bytes memory signatures
    ) external payable returns (bool success);

    function execTransactionFromModule(
        address to,
        uint256 value,
        bytes memory data,
        Operation operation
    ) external returns (bool success);

    function checkSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures)
        external
        view;

    function checkNSignatures(
        address executor,
        bytes32 dataHash,
        bytes memory, /* data */
        bytes memory signatures,
        uint256 requiredSignatures
    ) external view;

    function approveHash(bytes32 hashToApprove) external;

    function domainSeparator() external view returns (bytes32);

    function getTransactionHash(
        address to,
        uint256 value,
        bytes calldata data,
        Operation operation,
        uint256 safeTxGas,
        uint256 baseGas,
        uint256 gasPrice,
        address gasToken,
        address refundReceiver,
        uint256 _nonce
    ) external view returns (bytes32);

    function nonce() external view returns (uint256);

    function setFallbackHandler(address handler) external;

    function getOwners() external view returns (address[] memory);

    function isOwner(address owner) external view returns (bool);

    function getThreshold() external view returns (uint256);

    function enableModule(address module) external;

    function isModuleEnabled(address module) external view returns (bool);

    function disableModule(address prevModule, address module) external;

    function getModulesPaginated(address start, uint256 pageSize)
        external
        view
        returns (address[] memory array, address next);
}







contract MainnetDSAProxyFactoryAddresses {
    address internal constant DSA_LIST_ADDR = 0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb;
}







contract DSAProxyFactoryHelper is MainnetDSAProxyFactoryAddresses { }







contract MainnetProxyFactoryAddresses {
    address internal constant PROXY_FACTORY_ADDR = 0xA26e15C895EFc0616177B7c1e7270A4C7D51C997;
}







contract DSProxyFactoryHelper is MainnetProxyFactoryAddresses { }







contract MainnetSFProxyFactoryAddresses {
    address internal constant SF_PROXY_FACTORY_ADDR = 0xF7B75183A2829843dB06266c114297dfbFaeE2b6;
    address internal constant SF_PROXY_GUARD = 0xCe91349d2A4577BBd0fC91Fe6019600e047f2847;
    bytes32 internal constant SF_PROXY_CODEHASH =
        0x15b0c1a13812f0fce8291b8e7786ece58e0daab08d489cdfe2899fdac4f66045;
}







contract SFProxyFactoryHelper is MainnetSFProxyFactoryAddresses { }







enum WalletType {
    DSPROXY,
    SAFE,
    DSAPROXY,
    SFPROXY
}















contract SmartWalletUtils is DSProxyFactoryHelper, DSAProxyFactoryHelper, SFProxyFactoryHelper {
    /// @notice Determine the type of wallet an address represents
    function _getWalletType(address _wallet) internal view returns (WalletType) {
        if (_isDSProxy(_wallet)) {
            return WalletType.DSPROXY;
        }

        if (_isDSAProxy(_wallet)) {
            return WalletType.DSAPROXY;
        }

        if (_isSFProxy(_wallet)) {
            return WalletType.SFPROXY;
        }

        // Otherwise, we assume we are in context of Safe
        return WalletType.SAFE;
    }

    /// @notice Check if the wallet is a DSProxy
    function _isDSProxy(address _wallet) internal view returns (bool) {
        return IDSProxyFactory(PROXY_FACTORY_ADDR).isProxy(_wallet);
    }

    /// @notice Check if the wallet is a DSA Proxy Account
    function _isDSAProxy(address _wallet) internal view returns (bool) {
        return IInstaList(DSA_LIST_ADDR).accountID(_wallet) != 0;
    }

    /// @notice Check if the wallet is a Summerfi account
    function _isSFProxy(address _wallet) internal view returns (bool) {
        return _wallet.codehash == SF_PROXY_CODEHASH;
    }

    /// @notice Fetch the owner of the smart wallet or the wallet itself
    /// @dev For 1/1 Safe it returns the owner, otherwise it returns the wallet itself
    /// @dev Only supports Safe and DSProxy wallets because SFProxy and DSAProxy are not part of automation
    /// @param _wallet Address of the smart wallet
    /// @return Address of the owner or wallet
    function _fetchOwnerOrWallet(address _wallet) internal view returns (address) {
        if (_isDSProxy(_wallet)) return IDSProxy(_wallet).owner();

        // Otherwise, we assume we are in context of Safe
        address[] memory owners = ISafe(_wallet).getOwners();
        return owners.length == 1 ? owners[0] : _wallet;
    }
}











abstract contract ActionBase is AdminAuth, ActionsUtilHelper, SmartWalletUtils {
    event ActionEvent(string indexed logName, bytes data);

    IDFSRegistry public constant registry = IDFSRegistry(REGISTRY_ADDR);

    DefisaverLogger public constant logger = DefisaverLogger(DFS_LOGGER_ADDR);

    //Wrong sub index value
    error SubIndexValueError();
    //Wrong return index value
    error ReturnIndexValueError();

    /// @dev Subscription params index range [128, 255]
    uint8 public constant SUB_MIN_INDEX_VALUE = 128;
    uint8 public constant SUB_MAX_INDEX_VALUE = 255;

    /// @dev Return params index range [1, 127]
    uint8 public constant RETURN_MIN_INDEX_VALUE = 1;
    uint8 public constant RETURN_MAX_INDEX_VALUE = 127;

    /// @dev If the input value should not be replaced
    uint8 public constant NO_PARAM_MAPPING = 0;

    /// @dev We need to parse Flash loan actions in a different way
    enum ActionType {
        FL_ACTION,
        STANDARD_ACTION,
        FEE_ACTION,
        CHECK_ACTION,
        CUSTOM_ACTION
    }

    /// @notice Parses inputs and runs the implemented action through a user wallet
    /// @dev Is called by the RecipeExecutor chaining actions together
    /// @param _callData Array of input values each value encoded as bytes
    /// @param _subData Array of subscribed vales, replaces input values if specified
    /// @param _paramMapping Array that specifies how return and subscribed values are mapped in input
    /// @param _returnValues Returns values from actions before, which can be injected in inputs
    /// @return Returns a bytes32 value through user wallet, each actions implements what that value is
    function executeAction(
        bytes memory _callData,
        bytes32[] memory _subData,
        uint8[] memory _paramMapping,
        bytes32[] memory _returnValues
    ) public payable virtual returns (bytes32);

    /// @notice Parses inputs and runs the single implemented action through a user wallet
    /// @dev Used to save gas when executing a single action directly
    function executeActionDirect(bytes memory _callData) public payable virtual;

    /// @notice Returns the type of action we are implementing
    function actionType() public pure virtual returns (uint8);

    //////////////////////////// HELPER METHODS ////////////////////////////

    /// @notice Given an uint256 input, injects return/sub values if specified
    /// @param _param The original input value
    /// @param _mapType Indicated the type of the input in paramMapping
    /// @param _subData Array of subscription data we can replace the input value with
    /// @param _returnValues Array of subscription data we can replace the input value with
    function _parseParamUint(
        uint256 _param,
        uint8 _mapType,
        bytes32[] memory _subData,
        bytes32[] memory _returnValues
    ) internal pure returns (uint256) {
        if (isReplaceable(_mapType)) {
            if (isReturnInjection(_mapType)) {
                _param = uint256(_returnValues[getReturnIndex(_mapType)]);
            } else {
                _param = uint256(_subData[getSubIndex(_mapType)]);
            }
        }

        return _param;
    }

    /// @notice Given an addr input, injects return/sub values if specified
    /// @param _param The original input value
    /// @param _mapType Indicated the type of the input in paramMapping
    /// @param _subData Array of subscription data we can replace the input value with
    /// @param _returnValues Array of subscription data we can replace the input value with
    function _parseParamAddr(
        address _param,
        uint8 _mapType,
        bytes32[] memory _subData,
        bytes32[] memory _returnValues
    ) internal view returns (address) {
        if (isReplaceable(_mapType)) {
            if (isReturnInjection(_mapType)) {
                _param = address(bytes20((_returnValues[getReturnIndex(_mapType)])));
            } else {
                /// @dev The last two values are specially reserved for proxy addr and owner addr
                if (_mapType == 254) return address(this); // wallet address
                if (_mapType == 255) return _fetchOwnerOrWallet(address(this)); // owner if 1/1 wallet or the wallet itself

                _param = address(uint160(uint256(_subData[getSubIndex(_mapType)])));
            }
        }

        return _param;
    }

    /// @notice Given an bytes32 input, injects return/sub values if specified
    /// @param _param The original input value
    /// @param _mapType Indicated the type of the input in paramMapping
    /// @param _subData Array of subscription data we can replace the input value with
    /// @param _returnValues Array of subscription data we can replace the input value with
    function _parseParamABytes32(
        bytes32 _param,
        uint8 _mapType,
        bytes32[] memory _subData,
        bytes32[] memory _returnValues
    ) internal pure returns (bytes32) {
        if (isReplaceable(_mapType)) {
            if (isReturnInjection(_mapType)) {
                _param = (_returnValues[getReturnIndex(_mapType)]);
            } else {
                _param = _subData[getSubIndex(_mapType)];
            }
        }

        return _param;
    }

    /// @notice Checks if the paramMapping value indicated that we need to inject values
    /// @param _type Indicated the type of the input
    function isReplaceable(uint8 _type) internal pure returns (bool) {
        return _type != NO_PARAM_MAPPING;
    }

    /// @notice Checks if the paramMapping value is in the return value range
    /// @param _type Indicated the type of the input
    function isReturnInjection(uint8 _type) internal pure returns (bool) {
        return (_type >= RETURN_MIN_INDEX_VALUE) && (_type <= RETURN_MAX_INDEX_VALUE);
    }

    /// @notice Transforms the paramMapping value to the index in return array value
    /// @param _type Indicated the type of the input
    function getReturnIndex(uint8 _type) internal pure returns (uint8) {
        if (!(isReturnInjection(_type))) {
            revert SubIndexValueError();
        }

        return (_type - RETURN_MIN_INDEX_VALUE);
    }

    /// @notice Transforms the paramMapping value to the index in sub array value
    /// @param _type Indicated the type of the input
    function getSubIndex(uint8 _type) internal pure returns (uint8) {
        if (_type < SUB_MIN_INDEX_VALUE) {
            revert ReturnIndexValueError();
        }
        return (_type - SUB_MIN_INDEX_VALUE);
    }
}







interface IInstaAccount {
    function isAuth(address _user) external view returns (bool);
    function enable(address _user) external;
    function disable(address _user) external;
    function version() external view returns (uint256);
}









contract DSAProxyPermission is AuthHelper {
    /// @notice Called in the context of DSA proxy account to authorize an address
    /// @param _contractAddr Address which will be authorized
    /// @dev Can't enable the same contract twice
    function _giveDSAProxyPermission(address _contractAddr) internal {
        if (!IInstaAccount(address(this)).isAuth(_contractAddr)) {
            IInstaAccount(address(this)).enable(_contractAddr);
        }
    }

    /// @notice Called in the context of DSA proxy account to remove authority of an address
    /// @param _contractAddr Auth address which will be removed from auth list
    /// @dev Can't remove a contract that is not authorized
    function _removeDSAProxyPermission(address _contractAddr) internal {
        if (IInstaAccount(address(this)).isAuth(_contractAddr)) {
            IInstaAccount(address(this)).disable(_contractAddr);
        }
    }
}







interface IDSAuthority {
    function canCall(address src, address dst, bytes4 sig) external view returns (bool);
}







interface IDSAuth {
    function authority() external view returns (IDSAuthority);
    function owner() external view returns (address);
    function setOwner(address owner_) external;
    function setAuthority(IDSAuthority authority_) external;
    function isAuthorized(address src, bytes4 sig) external view returns (bool);
}







interface IDSGuard {
    function canCall(address src_, address dst_, bytes4 sig) external view returns (bool);
    function permit(bytes32 src, bytes32 dst, bytes32 sig) external;
    function forbid(bytes32 src, bytes32 dst, bytes32 sig) external;
    function permit(address src, address dst, bytes32 sig) external;
    function forbid(address src, address dst, bytes32 sig) external;
}







interface IDSGuardFactory {
    function newGuard() external returns (IDSGuard guard);
}












contract DSProxyPermission is AuthHelper {
    bytes4 private constant EXECUTE_SELECTOR = bytes4(keccak256("execute(address,bytes)"));

    /// @notice Called in the context of DSProxy to authorize an address
    /// @param _contractAddr Address which will be authorized
    function _giveProxyPermission(address _contractAddr) internal {
        address currAuthority = address(IDSAuth(address(this)).authority());
        IDSGuard guard = IDSGuard(currAuthority);

        if (currAuthority == address(0)) {
            guard = IDSGuardFactory(DSGUARD_FACTORY_ADDRESS).newGuard();
            IDSAuth(address(this)).setAuthority(IDSAuthority(address(guard)));
        }

        if (!guard.canCall(_contractAddr, address(this), EXECUTE_SELECTOR)) {
            guard.permit(_contractAddr, address(this), EXECUTE_SELECTOR);
        }
    }

    /// @notice Called in the context of DSProxy to remove authority of an address
    /// @param _contractAddr Auth address which will be removed from authority list
    function _removeProxyPermission(address _contractAddr) internal {
        address currAuthority = address(IDSAuth(address(this)).authority());

        // if there is no authority, that means that contract doesn't have permission
        if (currAuthority == address(0)) {
            return;
        }

        IDSGuard guard = IDSGuard(currAuthority);
        guard.forbid(_contractAddr, address(this), EXECUTE_SELECTOR);
    }
}








contract SafeModulePermission {
    address private constant SENTINEL_MODULES = address(0x1);

    error ModuleNotFoundError(address moduleAddr);

    /// @notice Called in the context of Safe to authorize module
    /// @param _moduleAddr Address of module which will be authorized
    /// @dev Can't enable the same module twice
    function _enableModule(address _moduleAddr) internal {
        if (!ISafe(address(this)).isModuleEnabled(_moduleAddr)) {
            ISafe(address(this)).enableModule(_moduleAddr);
        }
    }

    /// @notice Called in the context of Safe to remove authority of module
    /// @param _moduleAddr Address of module which will be removed from authority list
    /// @dev moduleAddr has to be one of the last 10 modules added
    /// @dev modules are returned in order SM -> Mn -> M(n-1) -> ... -> M1 -> SM, without SM included
    function _disableModule(address _moduleAddr) internal {
        address startFrom = SENTINEL_MODULES;

        // to save on gas, first check for last 2 modules added as they are most likely to be the ones to be removed
        (address[] memory modules,) = ISafe(address(this)).getModulesPaginated(startFrom, 2);

        // if no modules found, revert
        if (modules.length == 0) {
            revert ModuleNotFoundError(_moduleAddr);
        }

        // check for last module added
        if (modules[0] == _moduleAddr) {
            ISafe(address(this)).disableModule(SENTINEL_MODULES, _moduleAddr);
            return;
        }

        // if there is only 1 module and it is not the one to be removed, revert
        if (modules.length == 1) {
            revert ModuleNotFoundError(_moduleAddr);
        }

        // check for second last module added
        if (modules[1] == _moduleAddr) {
            ISafe(address(this)).disableModule(modules[0], _moduleAddr);
            return;
        }

        // if module not found in last 2 modules, fetch up to 8 more modules. Start searching from the second last module
        startFrom = modules[1];
        (modules,) = ISafe(address(this)).getModulesPaginated(startFrom, 8);

        if (modules.length > 0) {
            if (modules[0] == _moduleAddr) {
                ISafe(address(this)).disableModule(startFrom, _moduleAddr);
                return;
            }
            for (uint256 i = 1; i < modules.length; ++i) {
                if (modules[i] == _moduleAddr) {
                    ISafe(address(this)).disableModule(modules[i - 1], _moduleAddr);
                    return;
                }
            }
        }
        // if module not found, revert
        revert ModuleNotFoundError(_moduleAddr);
    }
}






interface IAccountGuard {
    function owners(address) external view returns (address);

    function owner() external view returns (address);

    function setWhitelist(address target, bool status) external;

    function canCall(address proxy, address operator) external view returns (bool);

    function permit(address caller, address target, bool allowance) external;

    function isWhitelisted(address target) external view returns (bool);

    function isWhitelistedSend(address target) external view returns (bool);
}






interface IAccountImplementation {
    function execute(address _target, bytes memory _data)
        external
        payable
        returns (bytes32 response);

    function send(address _target, bytes memory _data) external payable;

    function owner() external view returns (address owner);

    function guard() external view returns (address);
}










contract SFProxyPermission {
    /// @notice Gives permission to an address to call the Summerfi account
    /// @param _caller Address to give permission to
    function _giveSFProxyPermission(address _caller) internal {
        address guard = IAccountImplementation(address(this)).guard();
        if (!IAccountGuard(guard).canCall(address(this), _caller)) {
            IAccountGuard(guard).permit(_caller, address(this), true);
        }
    }

    /// @notice Removes permission from an address to call the Summerfi account
    /// @param _caller Address to remove permission from
    function _removeSFProxyPermission(address _caller) internal {
        address guard = IAccountImplementation(address(this)).guard();
        if (IAccountGuard(guard).canCall(address(this), _caller)) {
            IAccountGuard(guard).permit(_caller, address(this), false);
        }
    }
}













contract Permission is
    DSProxyPermission,
    SafeModulePermission,
    DSAProxyPermission,
    SFProxyPermission
{
    /// @notice Gives permission to Auth contract used by dfs automation
    function _givePermissionToAuthContract(bool _isDSProxyWallet) internal {
        _isDSProxyWallet
            ? _giveProxyPermission(PROXY_AUTH_ADDRESS)
            : _enableModule(MODULE_AUTH_ADDRESS);
    }

    /// @notice Removes permission for Auth contract used by dfs automation
    function _removePermissionFromAuthContract(bool _isDSProxyWallet) internal {
        _isDSProxyWallet
            ? _removeProxyPermission(PROXY_AUTH_ADDRESS)
            : _disableModule(MODULE_AUTH_ADDRESS);
    }

    /// @notice Gives permission to an arbitrary contract
    /// @dev Defaults to Safe Smart Wallet if wallet type is not found
    /// @param _walletType Type of smart wallet
    /// @param _to Address of the contract to give permission to
    function _givePermissionTo(WalletType _walletType, address _to) internal {
        if (_walletType == WalletType.DSPROXY) {
            _giveProxyPermission(_to);
        } else if (_walletType == WalletType.DSAPROXY) {
            _giveDSAProxyPermission(_to);
        } else if (_walletType == WalletType.SFPROXY) {
            _giveSFProxyPermission(_to);
        } else {
            _enableModule(_to);
        }
    }

    /// @notice Removes permission for an arbitrary contract
    /// @dev Defaults to Safe Smart Wallet if wallet type is not found
    /// @param _walletType Type of smart wallet
    /// @param _from Address of the contract to remove permission from
    function _removePermissionFrom(WalletType _walletType, address _from) internal {
        if (_walletType == WalletType.DSPROXY) {
            _removeProxyPermission(_from);
        } else if (_walletType == WalletType.DSAPROXY) {
            _removeDSAProxyPermission(_from);
        } else if (_walletType == WalletType.SFPROXY) {
            _removeSFProxyPermission(_from);
        } else {
            _disableModule(_from);
        }
    }
}







contract MainnetCoreAddresses {
    address internal constant REGISTRY_ADDR = 0x287778F121F134C66212FB16c9b53eC991D32f5b;
    address internal constant DEFISAVER_LOGGER = 0xcE7a977Cac4a481bc84AC06b2Da0df614e621cf3;

    address internal constant PROXY_AUTH_ADDR = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70;
    address internal constant MODULE_AUTH_ADDR = 0x7407974DDBF539e552F1d051e44573090912CC3D;

    address internal constant SUB_STORAGE_ADDR = 0x1612fc28Ee0AB882eC99842Cde0Fc77ff0691e90;
    address internal constant BUNDLE_STORAGE_ADDR = 0x223c6aDE533851Df03219f6E3D8B763Bd47f84cf;
    address internal constant STRATEGY_STORAGE_ADDR = 0xF52551F95ec4A2B4299DcC42fbbc576718Dbf933;

    address internal constant BYTES_TRANSIENT_STORAGE = 0xB3FE6f712c8B8c64CD2780ce714A36e7640DDf0f;
}







contract CoreHelper is MainnetCoreAddresses { }








contract StrategyModel {
    /// @dev Group of strategies bundled together so user can sub to multiple strategies at once
    /// @param creator Address of the user who created the bundle
    /// @param strategyIds Array of strategy ids stored in StrategyStorage
    struct StrategyBundle {
        address creator;
        uint64[] strategyIds;
    }

    /// @dev Template/Class which defines a Strategy
    /// @param name Name of the strategy useful for logging what strategy is executing
    /// @param creator Address of the user which created the strategy
    /// @param triggerIds Array of identifiers for trigger - bytes4(keccak256(TriggerName))
    /// @param actionIds Array of identifiers for actions - bytes4(keccak256(ActionName))
    /// @param paramMapping Describes how inputs to functions are piped from return/subbed values
    /// @param continuous If the action is repeated (continuos) or one time
    struct Strategy {
        string name;
        address creator;
        bytes4[] triggerIds;
        bytes4[] actionIds;
        uint8[][] paramMapping;
        bool continuous;
    }

    /// @dev List of actions grouped as a recipe
    /// @param name Name of the recipe useful for logging what recipe is executing
    /// @param callData Array of calldata inputs to each action
    /// @param subData Used only as part of strategy, subData injected from StrategySub.subData
    /// @param actionIds Array of identifiers for actions - bytes4(keccak256(ActionName))
    /// @param paramMapping Describes how inputs to functions are piped from return/subbed values
    struct Recipe {
        string name;
        bytes[] callData;
        bytes32[] subData;
        bytes4[] actionIds;
        uint8[][] paramMapping;
    }

    /// @dev Actual data of the sub we store on-chain
    /// @dev In order to save on gas we store a keccak256(StrategySub) and verify later on
    /// @param walletAddr Address of the users smart wallet/proxy
    /// @param isEnabled Toggle if the subscription is active
    /// @param strategySubHash Hash of the StrategySub data the user inputted
    struct StoredSubData {
        bytes20 walletAddr; // address but put in bytes20 for gas savings
        bool isEnabled;
        bytes32 strategySubHash;
    }

    /// @dev Instance of a strategy, user supplied data
    /// @param strategyOrBundleId Id of the strategy or bundle, depending on the isBundle bool
    /// @param isBundle If true the id points to bundle, if false points directly to strategyId
    /// @param triggerData User supplied data needed for checking trigger conditions
    /// @param subData User supplied data used in recipe
    struct StrategySub {
        uint64 strategyOrBundleId;
        bool isBundle;
        bytes[] triggerData;
        bytes32[] subData;
    }

    /// @dev Data needed when signing relay transaction
    /// @param maxTxCostInFeeToken Max tx cost user is willing to pay in fee token
    /// @param feeToken Address of the token user is willing to pay fee in
    /// @param tokenPriceInEth Price of the token in ETH
    /// @param deadline Deadline for the relay transaction to be executed
    /// @param shouldTakeFeeFromPosition Flag to indicate if fee should be taken from position, otherwise from EOA/wallet
    struct TxSaverSignedData {
        uint256 maxTxCostInFeeToken;
        address feeToken;
        uint256 tokenPriceInEth;
        uint256 deadline;
        bool shouldTakeFeeFromPosition;
    }
}






contract DFSExchangeData {
    struct OffchainData {
        address wrapper; // dfs wrapper address for the aggregator (must be in WrapperExchangeRegistry)
        address exchangeAddr; // exchange address we are calling to execute the order (must be in ExchangeAggregatorRegistry)
        address allowanceTarget; // exchange aggregator contract we give allowance to
        uint256 price; // expected price that the aggregator sent us
        uint256 protocolFee; // deprecated (used as a separate fee amount for 0x v1)
        bytes callData; // 0ff-chain calldata the aggregator gives to perform the swap
    }

    struct ExchangeData {
        address srcAddr; // source token address (which we're selling)
        address destAddr; // destination token address (which we're buying)
        uint256 srcAmount; // amount of source token in token decimals
        uint256 destAmount; // amount of bought token in token decimals
        uint256 minPrice; // minPrice we are expecting (checked in DFSExchangeCore)
        uint256 dfsFeeDivider; // service fee divider
        address user; // currently deprecated (used to check custom fees for the user)
        address wrapper; // on-chain wrapper address (must be in WrapperExchangeRegistry)
        bytes wrapperData; // on-chain additional data for on-chain (uniswap route for example)
        OffchainData offchainData; // offchain aggregator order
    }

    struct InjectedExchangeData {
        address wrapper; // on-chain wrapper address (must be in WrapperExchangeRegistry)
        bytes wrapperData; // on-chain additional data for on-chain (uniswap route for example)
        OffchainData offchainData; // offchain aggregator order
    }
}






interface IActionBase {
    function executeAction(
        bytes memory _callData,
        bytes32[] memory _subData,
        uint8[] memory _paramMapping,
        bytes32[] memory _returnValues
    ) external payable returns (bytes32);

    function executeActionDirect(bytes memory _callData) external payable;

    function actionType() external pure returns (uint8);
}






interface IBundleStorage {
    function openToPublic() external view returns (bool);
    function createBundle(uint64[] memory _strategyIds) external returns (uint256);
    function changeEditPermission(bool _openToPublic) external;
    function getStrategyId(uint256 _bundleId, uint256 _strategyIndex)
        external
        view
        returns (uint256);
    function getBundle(uint256 _bundleId)
        external
        view
        returns (StrategyModel.StrategyBundle memory);
    function getBundleCount() external view returns (uint256);
    function getPaginatedBundles(uint256 _page, uint256 _perPage)
        external
        view
        returns (StrategyModel.StrategyBundle[] memory);
}







interface IRecipeExecutor {
    function executeRecipe(StrategyModel.Recipe calldata _currRecipe) external payable;

    function executeRecipeFromTxSaver(
        StrategyModel.Recipe calldata _currRecipe,
        StrategyModel.TxSaverSignedData calldata _txSaverData
    ) external payable;

    function executeRecipeFromStrategy(
        uint256 _subId,
        bytes[] calldata _actionCallData,
        bytes[] calldata _triggerCallData,
        uint256 _strategyIndex,
        StrategyModel.StrategySub memory _sub
    ) external payable;

    function executeActionsFromFL(StrategyModel.Recipe calldata _currRecipe, bytes32 _flAmount)
        external
        payable;
}






interface IStrategyStorage {
    function openToPublic() external view returns (bool);
    function createStrategy(
        string memory _name,
        bytes4[] memory _triggerIds,
        bytes4[] memory _actionIds,
        uint8[][] memory _paramMapping,
        bool _continuous
    ) external returns (uint256);
    function changeEditPermission(bool _openToPublic) external;
    function getStrategy(uint256 _strategyId) external view returns (StrategyModel.Strategy memory);
    function getStrategyCount() external view returns (uint256);
    function getPaginatedStrategies(uint256 _page, uint256 _perPage)
        external
        view
        returns (StrategyModel.Strategy[] memory);
}






interface ISubStorage {
    function subscribeToStrategy(StrategyModel.StrategySub memory _sub) external returns (uint256);
    function updateSubData(uint256 _subId, StrategyModel.StrategySub calldata _sub) external;
    function activateSub(uint256 _subId) external;
    function deactivateSub(uint256 _subId) external;
    function getSub(uint256 _subId) external view returns (StrategyModel.StoredSubData memory);
    function getSubsCount() external view returns (uint256);
}







interface ITrigger {
    function isTriggered(bytes memory, bytes memory) external returns (bool);
    function isChangeable() external view returns (bool);
    function changedSubData(bytes memory) external view returns (bytes memory);
}







interface ITxSaverBytesTransientStorage {
    function getFeeType() external view returns (uint256);
    function getBytesTransiently() external view returns (bytes memory result);
}






interface IFlashLoanBase {
    struct FlashLoanParams {
        address[] tokens;
        uint256[] amounts;
        uint256[] modes;
        address onBehalfOf;
        address flParamGetterAddr;
        bytes flParamGetterData;
        bytes recipeData;
    }
}






contract DSMath {
    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x + y;
    }

    function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x - y;
    }

    function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x * y;
    }

    function div(uint256 x, uint256 y) internal pure returns (uint256 z) {
        return x / y;
    }

    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        return x <= y ? x : y;
    }

    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        return x >= y ? x : y;
    }

    function imin(int256 x, int256 y) internal pure returns (int256 z) {
        return x <= y ? x : y;
    }

    function imax(int256 x, int256 y) internal pure returns (int256 z) {
        return x >= y ? x : y;
    }

    uint256 constant WAD = 10 ** 18;
    uint256 constant RAY = 10 ** 27;

    function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, y), WAD / 2) / WAD;
    }

    function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, y), RAY / 2) / RAY;
    }

    function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, WAD), y / 2) / y;
    }

    function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, RAY), y / 2) / y;
    }

    // This famous algorithm is called "exponentiation by squaring"
    // and calculates x^n with x as fixed-point and n as regular unsigned.
    //
    // It's O(log n), instead of O(n) for naive repeated multiplication.
    //
    // These facts are why it works:
    //
    //  If n is even, then x^n = (x^2)^(n/2).
    //  If n is odd,  then x^n = x * x^(n-1),
    //   and applying the equation for even x gives
    //    x^n = x * (x^2)^((n-1) / 2).
    //
    //  Also, EVM division is flooring and
    //    floor[(n-1) / 2] = floor[n / 2].
    //
    function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) {
        z = n % 2 != 0 ? x : RAY;

        for (n /= 2; n != 0; n /= 2) {
            x = rmul(x, x);

            if (n % 2 != 0) {
                z = rmul(z, x);
            }
        }
    }
}







contract MainnetUtilAddresses {
    address internal refillCaller = 0x8973f5e6142ed2e2F50EEE8Bb34a47C2DAa6624a;

    address internal constant FEE_RECIPIENT_ADDR = 0x39C4a92Dc506300c3Ea4c67ca4CA611102ee6F2A;
    address internal constant BOT_REGISTRY_ADDRESS = 0x637726f8b08a7ABE3aE3aCaB01A80E2d8ddeF77B;
    address internal constant UNI_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
    address internal constant MKR_PROXY_REGISTRY = 0x4678f0a6958e4D2Bc4F1BAF7Bc52E8F3564f3fE4;
    address internal constant AAVE_MARKET = 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5;
    address internal constant AAVE_V3_MARKET = 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e;
    address internal constant SPARK_MARKET = 0x02C3eA4e34C0cBd694D2adFa2c690EECbC1793eE;

    address internal constant DFS_PROXY_REGISTRY_ADDR = 0x29474FdaC7142f9aB7773B8e38264FA15E3805ed;

    address internal constant WETH_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address internal constant ETH_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    address internal constant WSTETH_ADDR = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;
    address internal constant STETH_ADDR = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;
    a...

// [truncated — 82536 bytes total]

Read Contract

adminVault 0x8cedca71 → address

Write Contract 5 functions

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

executeActionsFromFL 0x2aeae6ec
tuple _currRecipe
bytes32 _flAmount
executeRecipe 0xe6e3534d
tuple _currRecipe
executeRecipeFromStrategy 0x6a90acf4
uint256 _subId
bytes[] _actionCallData
bytes[] _triggerCallData
uint256 _strategyIndex
tuple _sub
executeRecipeFromTxSaver 0x5dfbd566
tuple _currRecipe
tuple _txSaverData
withdrawStuckFunds 0xc579d490
address _token
address _receiver
uint256 _amount

Recent Transactions

This address has 1 on-chain transactions, but only 1.6% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →