ETH Price: $3,684.20 (+2.32%)

Contract

0x475f433407205557E8A7aeE7Be53155EB9681c92
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Execute Tx213007692024-11-30 13:23:594 hrs ago1732973039IN
0x475f4334...EB9681c92
0 ETH0.008477848.88995426
Execute Tx212934612024-11-29 12:50:2328 hrs ago1732884623IN
0x475f4334...EB9681c92
0 ETH0.0242497210.66900102
Execute Tx212912912024-11-29 5:33:2335 hrs ago1732858403IN
0x475f4334...EB9681c92
0 ETH0.003409157.51027085
Execute Tx212875402024-11-28 16:58:112 days ago1732813091IN
0x475f4334...EB9681c92
0 ETH0.0076243212.31674952
Execute Tx212851952024-11-28 9:06:352 days ago1732784795IN
0x475f4334...EB9681c92
0 ETH0.0111398910.52442953
Execute Tx212849472024-11-28 8:16:472 days ago1732781807IN
0x475f4334...EB9681c92
0 ETH0.012549439.60456866
Execute Tx212823832024-11-27 23:32:112 days ago1732750331IN
0x475f4334...EB9681c92
0 ETH0.018667915.87379929
Execute Tx212809932024-11-27 18:52:232 days ago1732733543IN
0x475f4334...EB9681c92
0 ETH0.016532720.11393281
Execute Tx212785952024-11-27 10:49:113 days ago1732704551IN
0x475f4334...EB9681c92
0 ETH0.0068719413.80563848
Execute Tx212732692024-11-26 16:58:474 days ago1732640327IN
0x475f4334...EB9681c92
0 ETH0.0163009616.68604179
Execute Tx212696662024-11-26 4:54:234 days ago1732596863IN
0x475f4334...EB9681c92
0 ETH0.007994366.93164823
Execute Tx212627342024-11-25 5:38:355 days ago1732513115IN
0x475f4334...EB9681c92
0 ETH0.00649517.85304343
Execute Tx212593552024-11-24 18:20:355 days ago1732472435IN
0x475f4334...EB9681c92
0 ETH0.0122362911.55211777
Execute Tx212577362024-11-24 12:55:116 days ago1732452911IN
0x475f4334...EB9681c92
0 ETH0.0176604621.09654264
Execute Tx212518332024-11-23 17:08:117 days ago1732381691IN
0x475f4334...EB9681c92
0 ETH0.0320403328.854741
Execute Tx212388572024-11-21 21:40:478 days ago1732225247IN
0x475f4334...EB9681c92
0 ETH0.0171144615.55922241
Execute Tx212109132024-11-18 0:07:4712 days ago1731888467IN
0x475f4334...EB9681c92
0 ETH0.0080952910.10850777
Execute Tx211975172024-11-16 3:18:1114 days ago1731727091IN
0x475f4334...EB9681c92
0 ETH0.0265239215.31874794
Execute Tx211830432024-11-14 2:47:3516 days ago1731552455IN
0x475f4334...EB9681c92
0 ETH0.0345873242.3565278
Execute Tx211763762024-11-13 4:27:2317 days ago1731472043IN
0x475f4334...EB9681c92
0 ETH0.0327334725.06633715
Execute Tx211697322024-11-12 6:11:5918 days ago1731391919IN
0x475f4334...EB9681c92
0 ETH0.0383320926.406662
Execute Tx211650922024-11-11 14:39:2319 days ago1731335963IN
0x475f4334...EB9681c92
0 ETH0.0182724819.19564108
Execute Tx211613932024-11-11 2:16:2319 days ago1731291383IN
0x475f4334...EB9681c92
0 ETH0.0197017416.44634208
Execute Tx211537782024-11-10 0:47:4720 days ago1731199667IN
0x475f4334...EB9681c92
0 ETH0.0154633511.9497561
Execute Tx211487182024-11-09 7:51:2321 days ago1731138683IN
0x475f4334...EB9681c92
0 ETH0.01642211.69601119
VIEW ADVANCED FILTER

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

Optimization Enabled:
Yes with 1000 runs

Other Settings:
cancun EvmVersion, MIT license

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

Contract ABI

[{"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"}]

