Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 212 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute Tx | 21300769 | 2 hrs ago | IN | 0 ETH | 0.00847784 | ||||
Execute Tx | 21293461 | 26 hrs ago | IN | 0 ETH | 0.02424972 | ||||
Execute Tx | 21291291 | 34 hrs ago | IN | 0 ETH | 0.00340915 | ||||
Execute Tx | 21287540 | 46 hrs ago | IN | 0 ETH | 0.00762432 | ||||
Execute Tx | 21285195 | 2 days ago | IN | 0 ETH | 0.01113989 | ||||
Execute Tx | 21284947 | 2 days ago | IN | 0 ETH | 0.01254943 | ||||
Execute Tx | 21282383 | 2 days ago | IN | 0 ETH | 0.0186679 | ||||
Execute Tx | 21280993 | 2 days ago | IN | 0 ETH | 0.0165327 | ||||
Execute Tx | 21278595 | 3 days ago | IN | 0 ETH | 0.00687194 | ||||
Execute Tx | 21273269 | 3 days ago | IN | 0 ETH | 0.01630096 | ||||
Execute Tx | 21269666 | 4 days ago | IN | 0 ETH | 0.00799436 | ||||
Execute Tx | 21262734 | 5 days ago | IN | 0 ETH | 0.0064951 | ||||
Execute Tx | 21259355 | 5 days ago | IN | 0 ETH | 0.01223629 | ||||
Execute Tx | 21257736 | 6 days ago | IN | 0 ETH | 0.01766046 | ||||
Execute Tx | 21251833 | 6 days ago | IN | 0 ETH | 0.03204033 | ||||
Execute Tx | 21238857 | 8 days ago | IN | 0 ETH | 0.01711446 | ||||
Execute Tx | 21210913 | 12 days ago | IN | 0 ETH | 0.00809529 | ||||
Execute Tx | 21197517 | 14 days ago | IN | 0 ETH | 0.02652392 | ||||
Execute Tx | 21183043 | 16 days ago | IN | 0 ETH | 0.03458732 | ||||
Execute Tx | 21176376 | 17 days ago | IN | 0 ETH | 0.03273347 | ||||
Execute Tx | 21169732 | 18 days ago | IN | 0 ETH | 0.03833209 | ||||
Execute Tx | 21165092 | 19 days ago | IN | 0 ETH | 0.01827248 | ||||
Execute Tx | 21161393 | 19 days ago | IN | 0 ETH | 0.01970174 | ||||
Execute Tx | 21153778 | 20 days ago | IN | 0 ETH | 0.01546335 | ||||
Execute Tx | 21148718 | 21 days ago | IN | 0 ETH | 0.016422 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TxSaverExecutor
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-07-20 */ // SPDX-License-Identifier: MIT pragma solidity =0.8.24; 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 { } contract AdminVault is AuthHelper { address public owner; address public admin; error SenderNotAdmin(); constructor() { owner = msg.sender; admin = ADMIN_ADDR; } /// @notice Admin is able to change owner /// @param _owner Address of new owner function changeOwner(address _owner) public { if (admin != msg.sender){ revert SenderNotAdmin(); } owner = _owner; } /// @notice Admin is able to set new admin /// @param _admin Address of multisig that becomes new admin function changeAdmin(address _admin) public { if (admin != msg.sender){ revert SenderNotAdmin(); } admin = _admin; } } 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 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); } } } } 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 AdminAuth is AuthHelper { using SafeERC20 for IERC20; AdminVault public constant adminVault = AdminVault(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); } } /// @notice Destroy the contract /// @dev Deprecated method, selfdestruct will soon just send eth function kill() public onlyAdmin { selfdestruct(payable(msg.sender)); } } contract DFSRegistry is AdminAuth { error EntryAlreadyExistsError(bytes4); error EntryNonExistentError(bytes4); error EntryNotInChangeError(bytes4); error ChangeNotReadyError(uint256,uint256); error EmptyPrevAddrError(bytes4); error AlreadyInContractChangeError(bytes4); error AlreadyInWaitPeriodChangeError(bytes4); event AddNewContract(address,bytes4,address,uint256); event RevertToPreviousAddress(address,bytes4,address,address); event StartContractChange(address,bytes4,address,address); event ApproveContractChange(address,bytes4,address,address); event CancelContractChange(address,bytes4,address,address); event StartWaitPeriodChange(address,bytes4,uint256); event ApproveWaitPeriodChange(address,bytes4,uint256,uint256); event CancelWaitPeriodChange(address,bytes4,uint256,uint256); struct Entry { address contractAddr; uint256 waitPeriod; uint256 changeStartTime; bool inContractChange; bool inWaitPeriodChange; bool exists; } mapping(bytes4 => Entry) public entries; mapping(bytes4 => address) public previousAddresses; mapping(bytes4 => address) public pendingAddresses; mapping(bytes4 => uint256) public pendingWaitTimes; /// @notice Given an contract id returns the registered address /// @dev Id is keccak256 of the contract name /// @param _id Id of contract function getAddr(bytes4 _id) public view returns (address) { return entries[_id].contractAddr; } /// @notice Helper function to easily query if id is registered /// @param _id Id of contract function isRegistered(bytes4 _id) public view returns (bool) { return entries[_id].exists; } /////////////////////////// OWNER ONLY FUNCTIONS /////////////////////////// /// @notice Adds a new contract to the registry /// @param _id Id of contract /// @param _contractAddr Address of the contract /// @param _waitPeriod Amount of time to wait before a contract address can be changed function addNewContract( bytes4 _id, address _contractAddr, uint256 _waitPeriod ) public onlyOwner { if (entries[_id].exists){ revert EntryAlreadyExistsError(_id); } entries[_id] = Entry({ contractAddr: _contractAddr, waitPeriod: _waitPeriod, changeStartTime: 0, inContractChange: false, inWaitPeriodChange: false, exists: true }); emit AddNewContract(msg.sender, _id, _contractAddr, _waitPeriod); } /// @notice Reverts to the previous address immediately /// @dev In case the new version has a fault, a quick way to fallback to the old contract /// @param _id Id of contract function revertToPreviousAddress(bytes4 _id) public onlyOwner { if (!(entries[_id].exists)){ revert EntryNonExistentError(_id); } if (previousAddresses[_id] == address(0)){ revert EmptyPrevAddrError(_id); } address currentAddr = entries[_id].contractAddr; entries[_id].contractAddr = previousAddresses[_id]; emit RevertToPreviousAddress(msg.sender, _id, currentAddr, previousAddresses[_id]); } /// @notice Starts an address change for an existing entry /// @dev Can override a change that is currently in progress /// @param _id Id of contract /// @param _newContractAddr Address of the new contract function startContractChange(bytes4 _id, address _newContractAddr) public onlyOwner { if (!entries[_id].exists){ revert EntryNonExistentError(_id); } if (entries[_id].inWaitPeriodChange){ revert AlreadyInWaitPeriodChangeError(_id); } entries[_id].changeStartTime = block.timestamp; // solhint-disable-line entries[_id].inContractChange = true; pendingAddresses[_id] = _newContractAddr; emit StartContractChange(msg.sender, _id, entries[_id].contractAddr, _newContractAddr); } /// @notice Changes new contract address, correct time must have passed /// @param _id Id of contract function approveContractChange(bytes4 _id) public onlyOwner { if (!entries[_id].exists){ revert EntryNonExistentError(_id); } if (!entries[_id].inContractChange){ revert EntryNotInChangeError(_id); } if (block.timestamp < (entries[_id].changeStartTime + entries[_id].waitPeriod)){// solhint-disable-line revert ChangeNotReadyError(block.timestamp, (entries[_id].changeStartTime + entries[_id].waitPeriod)); } address oldContractAddr = entries[_id].contractAddr; entries[_id].contractAddr = pendingAddresses[_id]; entries[_id].inContractChange = false; entries[_id].changeStartTime = 0; pendingAddresses[_id] = address(0); previousAddresses[_id] = oldContractAddr; emit ApproveContractChange(msg.sender, _id, oldContractAddr, entries[_id].contractAddr); } /// @notice Cancel pending change /// @param _id Id of contract function cancelContractChange(bytes4 _id) public onlyOwner { if (!entries[_id].exists){ revert EntryNonExistentError(_id); } if (!entries[_id].inContractChange){ revert EntryNotInChangeError(_id); } address oldContractAddr = pendingAddresses[_id]; pendingAddresses[_id] = address(0); entries[_id].inContractChange = false; entries[_id].changeStartTime = 0; emit CancelContractChange(msg.sender, _id, oldContractAddr, entries[_id].contractAddr); } /// @notice Starts the change for waitPeriod /// @param _id Id of contract /// @param _newWaitPeriod New wait time function startWaitPeriodChange(bytes4 _id, uint256 _newWaitPeriod) public onlyOwner { if (!entries[_id].exists){ revert EntryNonExistentError(_id); } if (entries[_id].inContractChange){ revert AlreadyInContractChangeError(_id); } pendingWaitTimes[_id] = _newWaitPeriod; entries[_id].changeStartTime = block.timestamp; // solhint-disable-line entries[_id].inWaitPeriodChange = true; emit StartWaitPeriodChange(msg.sender, _id, _newWaitPeriod); } /// @notice Changes new wait period, correct time must have passed /// @param _id Id of contract function approveWaitPeriodChange(bytes4 _id) public onlyOwner { if (!entries[_id].exists){ revert EntryNonExistentError(_id); } if (!entries[_id].inWaitPeriodChange){ revert EntryNotInChangeError(_id); } if (block.timestamp < (entries[_id].changeStartTime + entries[_id].waitPeriod)){ // solhint-disable-line revert ChangeNotReadyError(block.timestamp, (entries[_id].changeStartTime + entries[_id].waitPeriod)); } uint256 oldWaitTime = entries[_id].waitPeriod; entries[_id].waitPeriod = pendingWaitTimes[_id]; entries[_id].inWaitPeriodChange = false; entries[_id].changeStartTime = 0; pendingWaitTimes[_id] = 0; emit ApproveWaitPeriodChange(msg.sender, _id, oldWaitTime, entries[_id].waitPeriod); } /// @notice Cancel wait period change /// @param _id Id of contract function cancelWaitPeriodChange(bytes4 _id) public onlyOwner { if (!entries[_id].exists){ revert EntryNonExistentError(_id); } if (!entries[_id].inWaitPeriodChange){ revert EntryNotInChangeError(_id); } uint256 oldWaitPeriod = pendingWaitTimes[_id]; pendingWaitTimes[_id] = 0; entries[_id].inWaitPeriodChange = false; entries[_id].changeStartTime = 0; emit CancelWaitPeriodChange(msg.sender, _id, oldWaitPeriod, entries[_id].waitPeriod); } } contract MainnetCoreAddresses { address internal constant REGISTRY_ADDR = 0x287778F121F134C66212FB16c9b53eC991D32f5b; address internal constant PROXY_AUTH_ADDR = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70; address internal constant MODULE_AUTH_ADDR = 0x7407974DDBF539e552F1d051e44573090912CC3D; address internal constant DEFISAVER_LOGGER = 0xcE7a977Cac4a481bc84AC06b2Da0df614e621cf3; address internal constant SUB_STORAGE_ADDR = 0x1612fc28Ee0AB882eC99842Cde0Fc77ff0691e90; address internal constant BUNDLE_STORAGE_ADDR = 0x223c6aDE533851Df03219f6E3D8B763Bd47f84cf; address internal constant STRATEGY_STORAGE_ADDR = 0xF52551F95ec4A2B4299DcC42fbbc576718Dbf933; address internal constant RECIPE_EXECUTOR_ADDR = 0x5029336642814bC51a42bA80BF83a6322110035D; address internal constant BYTES_TRANSIENT_STORAGE = 0xB3FE6f712c8B8c64CD2780ce714A36e7640DDf0f; } contract CoreHelper is MainnetCoreAddresses { } contract BotAuthForTxSaver is AdminAuth { mapping(address => bool) public approvedCallers; /// @notice Checks if the caller is approved /// @param _caller Address of the caller function isApproved(address _caller) public view returns (bool) { return approvedCallers[_caller]; } /// @notice Adds a new bot address which will be able to call TxSaverExecutor /// @param _caller Bot address function addCaller(address _caller) public onlyOwner { approvedCallers[_caller] = true; } /// @notice Removes a bot address so it can't call TxSaverExecutor /// @param _caller Bot address function removeCaller(address _caller) public onlyOwner { approvedCallers[_caller] = false; } } interface ITxSaverBytesTransientStorage { function getFeeType() external view returns (uint256); function getBytesTransiently() external view returns (bytes memory result); } contract TxSaverBytesTransientStorage is ITxSaverBytesTransientStorage { uint256 constant POSITION_FEE_FLAG = 1; uint256 constant EOA_OR_WALLET_FEE_FLAG = 2; function setBytesTransiently(bytes memory _data, bool _takeFeeFromPosition) internal { uint256 dataLength = _data.length; // ensure data follows abi specification, so length will be multiple of 32 when using abi.encode require(dataLength >= 32 && dataLength % 32 == 0); // write flag to first slot to indicate if fee is taken from position or EOA/wallet uint256 flag = _takeFeeFromPosition ? POSITION_FEE_FLAG : EOA_OR_WALLET_FEE_FLAG; assembly { tstore(0, flag) } // write length of _data to second slot assembly { tstore(1, dataLength) } // calculate how many slots at full size are we going to use uint256 chunks = dataLength / 32; uint256 i = 1; // write _data split into bytes32 from slot 2 to slot 2+chunks for (i; i <= chunks; ++i) { uint256 slot = i + 1; bytes32 chunk; assembly { chunk := mload(add(_data, mul(0x20, i))) // chunks are bytes32: _data[0:32] -> _data[32:64] -> etc tstore(slot, chunk) } } } function getFeeType() public view returns (uint256) { uint256 feeType; assembly{ feeType := tload(0) } return feeType; } function getBytesTransiently() public view returns (bytes memory result){ uint256 dataLength; // fetch data length from second slot assembly{ dataLength := tload(1) } // find out how many full size chunks there are uint256 chunks = dataLength / 32; uint256 i = 1; // concat each full size chunk to the result for (i; i <= chunks; ++i) { bytes32 chunk; uint256 slot = i + 1; assembly { chunk := tload(slot) } result = bytes.concat(result, chunk); } } } 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 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 TxSaverExecutor is StrategyModel, AdminAuth, CoreHelper, TxSaverBytesTransientStorage { bytes4 public constant BOT_AUTH_ID_FOR_TX_SAVER = bytes4(keccak256("BotAuthForTxSaver")); bytes4 public constant RECIPE_EXECUTOR_ID = bytes4(keccak256("RecipeExecutor")); DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR); /// Caller must be authorized bot error BotNotApproved(address bot); /// Revert if execution fails when using safe wallet error SafeExecutionError(); /// Revert if signature is expired error TxSaverSignatureExpired(uint256 deadline, uint256 currentTimestamp); /// @notice Data needed to execute a Safe transaction /// @param safe Address of the Safe wallet /// @param refundReceiver Injected address to track safe points /// @param data Data payload of Safe transaction /// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v}) struct SafeTxParams { address safe; address refundReceiver; bytes data; bytes signatures; } /// @notice Execute a TxSaver transaction signed by user /// @notice When taking fee from position, gas fee is taken inside sell action. /// @notice Right now, we only support fee taking from position if recipe has sell action /// /// @notice when fee is taken from EOA/wallet: /// @notice If wallet is 1/1, gas fee is taken from eoa /// @notice If wallet is n/m, gas fee is taken from wallet itself /// /// @param _params SafeTxParams data needed to execute safe tx /// @param _estimatedGas Estimated gas usage for the transaction /// @param _l1GasCostInEth Additional gas cost added for Optimism based L2s /// @param _injectedExchangeData Exchange data injected by backend function executeTx( SafeTxParams calldata _params, uint256 _estimatedGas, uint256 _l1GasCostInEth, DFSExchangeData.InjectedExchangeData calldata _injectedExchangeData ) external { // only authorized bot can call this function if (!BotAuthForTxSaver(registry.getAddr(BOT_AUTH_ID_FOR_TX_SAVER)).isApproved(msg.sender)) { revert BotNotApproved(msg.sender); } (, TxSaverSignedData memory txSaverData) = parseTxSaverSignedData(_params.data); // check if signature is expired if (txSaverData.deadline > 0 && block.timestamp > txSaverData.deadline) { revert TxSaverSignatureExpired(txSaverData.deadline, block.timestamp); } if (txSaverData.shouldTakeFeeFromPosition) { setBytesTransiently( abi.encode(_estimatedGas, _l1GasCostInEth, txSaverData, _injectedExchangeData), txSaverData.shouldTakeFeeFromPosition ); } else { setBytesTransiently( abi.encode(_estimatedGas, _l1GasCostInEth, _injectedExchangeData), txSaverData.shouldTakeFeeFromPosition ); } _executeSafeTx(_params); } function _executeSafeTx(SafeTxParams memory _params) internal { bool success = ISafe(_params.safe).execTransaction( 0x2Ee96Cf53AE5FBd5309284704F978d0cA66cB963, 0, // value _params.data, ISafe.Operation.DelegateCall, 0, // safeTxGas, 0, // baseGas 0, // gasPrice address(0), // gasToken payable(_params.refundReceiver), _params.signatures ); if (!success) { revert SafeExecutionError(); } } function parseTxSaverSignedData(bytes calldata _data) public pure returns (Recipe memory recipe, TxSaverSignedData memory txSaverData) { (recipe, txSaverData) = abi.decode(_data[4:], (Recipe, TxSaverSignedData)); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"BotNotApproved","type":"error"},{"inputs":[],"name":"NonContractCall","type":"error"},{"inputs":[],"name":"SafeExecutionError","type":"error"},{"inputs":[],"name":"SenderNotAdmin","type":"error"},{"inputs":[],"name":"SenderNotOwner","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"TxSaverSignatureExpired","type":"error"},{"inputs":[],"name":"BOT_AUTH_ID_FOR_TX_SAVER","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECIPE_EXECUTOR_ID","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminVault","outputs":[{"internalType":"contract AdminVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"safe","type":"address"},{"internalType":"address","name":"refundReceiver","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"internalType":"struct TxSaverExecutor.SafeTxParams","name":"_params","type":"tuple"},{"internalType":"uint256","name":"_estimatedGas","type":"uint256"},{"internalType":"uint256","name":"_l1GasCostInEth","type":"uint256"},{"components":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"bytes","name":"wrapperData","type":"bytes"},{"components":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct DFSExchangeData.OffchainData","name":"offchainData","type":"tuple"}],"internalType":"struct DFSExchangeData.InjectedExchangeData","name":"_injectedExchangeData","type":"tuple"}],"name":"executeTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBytesTransiently","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"parseTxSaverSignedData","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"bytes[]","name":"callData","type":"bytes[]"},{"internalType":"bytes32[]","name":"subData","type":"bytes32[]"},{"internalType":"bytes4[]","name":"actionIds","type":"bytes4[]"},{"internalType":"uint8[][]","name":"paramMapping","type":"uint8[][]"}],"internalType":"struct StrategyModel.Recipe","name":"recipe","type":"tuple"},{"components":[{"internalType":"uint256","name":"maxTxCostInFeeToken","type":"uint256"},{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"uint256","name":"tokenPriceInEth","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"shouldTakeFeeFromPosition","type":"bool"}],"internalType":"struct StrategyModel.TxSaverSignedData","name":"txSaverData","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract DFSRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b506118a88061001d5f395ff3fe608060405234801561000f575f80fd5b50600436106100b9575f3560e01c8063b0ade5d211610072578063c579d49011610058578063c579d490146101bb578063dc32736a146101ce578063e15851f0146101e1575f80fd5b8063b0ade5d21461014e578063b752bd1c14610163575f80fd5b806341c0e1b5116100a257806341c0e1b5146100f65780637b103999146101005780638cedca7114610133575f80fd5b806318b0a773146100bd5780632d760642146100e7575b5f80fd5b6100d06100cb366004610b50565b610208565b6040516100de929190610d12565b60405180910390f35b6040515f5c81526020016100de565b6100fe610297565b005b61011b73287778f121f134c66212fb16c9b53ec991d32f5b81565b6040516001600160a01b0390911681526020016100de565b61011b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b610156610358565b6040516100de9190610e36565b61018a7f4c69ee1e22cfe3dcbdd1e818d6f188c546b5ce8d358762e14aaee0ba69d5f54881565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100de565b6100fe6101c9366004610e66565b6103c5565b6100fe6101dc366004610ea4565b6104f9565b61018a7f5efaa232c74d4abfb58bad9eacc8008797561139edbc1a4de6db36affd6d807d81565b61023a6040518060a0016040528060608152602001606081526020016060815260200160608152602001606081525090565b6102726040518060a001604052805f81526020015f6001600160a01b031681526020015f81526020015f81526020015f151581525090565b61027f8360048187610f21565b81019061028c91906112fe565b909590945092505050565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103159190611406565b6001600160a01b031614610355576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b606060015c5f610369602083611449565b905060015b8181116103bf575f8061038283600161145c565b9050805c9150858260405160200161039b929190611475565b60405160208183030381529060405295505050806103b890611496565b905061036e565b50505090565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104439190611406565b6001600160a01b031614610483576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee036104e0576040516001600160a01b0383169082156108fc029083905f818181858888f193505050501580156104da573d5f803e3d5ffd5b50505050565b6104f46001600160a01b0384168383610743565b505050565b6040517f93b188540000000000000000000000000000000000000000000000000000000081527f5efaa23200000000000000000000000000000000000000000000000000000000600482015273287778f121f134c66212fb16c9b53ec991d32f5b906393b1885490602401602060405180830381865afa15801561057f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a39190611406565b6040517f673448dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03919091169063673448dd90602401602060405180830381865afa158015610600573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062491906114ae565b610661576040517f6d0a9fef0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b5f6106726100cb60408701876114c9565b9150505f816060015111801561068b5750806060015142115b156106d15760608101516040517f26a4f2980000000000000000000000000000000000000000000000000000000081526004810191909152426024820152604401610658565b8060800151156107135761070e848483856040516020016106f5949392919061165c565b60405160208183030381529060405282608001516107c3565b61072b565b61072b8484846040516020016106f5939291906116c9565b61073c610737866116f0565b61084b565b5050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526104f4908490610943565b8151602081108015906107de57506107dc60208261179d565b155b6107e6575f80fd5b5f826107f35760026107f6565b60015b9050805f5d8160015d5f61080b602084611449565b905060015b818111610843575f61082382600161145c565b6020830288015190915080825d50508061083c90611496565b9050610810565b505050505050565b80516040808301516020840151606085015192517f6a7612020000000000000000000000000000000000000000000000000000000081525f946001600160a01b031693636a761202936108c693732ee96cf53ae5fbd5309284704f978d0ca66cb96393889360019285928392839283929091906004016117b0565b6020604051808303815f875af11580156108e2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090691906114ae565b90508061093f576040517fe540c1c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f610997826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a299092919063ffffffff16565b905080515f14806109b75750808060200190518101906109b791906114ae565b6104f45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610658565b6060610a3784845f85610a3f565b949350505050565b6060610a4a85610b18565b610a80576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80866001600160a01b03168587604051610a9b9190611857565b5f6040518083038185875af1925050503d805f8114610ad5576040519150601f19603f3d011682016040523d82523d5f602084013e610ada565b606091505b50915091508115610aee579150610a379050565b805115610afe5780518082602001fd5b8360405162461bcd60e51b81526004016106589190610e36565b5f813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610a37575050151592915050565b5f8060208385031215610b61575f80fd5b823567ffffffffffffffff80821115610b78575f80fd5b818501915085601f830112610b8b575f80fd5b813581811115610b99575f80fd5b866020828501011115610baa575f80fd5b60209290920196919550909350505050565b5f5b83811015610bd6578181015183820152602001610bbe565b50505f910152565b5f8151808452610bf5816020860160208601610bbc565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b83811015610c3857815187529582019590820190600101610c1c565b509495945050505050565b5f815180845260208085019450602084015f5b83811015610c385781517fffffffff000000000000000000000000000000000000000000000000000000001687529582019590820190600101610c56565b5f82825180855260208086019550808260051b8401018186015f5b84811015610d0557858303601f190189528151805180855290850190858501905f5b81811015610cf057835160ff1683529287019291870191600101610cd1565b50509985019993505090830190600101610caf565b5090979650505050505050565b60c081525f835160a060c0840152610d2e610160840182610bde565b905060208086015160bf19808685030160e08701528382518086528486019150848160051b87010185850194505f5b82811015610d8b57601f19888303018452610d79828751610bde565b95870195938701939150600101610d5d565b5060408b0151965083898203016101008a0152610da88188610c09565b9650505050606088015191508086850301610120870152610dc98483610c43565b935060808801519150808685030161014087015250610de88382610c94565b935050610e2d81850186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b50509392505050565b602081525f610e486020830184610bde565b9392505050565b6001600160a01b0381168114610e63575f80fd5b50565b5f805f60608486031215610e78575f80fd5b8335610e8381610e4f565b92506020840135610e9381610e4f565b929592945050506040919091013590565b5f805f8060808587031215610eb7575f80fd5b843567ffffffffffffffff80821115610ece575f80fd5b9086019060808289031215610ee1575f80fd5b909450602086013593506040860135925060608601359080821115610f04575f80fd5b50850160608188031215610f16575f80fd5b939692955090935050565b5f8085851115610f2f575f80fd5b83861115610f3b575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b60405160a0810167ffffffffffffffff81118282101715610f7f57610f7f610f48565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610fae57610fae610f48565b604052919050565b5f82601f830112610fc5575f80fd5b813567ffffffffffffffff811115610fdf57610fdf610f48565b610ff2601f8201601f1916602001610f85565b818152846020838601011115611006575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff82111561103b5761103b610f48565b5060051b60200190565b5f82601f830112611054575f80fd5b8135602061106961106483611022565b610f85565b82815260059290921b84018101918181019086841115611087575f80fd5b8286015b848110156110c557803567ffffffffffffffff8111156110a9575f80fd5b6110b78986838b0101610fb6565b84525091830191830161108b565b509695505050505050565b5f82601f8301126110df575f80fd5b813560206110ef61106483611022565b8083825260208201915060208460051b870101935086841115611110575f80fd5b602086015b848110156110c55780358352918301918301611115565b5f82601f83011261113b575f80fd5b8135602061114b61106483611022565b8083825260208201915060208460051b87010193508684111561116c575f80fd5b602086015b848110156110c55780357fffffffff00000000000000000000000000000000000000000000000000000000811681146111a8575f80fd5b8352918301918301611171565b5f82601f8301126111c4575f80fd5b813560206111d461106483611022565b828152600592831b85018201928282019190878511156111f2575f80fd5b8387015b85811015610d0557803567ffffffffffffffff811115611214575f80fd5b8801603f81018a13611224575f80fd5b85810135604061123661106483611022565b82815291851b8301810191888101908d841115611251575f80fd5b938201935b83851015611280578435925060ff83168314611270575f80fd5b8282529389019390890190611256565b8852505050938501935084016111f6565b8015158114610e63575f80fd5b5f60a082840312156112ae575f80fd5b6112b6610f5c565b90508135815260208201356112ca81610e4f565b80602083015250604082013560408201526060820135606082015260808201356112f381611291565b608082015292915050565b5f8060c0838503121561130f575f80fd5b823567ffffffffffffffff80821115611326575f80fd5b9084019060a08287031215611339575f80fd5b611341610f5c565b82358281111561134f575f80fd5b61135b88828601610fb6565b82525060208301358281111561136f575f80fd5b61137b88828601611045565b602083015250604083013582811115611392575f80fd5b61139e888286016110d0565b6040830152506060830135828111156113b5575f80fd5b6113c18882860161112c565b6060830152506080830135828111156113d8575f80fd5b6113e4888286016111b5565b6080830152508094505050506113fd846020850161129e565b90509250929050565b5f60208284031215611416575f80fd5b8151610e4881610e4f565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f8261145757611457611421565b500490565b8082018082111561146f5761146f611435565b92915050565b5f8351611486818460208801610bbc565b9190910191825250602001919050565b5f600182016114a7576114a7611435565b5060010190565b5f602082840312156114be575f80fd5b8151610e4881611291565b5f808335601e198436030181126114de575f80fd5b83018035915067ffffffffffffffff8211156114f8575f80fd5b60200191503681900382131561150c575f80fd5b9250929050565b5f808335601e19843603018112611528575f80fd5b830160208101925035905067ffffffffffffffff811115611547575f80fd5b80360382131561150c575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561158981610e4f565b6001600160a01b0380821685526115a36020850185611513565b9250606060208701526115ba606087018483611555565b925050604084013560be198536030181126115d3575f80fd5b8583036040870152840180356115e881610e4f565b8216835260208101356115fa81610e4f565b82166020840152604081013561160f81610e4f565b828116604085015250606081013560608401526080810135608084015261163960a0820182611513565b9250905060c060a084015261165260c084018383611555565b9695505050505050565b5f6101008683528560208401526116ac6040840186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b8060e08401526116be8184018561157d565b979650505050505050565b838152826020820152606060408201525f6116e7606083018461157d565b95945050505050565b5f60808236031215611700575f80fd5b6040516080810167ffffffffffffffff828210818311171561172457611724610f48565b816040528435915061173582610e4f565b90825260208401359061174782610e4f565b8160208401526040850135915080821115611760575f80fd5b61176c36838701610fb6565b60408401526060850135915080821115611784575f80fd5b5061179136828601610fb6565b60608301525092915050565b5f826117ab576117ab611421565b500690565b5f6101406001600160a01b038d1683528b60208401528060408401526117d88184018c610bde565b905060028a106117f657634e487b7160e01b5f52602160045260245ffd5b8960608401528860808401528760a08401528660c084015261182360e08401876001600160a01b03169052565b6001600160a01b0385166101008401528281036101208401526118468185610bde565b9d9c50505050505050505050505050565b5f8251611868818460208701610bbc565b919091019291505056fea264697066735822122026c16c36c81468e50707d2bb1d61c6e30b0efff7297258c7c9b0a2b1081823ff64736f6c63430008180033
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100b9575f3560e01c8063b0ade5d211610072578063c579d49011610058578063c579d490146101bb578063dc32736a146101ce578063e15851f0146101e1575f80fd5b8063b0ade5d21461014e578063b752bd1c14610163575f80fd5b806341c0e1b5116100a257806341c0e1b5146100f65780637b103999146101005780638cedca7114610133575f80fd5b806318b0a773146100bd5780632d760642146100e7575b5f80fd5b6100d06100cb366004610b50565b610208565b6040516100de929190610d12565b60405180910390f35b6040515f5c81526020016100de565b6100fe610297565b005b61011b73287778f121f134c66212fb16c9b53ec991d32f5b81565b6040516001600160a01b0390911681526020016100de565b61011b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b610156610358565b6040516100de9190610e36565b61018a7f4c69ee1e22cfe3dcbdd1e818d6f188c546b5ce8d358762e14aaee0ba69d5f54881565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100de565b6100fe6101c9366004610e66565b6103c5565b6100fe6101dc366004610ea4565b6104f9565b61018a7f5efaa232c74d4abfb58bad9eacc8008797561139edbc1a4de6db36affd6d807d81565b61023a6040518060a0016040528060608152602001606081526020016060815260200160608152602001606081525090565b6102726040518060a001604052805f81526020015f6001600160a01b031681526020015f81526020015f81526020015f151581525090565b61027f8360048187610f21565b81019061028c91906112fe565b909590945092505050565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103159190611406565b6001600160a01b031614610355576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b606060015c5f610369602083611449565b905060015b8181116103bf575f8061038283600161145c565b9050805c9150858260405160200161039b929190611475565b60405160208183030381529060405295505050806103b890611496565b905061036e565b50505090565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104439190611406565b6001600160a01b031614610483576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee036104e0576040516001600160a01b0383169082156108fc029083905f818181858888f193505050501580156104da573d5f803e3d5ffd5b50505050565b6104f46001600160a01b0384168383610743565b505050565b6040517f93b188540000000000000000000000000000000000000000000000000000000081527f5efaa23200000000000000000000000000000000000000000000000000000000600482015273287778f121f134c66212fb16c9b53ec991d32f5b906393b1885490602401602060405180830381865afa15801561057f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a39190611406565b6040517f673448dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03919091169063673448dd90602401602060405180830381865afa158015610600573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062491906114ae565b610661576040517f6d0a9fef0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b5f6106726100cb60408701876114c9565b9150505f816060015111801561068b5750806060015142115b156106d15760608101516040517f26a4f2980000000000000000000000000000000000000000000000000000000081526004810191909152426024820152604401610658565b8060800151156107135761070e848483856040516020016106f5949392919061165c565b60405160208183030381529060405282608001516107c3565b61072b565b61072b8484846040516020016106f5939291906116c9565b61073c610737866116f0565b61084b565b5050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526104f4908490610943565b8151602081108015906107de57506107dc60208261179d565b155b6107e6575f80fd5b5f826107f35760026107f6565b60015b9050805f5d8160015d5f61080b602084611449565b905060015b818111610843575f61082382600161145c565b6020830288015190915080825d50508061083c90611496565b9050610810565b505050505050565b80516040808301516020840151606085015192517f6a7612020000000000000000000000000000000000000000000000000000000081525f946001600160a01b031693636a761202936108c693732ee96cf53ae5fbd5309284704f978d0ca66cb96393889360019285928392839283929091906004016117b0565b6020604051808303815f875af11580156108e2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090691906114ae565b90508061093f576040517fe540c1c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f610997826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a299092919063ffffffff16565b905080515f14806109b75750808060200190518101906109b791906114ae565b6104f45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610658565b6060610a3784845f85610a3f565b949350505050565b6060610a4a85610b18565b610a80576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80866001600160a01b03168587604051610a9b9190611857565b5f6040518083038185875af1925050503d805f8114610ad5576040519150601f19603f3d011682016040523d82523d5f602084013e610ada565b606091505b50915091508115610aee579150610a379050565b805115610afe5780518082602001fd5b8360405162461bcd60e51b81526004016106589190610e36565b5f813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610a37575050151592915050565b5f8060208385031215610b61575f80fd5b823567ffffffffffffffff80821115610b78575f80fd5b818501915085601f830112610b8b575f80fd5b813581811115610b99575f80fd5b866020828501011115610baa575f80fd5b60209290920196919550909350505050565b5f5b83811015610bd6578181015183820152602001610bbe565b50505f910152565b5f8151808452610bf5816020860160208601610bbc565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b83811015610c3857815187529582019590820190600101610c1c565b509495945050505050565b5f815180845260208085019450602084015f5b83811015610c385781517fffffffff000000000000000000000000000000000000000000000000000000001687529582019590820190600101610c56565b5f82825180855260208086019550808260051b8401018186015f5b84811015610d0557858303601f190189528151805180855290850190858501905f5b81811015610cf057835160ff1683529287019291870191600101610cd1565b50509985019993505090830190600101610caf565b5090979650505050505050565b60c081525f835160a060c0840152610d2e610160840182610bde565b905060208086015160bf19808685030160e08701528382518086528486019150848160051b87010185850194505f5b82811015610d8b57601f19888303018452610d79828751610bde565b95870195938701939150600101610d5d565b5060408b0151965083898203016101008a0152610da88188610c09565b9650505050606088015191508086850301610120870152610dc98483610c43565b935060808801519150808685030161014087015250610de88382610c94565b935050610e2d81850186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b50509392505050565b602081525f610e486020830184610bde565b9392505050565b6001600160a01b0381168114610e63575f80fd5b50565b5f805f60608486031215610e78575f80fd5b8335610e8381610e4f565b92506020840135610e9381610e4f565b929592945050506040919091013590565b5f805f8060808587031215610eb7575f80fd5b843567ffffffffffffffff80821115610ece575f80fd5b9086019060808289031215610ee1575f80fd5b909450602086013593506040860135925060608601359080821115610f04575f80fd5b50850160608188031215610f16575f80fd5b939692955090935050565b5f8085851115610f2f575f80fd5b83861115610f3b575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b60405160a0810167ffffffffffffffff81118282101715610f7f57610f7f610f48565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610fae57610fae610f48565b604052919050565b5f82601f830112610fc5575f80fd5b813567ffffffffffffffff811115610fdf57610fdf610f48565b610ff2601f8201601f1916602001610f85565b818152846020838601011115611006575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff82111561103b5761103b610f48565b5060051b60200190565b5f82601f830112611054575f80fd5b8135602061106961106483611022565b610f85565b82815260059290921b84018101918181019086841115611087575f80fd5b8286015b848110156110c557803567ffffffffffffffff8111156110a9575f80fd5b6110b78986838b0101610fb6565b84525091830191830161108b565b509695505050505050565b5f82601f8301126110df575f80fd5b813560206110ef61106483611022565b8083825260208201915060208460051b870101935086841115611110575f80fd5b602086015b848110156110c55780358352918301918301611115565b5f82601f83011261113b575f80fd5b8135602061114b61106483611022565b8083825260208201915060208460051b87010193508684111561116c575f80fd5b602086015b848110156110c55780357fffffffff00000000000000000000000000000000000000000000000000000000811681146111a8575f80fd5b8352918301918301611171565b5f82601f8301126111c4575f80fd5b813560206111d461106483611022565b828152600592831b85018201928282019190878511156111f2575f80fd5b8387015b85811015610d0557803567ffffffffffffffff811115611214575f80fd5b8801603f81018a13611224575f80fd5b85810135604061123661106483611022565b82815291851b8301810191888101908d841115611251575f80fd5b938201935b83851015611280578435925060ff83168314611270575f80fd5b8282529389019390890190611256565b8852505050938501935084016111f6565b8015158114610e63575f80fd5b5f60a082840312156112ae575f80fd5b6112b6610f5c565b90508135815260208201356112ca81610e4f565b80602083015250604082013560408201526060820135606082015260808201356112f381611291565b608082015292915050565b5f8060c0838503121561130f575f80fd5b823567ffffffffffffffff80821115611326575f80fd5b9084019060a08287031215611339575f80fd5b611341610f5c565b82358281111561134f575f80fd5b61135b88828601610fb6565b82525060208301358281111561136f575f80fd5b61137b88828601611045565b602083015250604083013582811115611392575f80fd5b61139e888286016110d0565b6040830152506060830135828111156113b5575f80fd5b6113c18882860161112c565b6060830152506080830135828111156113d8575f80fd5b6113e4888286016111b5565b6080830152508094505050506113fd846020850161129e565b90509250929050565b5f60208284031215611416575f80fd5b8151610e4881610e4f565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f8261145757611457611421565b500490565b8082018082111561146f5761146f611435565b92915050565b5f8351611486818460208801610bbc565b9190910191825250602001919050565b5f600182016114a7576114a7611435565b5060010190565b5f602082840312156114be575f80fd5b8151610e4881611291565b5f808335601e198436030181126114de575f80fd5b83018035915067ffffffffffffffff8211156114f8575f80fd5b60200191503681900382131561150c575f80fd5b9250929050565b5f808335601e19843603018112611528575f80fd5b830160208101925035905067ffffffffffffffff811115611547575f80fd5b80360382131561150c575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561158981610e4f565b6001600160a01b0380821685526115a36020850185611513565b9250606060208701526115ba606087018483611555565b925050604084013560be198536030181126115d3575f80fd5b8583036040870152840180356115e881610e4f565b8216835260208101356115fa81610e4f565b82166020840152604081013561160f81610e4f565b828116604085015250606081013560608401526080810135608084015261163960a0820182611513565b9250905060c060a084015261165260c084018383611555565b9695505050505050565b5f6101008683528560208401526116ac6040840186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b8060e08401526116be8184018561157d565b979650505050505050565b838152826020820152606060408201525f6116e7606083018461157d565b95945050505050565b5f60808236031215611700575f80fd5b6040516080810167ffffffffffffffff828210818311171561172457611724610f48565b816040528435915061173582610e4f565b90825260208401359061174782610e4f565b8160208401526040850135915080821115611760575f80fd5b61176c36838701610fb6565b60408401526060850135915080821115611784575f80fd5b5061179136828601610fb6565b60608301525092915050565b5f826117ab576117ab611421565b500690565b5f6101406001600160a01b038d1683528b60208401528060408401526117d88184018c610bde565b905060028a106117f657634e487b7160e01b5f52602160045260245ffd5b8960608401528860808401528760a08401528660c084015261182360e08401876001600160a01b03169052565b6001600160a01b0385166101008401528281036101208401526118468185610bde565b9d9c50505050505050505050505050565b5f8251611868818460208701610bbc565b919091019291505056fea264697066735822122026c16c36c81468e50707d2bb1d61c6e30b0efff7297258c7c9b0a2b1081823ff64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.