608060405234801561000f575f80fd5b506118a88061001d5f395ff3fe608060405234801561000f575f80fd5b50600436106100b9575f3560e01c8063b0ade5d211610072578063c579d49011610058578063c579d490146101bb578063dc32736a146101ce578063e15851f0146101e1575f80fd5b8063b0ade5d21461014e578063b752bd1c14610163575f80fd5b806341c0e1b5116100a257806341c0e1b5146100f65780637b103999146101005780638cedca7114610133575f80fd5b806318b0a773146100bd5780632d760642146100e7575b5f80fd5b6100d06100cb366004610b50565b610208565b6040516100de929190610d12565b60405180910390f35b6040515f5c81526020016100de565b6100fe610297565b005b61011b73287778f121f134c66212fb16c9b53ec991d32f5b81565b6040516001600160a01b0390911681526020016100de565b61011b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b610156610358565b6040516100de9190610e36565b61018a7f4c69ee1e22cfe3dcbdd1e818d6f188c546b5ce8d358762e14aaee0ba69d5f54881565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100de565b6100fe6101c9366004610e66565b6103c5565b6100fe6101dc366004610ea4565b6104f9565b61018a7f5efaa232c74d4abfb58bad9eacc8008797561139edbc1a4de6db36affd6d807d81565b61023a6040518060a0016040528060608152602001606081526020016060815260200160608152602001606081525090565b6102726040518060a001604052805f81526020015f6001600160a01b031681526020015f81526020015f81526020015f151581525090565b61027f8360048187610f21565b81019061028c91906112fe565b909590945092505050565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103159190611406565b6001600160a01b031614610355576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b606060015c5f610369602083611449565b905060015b8181116103bf575f8061038283600161145c565b9050805c9150858260405160200161039b929190611475565b60405160208183030381529060405295505050806103b890611496565b905061036e565b50505090565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104439190611406565b6001600160a01b031614610483576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee036104e0576040516001600160a01b0383169082156108fc029083905f818181858888f193505050501580156104da573d5f803e3d5ffd5b50505050565b6104f46001600160a01b0384168383610743565b505050565b6040517f93b188540000000000000000000000000000000000000000000000000000000081527f5efaa23200000000000000000000000000000000000000000000000000000000600482015273287778f121f134c66212fb16c9b53ec991d32f5b906393b1885490602401602060405180830381865afa15801561057f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a39190611406565b6040517f673448dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03919091169063673448dd90602401602060405180830381865afa158015610600573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062491906114ae565b610661576040517f6d0a9fef0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b5f6106726100cb60408701876114c9565b9150505f816060015111801561068b5750806060015142115b156106d15760608101516040517f26a4f2980000000000000000000000000000000000000000000000000000000081526004810191909152426024820152604401610658565b8060800151156107135761070e848483856040516020016106f5949392919061165c565b60405160208183030381529060405282608001516107c3565b61072b565b61072b8484846040516020016106f5939291906116c9565b61073c610737866116f0565b61084b565b5050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526104f4908490610943565b8151602081108015906107de57506107dc60208261179d565b155b6107e6575f80fd5b5f826107f35760026107f6565b60015b9050805f5d8160015d5f61080b602084611449565b905060015b818111610843575f61082382600161145c565b6020830288015190915080825d50508061083c90611496565b9050610810565b505050505050565b80516040808301516020840151606085015192517f6a7612020000000000000000000000000000000000000000000000000000000081525f946001600160a01b031693636a761202936108c693732ee96cf53ae5fbd5309284704f978d0ca66cb96393889360019285928392839283929091906004016117b0565b6020604051808303815f875af11580156108e2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090691906114ae565b90508061093f576040517fe540c1c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f610997826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a299092919063ffffffff16565b905080515f14806109b75750808060200190518101906109b791906114ae565b6104f45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610658565b6060610a3784845f85610a3f565b949350505050565b6060610a4a85610b18565b610a80576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80866001600160a01b03168587604051610a9b9190611857565b5f6040518083038185875af1925050503d805f8114610ad5576040519150601f19603f3d011682016040523d82523d5f602084013e610ada565b606091505b50915091508115610aee579150610a379050565b805115610afe5780518082602001fd5b8360405162461bcd60e51b81526004016106589190610e36565b5f813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610a37575050151592915050565b5f8060208385031215610b61575f80fd5b823567ffffffffffffffff80821115610b78575f80fd5b818501915085601f830112610b8b575f80fd5b813581811115610b99575f80fd5b866020828501011115610baa575f80fd5b60209290920196919550909350505050565b5f5b83811015610bd6578181015183820152602001610bbe565b50505f910152565b5f8151808452610bf5816020860160208601610bbc565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b83811015610c3857815187529582019590820190600101610c1c565b509495945050505050565b5f815180845260208085019450602084015f5b83811015610c385781517fffffffff000000000000000000000000000000000000000000000000000000001687529582019590820190600101610c56565b5f82825180855260208086019550808260051b8401018186015f5b84811015610d0557858303601f190189528151805180855290850190858501905f5b81811015610cf057835160ff1683529287019291870191600101610cd1565b50509985019993505090830190600101610caf565b5090979650505050505050565b60c081525f835160a060c0840152610d2e610160840182610bde565b905060208086015160bf19808685030160e08701528382518086528486019150848160051b87010185850194505f5b82811015610d8b57601f19888303018452610d79828751610bde565b95870195938701939150600101610d5d565b5060408b0151965083898203016101008a0152610da88188610c09565b9650505050606088015191508086850301610120870152610dc98483610c43565b935060808801519150808685030161014087015250610de88382610c94565b935050610e2d81850186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b50509392505050565b602081525f610e486020830184610bde565b9392505050565b6001600160a01b0381168114610e63575f80fd5b50565b5f805f60608486031215610e78575f80fd5b8335610e8381610e4f565b92506020840135610e9381610e4f565b929592945050506040919091013590565b5f805f8060808587031215610eb7575f80fd5b843567ffffffffffffffff80821115610ece575f80fd5b9086019060808289031215610ee1575f80fd5b909450602086013593506040860135925060608601359080821115610f04575f80fd5b50850160608188031215610f16575f80fd5b939692955090935050565b5f8085851115610f2f575f80fd5b83861115610f3b575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b60405160a0810167ffffffffffffffff81118282101715610f7f57610f7f610f48565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610fae57610fae610f48565b604052919050565b5f82601f830112610fc5575f80fd5b813567ffffffffffffffff811115610fdf57610fdf610f48565b610ff2601f8201601f1916602001610f85565b818152846020838601011115611006575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff82111561103b5761103b610f48565b5060051b60200190565b5f82601f830112611054575f80fd5b8135602061106961106483611022565b610f85565b82815260059290921b84018101918181019086841115611087575f80fd5b8286015b848110156110c557803567ffffffffffffffff8111156110a9575f80fd5b6110b78986838b0101610fb6565b84525091830191830161108b565b509695505050505050565b5f82601f8301126110df575f80fd5b813560206110ef61106483611022565b8083825260208201915060208460051b870101935086841115611110575f80fd5b602086015b848110156110c55780358352918301918301611115565b5f82601f83011261113b575f80fd5b8135602061114b61106483611022565b8083825260208201915060208460051b87010193508684111561116c575f80fd5b602086015b848110156110c55780357fffffffff00000000000000000000000000000000000000000000000000000000811681146111a8575f80fd5b8352918301918301611171565b5f82601f8301126111c4575f80fd5b813560206111d461106483611022565b828152600592831b85018201928282019190878511156111f2575f80fd5b8387015b85811015610d0557803567ffffffffffffffff811115611214575f80fd5b8801603f81018a13611224575f80fd5b85810135604061123661106483611022565b82815291851b8301810191888101908d841115611251575f80fd5b938201935b83851015611280578435925060ff83168314611270575f80fd5b8282529389019390890190611256565b8852505050938501935084016111f6565b8015158114610e63575f80fd5b5f60a082840312156112ae575f80fd5b6112b6610f5c565b90508135815260208201356112ca81610e4f565b80602083015250604082013560408201526060820135606082015260808201356112f381611291565b608082015292915050565b5f8060c0838503121561130f575f80fd5b823567ffffffffffffffff80821115611326575f80fd5b9084019060a08287031215611339575f80fd5b611341610f5c565b82358281111561134f575f80fd5b61135b88828601610fb6565b82525060208301358281111561136f575f80fd5b61137b88828601611045565b602083015250604083013582811115611392575f80fd5b61139e888286016110d0565b6040830152506060830135828111156113b5575f80fd5b6113c18882860161112c565b6060830152506080830135828111156113d8575f80fd5b6113e4888286016111b5565b6080830152508094505050506113fd846020850161129e565b90509250929050565b5f60208284031215611416575f80fd5b8151610e4881610e4f565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f8261145757611457611421565b500490565b8082018082111561146f5761146f611435565b92915050565b5f8351611486818460208801610bbc565b9190910191825250602001919050565b5f600182016114a7576114a7611435565b5060010190565b5f602082840312156114be575f80fd5b8151610e4881611291565b5f808335601e198436030181126114de575f80fd5b83018035915067ffffffffffffffff8211156114f8575f80fd5b60200191503681900382131561150c575f80fd5b9250929050565b5f808335601e19843603018112611528575f80fd5b830160208101925035905067ffffffffffffffff811115611547575f80fd5b80360382131561150c575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561158981610e4f565b6001600160a01b0380821685526115a36020850185611513565b9250606060208701526115ba606087018483611555565b925050604084013560be198536030181126115d3575f80fd5b8583036040870152840180356115e881610e4f565b8216835260208101356115fa81610e4f565b82166020840152604081013561160f81610e4f565b828116604085015250606081013560608401526080810135608084015261163960a0820182611513565b9250905060c060a084015261165260c084018383611555565b9695505050505050565b5f6101008683528560208401526116ac6040840186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b8060e08401526116be8184018561157d565b979650505050505050565b838152826020820152606060408201525f6116e7606083018461157d565b95945050505050565b5f60808236031215611700575f80fd5b6040516080810167ffffffffffffffff828210818311171561172457611724610f48565b816040528435915061173582610e4f565b90825260208401359061174782610e4f565b8160208401526040850135915080821115611760575f80fd5b61176c36838701610fb6565b60408401526060850135915080821115611784575f80fd5b5061179136828601610fb6565b60608301525092915050565b5f826117ab576117ab611421565b500690565b5f6101406001600160a01b038d1683528b60208401528060408401526117d88184018c610bde565b905060028a106117f657634e487b7160e01b5f52602160045260245ffd5b8960608401528860808401528760a08401528660c084015261182360e08401876001600160a01b03169052565b6001600160a01b0385166101008401528281036101208401526118468185610bde565b9d9c50505050505050505050505050565b5f8251611868818460208701610bbc565b919091019291505056fea264697066735822122026c16c36c81468e50707d2bb1d61c6e30b0efff7297258c7c9b0a2b1081823ff64736f6c63430008180033

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106100b9575f3560e01c8063b0ade5d211610072578063c579d49011610058578063c579d490146101bb578063dc32736a146101ce578063e15851f0146101e1575f80fd5b8063b0ade5d21461014e578063b752bd1c14610163575f80fd5b806341c0e1b5116100a257806341c0e1b5146100f65780637b103999146101005780638cedca7114610133575f80fd5b806318b0a773146100bd5780632d760642146100e7575b5f80fd5b6100d06100cb366004610b50565b610208565b6040516100de929190610d12565b60405180910390f35b6040515f5c81526020016100de565b6100fe610297565b005b61011b73287778f121f134c66212fb16c9b53ec991d32f5b81565b6040516001600160a01b0390911681526020016100de565b61011b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b610156610358565b6040516100de9190610e36565b61018a7f4c69ee1e22cfe3dcbdd1e818d6f188c546b5ce8d358762e14aaee0ba69d5f54881565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100de565b6100fe6101c9366004610e66565b6103c5565b6100fe6101dc366004610ea4565b6104f9565b61018a7f5efaa232c74d4abfb58bad9eacc8008797561139edbc1a4de6db36affd6d807d81565b61023a6040518060a0016040528060608152602001606081526020016060815260200160608152602001606081525090565b6102726040518060a001604052805f81526020015f6001600160a01b031681526020015f81526020015f81526020015f151581525090565b61027f8360048187610f21565b81019061028c91906112fe565b909590945092505050565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103159190611406565b6001600160a01b031614610355576040517fa6c827a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33ff5b606060015c5f610369602083611449565b905060015b8181116103bf575f8061038283600161145c565b9050805c9150858260405160200161039b929190611475565b60405160208183030381529060405295505050806103b890611496565b905061036e565b50505090565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104439190611406565b6001600160a01b031614610483576040517f19494c8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee036104e0576040516001600160a01b0383169082156108fc029083905f818181858888f193505050501580156104da573d5f803e3d5ffd5b50505050565b6104f46001600160a01b0384168383610743565b505050565b6040517f93b188540000000000000000000000000000000000000000000000000000000081527f5efaa23200000000000000000000000000000000000000000000000000000000600482015273287778f121f134c66212fb16c9b53ec991d32f5b906393b1885490602401602060405180830381865afa15801561057f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a39190611406565b6040517f673448dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03919091169063673448dd90602401602060405180830381865afa158015610600573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062491906114ae565b610661576040517f6d0a9fef0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b5f6106726100cb60408701876114c9565b9150505f816060015111801561068b5750806060015142115b156106d15760608101516040517f26a4f2980000000000000000000000000000000000000000000000000000000081526004810191909152426024820152604401610658565b8060800151156107135761070e848483856040516020016106f5949392919061165c565b60405160208183030381529060405282608001516107c3565b61072b565b61072b8484846040516020016106f5939291906116c9565b61073c610737866116f0565b61084b565b5050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526104f4908490610943565b8151602081108015906107de57506107dc60208261179d565b155b6107e6575f80fd5b5f826107f35760026107f6565b60015b9050805f5d8160015d5f61080b602084611449565b905060015b818111610843575f61082382600161145c565b6020830288015190915080825d50508061083c90611496565b9050610810565b505050505050565b80516040808301516020840151606085015192517f6a7612020000000000000000000000000000000000000000000000000000000081525f946001600160a01b031693636a761202936108c693732ee96cf53ae5fbd5309284704f978d0ca66cb96393889360019285928392839283929091906004016117b0565b6020604051808303815f875af11580156108e2573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061090691906114ae565b90508061093f576040517fe540c1c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b5f610997826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a299092919063ffffffff16565b905080515f14806109b75750808060200190518101906109b791906114ae565b6104f45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610658565b6060610a3784845f85610a3f565b949350505050565b6060610a4a85610b18565b610a80576040517f304619b500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80866001600160a01b03168587604051610a9b9190611857565b5f6040518083038185875af1925050503d805f8114610ad5576040519150601f19603f3d011682016040523d82523d5f602084013e610ada565b606091505b50915091508115610aee579150610a379050565b805115610afe5780518082602001fd5b8360405162461bcd60e51b81526004016106589190610e36565b5f813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610a37575050151592915050565b5f8060208385031215610b61575f80fd5b823567ffffffffffffffff80821115610b78575f80fd5b818501915085601f830112610b8b575f80fd5b813581811115610b99575f80fd5b866020828501011115610baa575f80fd5b60209290920196919550909350505050565b5f5b83811015610bd6578181015183820152602001610bbe565b50505f910152565b5f8151808452610bf5816020860160208601610bbc565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b83811015610c3857815187529582019590820190600101610c1c565b509495945050505050565b5f815180845260208085019450602084015f5b83811015610c385781517fffffffff000000000000000000000000000000000000000000000000000000001687529582019590820190600101610c56565b5f82825180855260208086019550808260051b8401018186015f5b84811015610d0557858303601f190189528151805180855290850190858501905f5b81811015610cf057835160ff1683529287019291870191600101610cd1565b50509985019993505090830190600101610caf565b5090979650505050505050565b60c081525f835160a060c0840152610d2e610160840182610bde565b905060208086015160bf19808685030160e08701528382518086528486019150848160051b87010185850194505f5b82811015610d8b57601f19888303018452610d79828751610bde565b95870195938701939150600101610d5d565b5060408b0151965083898203016101008a0152610da88188610c09565b9650505050606088015191508086850301610120870152610dc98483610c43565b935060808801519150808685030161014087015250610de88382610c94565b935050610e2d81850186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b50509392505050565b602081525f610e486020830184610bde565b9392505050565b6001600160a01b0381168114610e63575f80fd5b50565b5f805f60608486031215610e78575f80fd5b8335610e8381610e4f565b92506020840135610e9381610e4f565b929592945050506040919091013590565b5f805f8060808587031215610eb7575f80fd5b843567ffffffffffffffff80821115610ece575f80fd5b9086019060808289031215610ee1575f80fd5b909450602086013593506040860135925060608601359080821115610f04575f80fd5b50850160608188031215610f16575f80fd5b939692955090935050565b5f8085851115610f2f575f80fd5b83861115610f3b575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b60405160a0810167ffffffffffffffff81118282101715610f7f57610f7f610f48565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610fae57610fae610f48565b604052919050565b5f82601f830112610fc5575f80fd5b813567ffffffffffffffff811115610fdf57610fdf610f48565b610ff2601f8201601f1916602001610f85565b818152846020838601011115611006575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff82111561103b5761103b610f48565b5060051b60200190565b5f82601f830112611054575f80fd5b8135602061106961106483611022565b610f85565b82815260059290921b84018101918181019086841115611087575f80fd5b8286015b848110156110c557803567ffffffffffffffff8111156110a9575f80fd5b6110b78986838b0101610fb6565b84525091830191830161108b565b509695505050505050565b5f82601f8301126110df575f80fd5b813560206110ef61106483611022565b8083825260208201915060208460051b870101935086841115611110575f80fd5b602086015b848110156110c55780358352918301918301611115565b5f82601f83011261113b575f80fd5b8135602061114b61106483611022565b8083825260208201915060208460051b87010193508684111561116c575f80fd5b602086015b848110156110c55780357fffffffff00000000000000000000000000000000000000000000000000000000811681146111a8575f80fd5b8352918301918301611171565b5f82601f8301126111c4575f80fd5b813560206111d461106483611022565b828152600592831b85018201928282019190878511156111f2575f80fd5b8387015b85811015610d0557803567ffffffffffffffff811115611214575f80fd5b8801603f81018a13611224575f80fd5b85810135604061123661106483611022565b82815291851b8301810191888101908d841115611251575f80fd5b938201935b83851015611280578435925060ff83168314611270575f80fd5b8282529389019390890190611256565b8852505050938501935084016111f6565b8015158114610e63575f80fd5b5f60a082840312156112ae575f80fd5b6112b6610f5c565b90508135815260208201356112ca81610e4f565b80602083015250604082013560408201526060820135606082015260808201356112f381611291565b608082015292915050565b5f8060c0838503121561130f575f80fd5b823567ffffffffffffffff80821115611326575f80fd5b9084019060a08287031215611339575f80fd5b611341610f5c565b82358281111561134f575f80fd5b61135b88828601610fb6565b82525060208301358281111561136f575f80fd5b61137b88828601611045565b602083015250604083013582811115611392575f80fd5b61139e888286016110d0565b6040830152506060830135828111156113b5575f80fd5b6113c18882860161112c565b6060830152506080830135828111156113d8575f80fd5b6113e4888286016111b5565b6080830152508094505050506113fd846020850161129e565b90509250929050565b5f60208284031215611416575f80fd5b8151610e4881610e4f565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f8261145757611457611421565b500490565b8082018082111561146f5761146f611435565b92915050565b5f8351611486818460208801610bbc565b9190910191825250602001919050565b5f600182016114a7576114a7611435565b5060010190565b5f602082840312156114be575f80fd5b8151610e4881611291565b5f808335601e198436030181126114de575f80fd5b83018035915067ffffffffffffffff8211156114f8575f80fd5b60200191503681900382131561150c575f80fd5b9250929050565b5f808335601e19843603018112611528575f80fd5b830160208101925035905067ffffffffffffffff811115611547575f80fd5b80360382131561150c575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f813561158981610e4f565b6001600160a01b0380821685526115a36020850185611513565b9250606060208701526115ba606087018483611555565b925050604084013560be198536030181126115d3575f80fd5b8583036040870152840180356115e881610e4f565b8216835260208101356115fa81610e4f565b82166020840152604081013561160f81610e4f565b828116604085015250606081013560608401526080810135608084015261163960a0820182611513565b9250905060c060a084015261165260c084018383611555565b9695505050505050565b5f6101008683528560208401526116ac6040840186805182526001600160a01b03602082015116602083015260408101516040830152606081015160608301526080810151151560808301525050565b8060e08401526116be8184018561157d565b979650505050505050565b838152826020820152606060408201525f6116e7606083018461157d565b95945050505050565b5f60808236031215611700575f80fd5b6040516080810167ffffffffffffffff828210818311171561172457611724610f48565b816040528435915061173582610e4f565b90825260208401359061174782610e4f565b8160208401526040850135915080821115611760575f80fd5b61176c36838701610fb6565b60408401526060850135915080821115611784575f80fd5b5061179136828601610fb6565b60608301525092915050565b5f826117ab576117ab611421565b500690565b5f6101406001600160a01b038d1683528b60208401528060408401526117d88184018c610bde565b905060028a106117f657634e487b7160e01b5f52602160045260245ffd5b8960608401528860808401528760a08401528660c084015261182360e08401876001600160a01b03169052565b6001600160a01b0385166101008401528281036101208401526118468185610bde565b9d9c50505050505050505050505050565b5f8251611868818460208701610bbc565b919091019291505056fea264697066735822122026c16c36c81468e50707d2bb1d61c6e30b0efff7297258c7c9b0a2b1081823ff64736f6c63430008180033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.