S Price: $0.068041 (+1.49%)
Gas: 55 Gwei

Contract

0x8a725d6D36bBD09feCC5bD9a37eb7fCa34895A40

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Execute610164022026-01-23 20:05:022 days ago1769198702IN
0x8a725d6D...a34895A40
0 S0.008539850
Burn610127392026-01-23 18:58:593 days ago1769194739IN
0x8a725d6D...a34895A40
0 S0.1974435155
Burn609082702026-01-22 8:21:414 days ago1769070101IN
0x8a725d6D...a34895A40
0 S0.1981534555
Execute608854482026-01-21 23:40:164 days ago1769038816IN
0x8a725d6D...a34895A40
0 S0.2547777750.000378
Execute608854382026-01-21 23:40:114 days ago1769038811IN
0x8a725d6D...a34895A40
0 S0.267961550
Execute608854352026-01-21 23:40:074 days ago1769038807IN
0x8a725d6D...a34895A40
0 S0.267960950
Set Default Conf...608854302026-01-21 23:40:024 days ago1769038802IN
0x8a725d6D...a34895A40
0 S0.0092376150.38461538
Execute605334742026-01-16 20:05:029 days ago1768593902IN
0x8a725d6D...a34895A40
0 S0.0064303550
Execute604038282026-01-14 23:40:1511 days ago1768434015IN
0x8a725d6D...a34895A40
0 S0.185141750
Execute604038252026-01-14 23:40:1111 days ago1768434011IN
0x8a725d6D...a34895A40
0 S0.194691250
Execute604038222026-01-14 23:40:0711 days ago1768434007IN
0x8a725d6D...a34895A40
0 S0.194690650
Set Default Conf...604038182026-01-14 23:40:0311 days ago1768434003IN
0x8a725d6D...a34895A40
0 S0.004064350
Execute600314192026-01-09 20:05:0116 days ago1767989101IN
0x8a725d6D...a34895A40
0 S0.0063659550
Mint599954022026-01-09 11:07:4517 days ago1767956865IN
0x8a725d6D...a34895A40
0 S0.0120727255
Execute598662832026-01-07 23:40:1818 days ago1767829218IN
0x8a725d6D...a34895A40
0 S0.0132637550
Execute598662792026-01-07 23:40:1418 days ago1767829214IN
0x8a725d6D...a34895A40
0 S0.1946950
Execute598662752026-01-07 23:40:1018 days ago1767829210IN
0x8a725d6D...a34895A40
0 S0.194691250
Execute598662702026-01-07 23:40:0518 days ago1767829205IN
0x8a725d6D...a34895A40
0 S0.194690650
Set Default Conf...598662642026-01-07 23:40:0118 days ago1767829201IN
0x8a725d6D...a34895A40
0 S0.005069850
Execute597564102026-01-06 15:41:3820 days ago1767714098IN
0x8a725d6D...a34895A40
0 S0.0132497761.48615384
Burn593515002026-01-01 6:48:5625 days ago1767250136IN
0x8a725d6D...a34895A40
0 S0.1993935355
Execute593343032025-12-31 23:40:1925 days ago1767224419IN
0x8a725d6D...a34895A40
0 S0.0174474550
Execute593342982025-12-31 23:40:1525 days ago1767224415IN
0x8a725d6D...a34895A40
0 S0.267960350
Execute593342912025-12-31 23:40:1025 days ago1767224410IN
0x8a725d6D...a34895A40
0 S0.267961550
Execute593342872025-12-31 23:40:0625 days ago1767224406IN
0x8a725d6D...a34895A40
0 S0.267960950
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
375774482025-07-08 7:38:08202 days ago1751960288  Contract Creation0 S
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Puppeteer

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 1000 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { IAdapter } from "./interfaces/IAdapter.sol";
import { IRewardDistributor } from "./interfaces/IRewardDistributor.sol";
import { Adapter } from "./libraries/Adapter.sol";
import { Marionette } from "./libraries/Marionette.sol";
import { MarionetteKey } from "./types/MarionetteKey.sol";
import { MarionetteIdLib, MarionetteId } from "./types/MarionetteId.sol";
import { ERC721 } from "./ERC721.sol";
import { AccessControl } from "./AccessControl.sol";
import { FeeM } from "./FeeM.sol";
import { IPuppeteer } from "./interfaces/IPuppeteer.sol";
import { Ownable2Step } from "openzeppelin/access/Ownable2Step.sol";
import { Ownable } from "openzeppelin/access/Ownable.sol";
import { ReentrancyGuard } from "openzeppelin/utils/ReentrancyGuard.sol";
import { Incentive, IncentiveClaim } from "./types/Incentive.sol";

/**
 * @title Puppeteer
 * @author Redacted
 * @dev This smart contract is designed to manage the state and configuration of Marionettes.
 *      The contract performs the following key functionalities:
 *
 *      1. Hold the State of All Marionettes:
 *      2. ERC721 Tokenization:
 *      3. Access Control:
 *      4. Marionette Lifecycle: initialization, minting, burning, executing ve actions and claiming rewards.
 */
contract Puppeteer is ERC721, IPuppeteer, Ownable2Step, AccessControl, ReentrancyGuard, FeeM {
    using MarionetteIdLib for MarionetteKey;
    using Adapter for IAdapter;
    using Marionette for *;

    /*//////////////////////////////////////////////////////////////
                      STATE VARIABLES
    //////////////////////////////////////////////////////////////*/

    mapping(MarionetteId id => Marionette.State) internal marionettes;
    mapping(MarionetteId => MarionetteKey) internal marionetteIdToMarionetteKey;
    mapping(uint256 => MarionetteId) public tokenIdToMarionetteId;
    mapping(address => mapping(uint256 => bool)) public veTokenSubscribed;
    uint256 public currentTokenId;

    /*//////////////////////////////////////////////////////////////
                          ERRORS
    //////////////////////////////////////////////////////////////*/

    error AlreadyInitialized();
    error AlreadySubscribed();
    error OnlyOwnerOrApproved();
    error UninitializedOrPausedMarionette();

    constructor(address _owner) ERC721("Trevee veETH", "trveETH") Ownable(_owner) { 
        registerMe();
    }

    /*//////////////////////////////////////////////////////////////
                      EXTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPuppeteer
    function initialize(
        MarionetteKey memory key,
        string calldata uri,
        Marionette.VoteConfig calldata defaultVoteConfig,
        Marionette.RewardConfig calldata defaultRewardConfig,
        Marionette.LockConfig calldata defaultLockConfig,
        bytes calldata adapterData
    ) external onlyOwner {
        MarionetteId id = key.toId();
        if (marionettes[id].initialized) revert AlreadyInitialized();

        if (
            key.adapter.beforeInitialize(
                msg.sender, defaultVoteConfig, defaultRewardConfig, defaultLockConfig, adapterData
            ) != IAdapter.beforeInitialize.selector
        ) {
            revert Adapter.InvalidAdapterResponse();
        }

        marionetteIdToMarionetteKey[id] = key;
        marionettes[id].initialize(uri, defaultVoteConfig, defaultRewardConfig, defaultLockConfig);
        _grantRole(id, MARIONETTE_ADMIN_ROLE, msg.sender);

        emit Initialize(
            key, id, uri, msg.sender, defaultVoteConfig, defaultRewardConfig, defaultLockConfig, adapterData
        );
    }

    /// @inheritdoc IPuppeteer
    function setDefaultConfig(
        MarionetteKey memory key,
        Marionette.ConfigType calldata configType,
        bytes calldata configData,
        bytes calldata adapterData
    ) external {
        MarionetteId id = key.toId();
        _checkRole(id, MARIONETTE_ADMIN_ROLE);

        if (key.adapter.shouldCallBeforeSetDefaultConfig()) {
            if (
                key.adapter.beforeSetDefaultConfig(msg.sender, configType, configData, adapterData)
                    != IAdapter.beforeSetDefaultConfig.selector
            ) {
                revert Adapter.InvalidAdapterResponse();
            }
        }

        marionettes[id].setDefaultConfig(configType, configData);

        emit SetDefaultConfig(id, configType, configData);
    }

    /// @inheritdoc IPuppeteer
    function setCustomConfig(
        MarionetteKey memory key,
        uint256 tokenId,
        Marionette.ConfigType calldata configType,
        bytes calldata configData,
        bytes calldata adapterData
    ) external {
        _onlyOwnerOrApproved(msg.sender, tokenId);
        MarionetteId id = key.toId();
        _onlyInitializedUnpaused(id);

        if (key.adapter.shouldCallBeforeSetCustomConfig()) {
            if (
                key.adapter.beforeSetCustomConfig(
                    msg.sender, marionettes[id].marionette[tokenId].veId, configType, configData, adapterData
                ) != IAdapter.beforeSetCustomConfig.selector
            ) {
                revert Adapter.InvalidAdapterResponse();
            }
        }

        marionettes[id].setCustomConfig(tokenId, configType, configData);

        emit SetCustomConfig(id, tokenId, configType, configData);
    }

    /// @inheritdoc IPuppeteer
    function mint(
        MarionetteKey memory key,
        uint256 veId,
        Marionette.RewardConfig calldata rewardConfig,
        Marionette.LockConfig calldata lockConfig,
        bytes calldata adapterData
    ) external nonReentrant {
        MarionetteId id = key.toId();
        _onlyInitializedUnpaused(id);

        bytes memory data = abi.encode(rewardConfig, lockConfig, adapterData);

        uint256 tokenId = ++currentTokenId;
        tokenIdToMarionetteId[tokenId] = id;
        marionettes[id].mint(tokenId, veId, rewardConfig, lockConfig);

        _mint(msg.sender, tokenId, data);

        veTokenSubscribed[key.protocol.veAddress][veId] = true;

        emit Mint(id, tokenId, veId, msg.sender, rewardConfig, lockConfig, adapterData);
    }

    /// @inheritdoc IPuppeteer
    function burn(MarionetteKey memory key, uint256 tokenId, bytes calldata adapterData) external nonReentrant {
        MarionetteId id = key.toId();
        _onlyInitializedUnpaused(id);
        _onlyOwnerOrApproved(msg.sender, tokenId);

        _burn(tokenId, adapterData);

        veTokenSubscribed[key.protocol.veAddress][marionettes[id].marionette[tokenId].veId] = false;
        tokenIdToMarionetteId[tokenId] = MarionetteId.wrap(0);
        marionettes[id].burn(tokenId);

        emit Burn(id, tokenId, adapterData);
    }

    /// @inheritdoc IPuppeteer
    function execute(MarionetteKey memory key, bytes calldata adapterData) external {
        MarionetteId id = key.toId();
        _onlyInitializedUnpaused(id);
        _checkRole(id, KEEPER_ROLE);

        if (key.adapter.execute(msg.sender, adapterData) != IAdapter.execute.selector) {
            revert Adapter.InvalidAdapterResponse();
        }

        emit Execute(id, adapterData);
    }

    /// @inheritdoc IPuppeteer
    function setPaused(MarionetteKey memory key, bool paused, bytes calldata adapterData) external {
        MarionetteId id = key.toId();
        _checkRole(id, MARIONETTE_ADMIN_ROLE);

        if (key.adapter.shouldCallBeforePause()) {
            if (key.adapter.beforePause(msg.sender, paused, adapterData) != IAdapter.beforePause.selector) {
                revert Adapter.InvalidAdapterResponse();
            }
        }
        marionettes[id].setPaused(paused);

        emit SetPaused(id, paused);
    }

    /// @inheritdoc IPuppeteer
    function setUri(MarionetteKey memory key, string calldata uri) external {
        MarionetteId id = key.toId();
        _checkRole(id, MARIONETTE_ADMIN_ROLE);

        marionettes[id].setUri(uri);

        emit SetUri(id, uri);
    }

    /*//////////////////////////////////////////////////////////////
                        VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice returns Marionette metadata uri
     * @param tokenId The tokenId of the Marionette
     */
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        _requireMinted(tokenId);

        return marionettes[_getMarionetteId(tokenId)].uri;
    }

    /// @inheritdoc IPuppeteer
    function getMarionette(uint256 tokenId) external view returns (Marionette.MarionetteState memory) {
        _requireMinted(tokenId);

        return marionettes[_getMarionetteId(tokenId)].getMarionette(tokenId);
    }

    /// @inheritdoc IPuppeteer
    function getState(MarionetteKey memory key)
        external
        view
        returns (
            bool initialized,
            bool paused,
            string memory uri,
            Marionette.VoteConfig memory defaultVoteConfig,
            Marionette.RewardConfig memory defaultRewardConfig,
            Marionette.LockConfig memory defaultLockConfig
        )
    {
        MarionetteId id = key.toId();

        return marionettes[id].getState();
    }

    /**
     * @notice Get the tokenId of a Marionette by its veId
     * @param key The MarionetteKey of the Marionette
     * @param veId The veId of the deposited token
     */
    function getVeIdTokenId(MarionetteKey memory key, uint256 veId) external view returns (uint256) {
        MarionetteId id = key.toId();
        return marionettes[id].getTokenId(veId);
    }

    /*//////////////////////////////////////////////////////////////
                      INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev Check if can mint and perform actions on the adapter side if necessary
     */
    function _beforeTokenTransfer(address from, address to, uint256 tokenId, bytes memory data) internal override {
        MarionetteKey memory key = marionetteIdToMarionetteKey[tokenIdToMarionetteId[tokenId]];
        MarionetteId id = key.toId();
        uint256 veId = marionettes[id].marionette[tokenId].veId;

        if (from == address(0) && veTokenSubscribed[key.protocol.veAddress][veId]) {
            revert AlreadySubscribed();
        }

        if ((from == address(0) || to == address(0)) || key.adapter.shouldCallBeforeTransfer()) {
            if (key.adapter.beforeTransfer(from, to, veId, data) != IAdapter.beforeTransfer.selector) {
                revert Adapter.InvalidAdapterResponse();
            }
        }
    }

    function _getMarionetteId(uint256 tokenId) internal view returns (MarionetteId) {
        return tokenIdToMarionetteId[tokenId];
    }

    function _onlyInitializedUnpaused(MarionetteId id) internal view {
        if (!marionettes[id].initialized || marionettes[id].paused) revert UninitializedOrPausedMarionette();
    }

    function _onlyOwnerOrApproved(address sender, uint256 tokenId) internal view {
        if (sender != ownerOf(tokenId) && getApproved[tokenId] != msg.sender) {
            revert OnlyOwnerOrApproved();
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { Marionette } from "../libraries/Marionette.sol";

interface IAdapter {
    function beforeInitialize(
        address sender,
        Marionette.VoteConfig memory defaultVoteConfig,
        Marionette.RewardConfig memory defaultRewardConfig,
        Marionette.LockConfig memory defaultLockConfig,
        bytes calldata adapterData
    ) external returns (bytes4);

    function beforeTransfer(address from, address to, uint256 veId, bytes calldata adapterData)
        external
        returns (bytes4);

    function beforeSetDefaultConfig(
        address sender,
        Marionette.ConfigType calldata configType,
        bytes calldata configData,
        bytes calldata adapterData
    ) external returns (bytes4);

    function beforeSetCustomConfig(
        address sender,
        uint256 tokenId,
        Marionette.ConfigType calldata configType,
        bytes calldata configData,
        bytes calldata adapterData
    ) external returns (bytes4);

    function beforeSwap(address sender, bytes calldata adapterData) external returns (bytes4);

    function beforeClaim(address sender, uint256 veId, bytes calldata adapterData) external returns (bytes4);

    function beforePause(address sender, bool paused, bytes calldata adapterData) external returns (bytes4);

    function execute(address sender, bytes calldata adapterData) external returns (bytes4);

    function increaseMany(uint256[] memory veNFTs, uint256[] memory amounts, address depositor, bool pullToken)
        external;
}

//SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

/**
 * @title IRewardsDistributor
 * @author 0xMemoryGrinder
 * @dev MerkleDistributor interface which updates the merkle root when the claims are made
 */
interface IRewardDistributor {
    struct ClaimParams {
        address token;
        uint256 epoch;
        uint256 index;
        uint256 amount;
        bytes32[] merkleProof;
    }

    /**
     * @dev Claim a token reward for a given account
     * @param epoch Epoch to claim rewards for
     * @param index Index in the merkle tree to claim rewards for
     * @param token Token address to claim
     * @param account Account to claim rewards for
     * @param amount Rewards amount to claim
     * @param merkleProof Merkle proof to validate the claim
     */
    function claim(
        uint256 epoch,
        uint256 index,
        address token,
        address account,
        uint256 amount,
        bytes32[] calldata merkleProof
    ) external;

    /**
     * @dev Claim multiple token rewards for given accounts
     * @param account Account to claim rewards for
     * @param params ClaimParams array containing the tokens, amounts and merkle proofs
     */
    function multiClaim(address account, ClaimParams[] calldata params) external;

    /**
     * @dev Update the merkle root
     * @param epoch Epoch id
     * @param newMerkleRoot New merkle root after a harvest, set by the operator
     */
    function addEpochRewards(uint256 epoch, bytes32 newMerkleRoot) external;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;

import { IAdapter } from "../interfaces/IAdapter.sol";

/// @notice The protocol decides whether to invoke specific adapter by inspecting the leading bits of the address that
/// the adapter contract is deployed to.
/// For example, a adapter contract deployed to address: 0x9000000000000000000000000000000000000000
/// has leading bits "1001" which would cause the "before initialize" and "after transfer" adapter to be used.
library Adapter {
    uint256 internal constant BEFORE_TRANSFER_FLAG = 1 << 159;
    uint256 internal constant BEFORE_SET_DEFAULT_FLAG = 1 << 158;
    uint256 internal constant BEFORE_SET_CUSTOM_FLAG = 1 << 157;
    uint256 internal constant BEFORE_SWAP_FLAG = 1 << 156;
    uint256 internal constant BEFORE_CLAIM_FLAG = 1 << 155;
    uint256 internal constant BEFORE_PAUSE_FLAG = 1 << 154;

    struct Calls {
        bool beforeTransfer;
        bool beforeSetDefaultConfig;
        bool beforeSetCustomConfig;
        bool beforeSwap;
        bool beforeClaim;
        bool beforePause;
    }

    /// @notice Thrown if the address will not lead to the specified adapter calls being called
    /// @param adapter The address of the adapter contract
    error AdapterAddressNotValid(address adapter);

    /// @notice Adapter did not return its selector
    error InvalidAdapterResponse();

    /// @notice Utility function intended to be used in adapter constructors to ensure
    /// the deployed adapter address causes the intended adapter to be called
    /// @param calls The adapter that are intended to be called
    /// @dev calls param is memory as the function will be called from constructors
    function validateAdapterAddress(IAdapter self, Calls memory calls) internal pure {
        if (
            calls.beforeTransfer != shouldCallBeforeTransfer(self)
                || calls.beforeSetDefaultConfig != shouldCallBeforeSetDefaultConfig(self)
                || calls.beforeSetCustomConfig != shouldCallBeforeSetCustomConfig(self)
                || calls.beforeSwap != shouldCallBeforeSwap(self) || calls.beforeClaim != shouldCallBeforeClaim(self)
                || calls.beforePause != shouldCallBeforePause(self)
        ) {
            revert AdapterAddressNotValid(address(self));
        }
    }

    /// @notice Ensures that the adapter address includes at least one adapter flag or dynamic fees, or is the 0 address
    /// @param adapter The adapter to verify
    function isValidAdapterAddress(IAdapter adapter) internal pure returns (bool) {
        return uint160(address(adapter)) >= BEFORE_PAUSE_FLAG;
    }

    function shouldCallBeforeTransfer(IAdapter self) internal pure returns (bool) {
        return uint256(uint160(address(self))) & BEFORE_TRANSFER_FLAG != 0;
    }

    function shouldCallBeforeSetDefaultConfig(IAdapter self) internal pure returns (bool) {
        return uint256(uint160(address(self))) & BEFORE_SET_DEFAULT_FLAG != 0;
    }

    function shouldCallBeforeSetCustomConfig(IAdapter self) internal pure returns (bool) {
        return uint256(uint160(address(self))) & BEFORE_SET_CUSTOM_FLAG != 0;
    }

    function shouldCallBeforeSwap(IAdapter self) internal pure returns (bool) {
        return uint256(uint160(address(self))) & BEFORE_SWAP_FLAG != 0;
    }

    function shouldCallBeforePause(IAdapter self) internal pure returns (bool) {
        return uint256(uint160(address(self))) & BEFORE_PAUSE_FLAG != 0;
    }

    function shouldCallBeforeClaim(IAdapter self) internal pure returns (bool) {
        return uint256(uint160(address(self))) & BEFORE_CLAIM_FLAG != 0;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

library Marionette {
    error InvalidStatus();

    struct ConfigType {
        bool vote;
        bool reward;
        bool lock;
    }

    enum RewardMode {
        VoteOnly,
        Default,
        Compound,
        Custom
    }

    struct RewardConfig {
        RewardMode rewardMode;
        bytes data;
    }

    struct VoteConfig {
        address[] gauges;
        uint256[] weights;
        bytes data;
    }

    enum LockMode {
        None,
        Max,
        Maintain,
        Custom
    }

    struct LockConfig {
        LockMode lockMode;
        bytes data;
    }

    struct MarionetteState {
        uint256 veId;
        RewardConfig customRewardConfig;
        LockConfig customLockConfig;
    }

    struct State {
        bool initialized;
        bool paused;
        string uri;
        VoteConfig defaultVoteConfig;
        RewardConfig defaultRewardConfig;
        LockConfig defaultLockConfig;
        mapping(uint256 => MarionetteState) marionette;
        mapping(uint256 veId => uint256 tokenId) veIdToTokenId;
    }

    function initialize(
        State storage state,
        string memory uri,
        VoteConfig memory defaultVoteConfig,
        RewardConfig memory defaultRewardConfig,
        LockConfig memory defaultLockConfig
    ) internal {
        state.initialized = true;
        state.paused = true;
        state.uri = uri;
        state.defaultVoteConfig = defaultVoteConfig;
        state.defaultRewardConfig = defaultRewardConfig;
        state.defaultLockConfig = defaultLockConfig;
    }

    function mint(
        State storage state,
        uint256 tokenId,
        uint256 veId,
        RewardConfig memory rewardConfig,
        LockConfig memory lockConfig
    ) internal {
        state.marionette[tokenId].veId = veId;
        state.marionette[tokenId].customRewardConfig = rewardConfig;
        state.marionette[tokenId].customLockConfig = lockConfig;
        state.veIdToTokenId[veId] = tokenId;
    }

    function burn(State storage state, uint256 tokenId) internal {
        delete state.marionette[tokenId];
    }

    function setPaused(State storage state, bool paused) internal {
        if (state.paused == paused) revert InvalidStatus();

        state.paused = paused;
    }

    function setUri(State storage state, string memory uri) internal {
        state.uri = uri;
    }

    function setDefaultConfig(State storage state, ConfigType memory configType, bytes memory configData) internal {
        if (configType.vote) {
            (VoteConfig memory config,,) = abi.decode(configData, (VoteConfig, RewardConfig, LockConfig));
            state.defaultVoteConfig = config;
        }
        if (configType.reward) {
            (, RewardConfig memory config,) = abi.decode(configData, (VoteConfig, RewardConfig, LockConfig));
            state.defaultRewardConfig = config;
        }
        if (configType.lock) {
            (,, LockConfig memory config) = abi.decode(configData, (VoteConfig, RewardConfig, LockConfig));
            state.defaultLockConfig = config;
        }
    }

    function setCustomConfig(
        State storage state,
        uint256 tokenId,
        ConfigType memory configType,
        bytes memory configData
    ) internal {
        if (configType.reward) {
            (RewardConfig memory config,) = abi.decode(configData, (RewardConfig, LockConfig));
            state.marionette[tokenId].customRewardConfig = config;
        }
        if (configType.lock) {
            (, LockConfig memory config) = abi.decode(configData, (RewardConfig, LockConfig));
            state.marionette[tokenId].customLockConfig = config;
        }
    }

    function getMarionette(State storage state, uint256 tokenId) internal view returns (MarionetteState memory) {
        return state.marionette[tokenId];
    }

    function getState(State storage state)
        internal
        view
        returns (
            bool initialized,
            bool paused,
            string memory uri,
            VoteConfig memory defaultVoteConfig,
            RewardConfig memory defaultRewardConfig,
            LockConfig memory defaultLockConfig
        )
    {
        return (
            state.initialized,
            state.paused,
            state.uri,
            state.defaultVoteConfig,
            state.defaultRewardConfig,
            state.defaultLockConfig
        );
    }

    function getTokenId(State storage state, uint256 veId) internal view returns (uint256 tokenId) {
        return state.veIdToTokenId[veId];
    }
}

File 6 of 16 : MarionetteKey.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { IAdapter } from "../interfaces/IAdapter.sol";
import { IRewardDistributor } from "../interfaces/IRewardDistributor.sol";

struct Protocol {
    string protocol;
    address veAddress;
    uint24 version;
}

struct MarionetteKey {
    Protocol protocol;
    IAdapter adapter;
    IRewardDistributor rewardDistributor;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { MarionetteKey } from "./MarionetteKey.sol";

type MarionetteId is bytes32;

library MarionetteIdLib {
    function toId(MarionetteKey memory marionetteKey) internal pure returns (MarionetteId) {
        return MarionetteId.wrap(keccak256(abi.encode(marionetteKey)));
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

/// @notice Minimalist ERC-721 implementation based on Solmate's ERC721 contract
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    error ZeroAddress();
    error NotMinted();
    error AlreadyMinted();
    error NotAuthorized();
    error InvalidRecipient();
    error InvalidFrom();
    error UnsafeRecipient();

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        owner = _ownerOf[id];
        if (owner == address(0)) revert NotMinted();

        return owner;
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        if (owner == address(0)) revert ZeroAddress();

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) revert NotAuthorized();

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function _transferFrom(address from, address to, uint256 id, bytes calldata data) internal virtual {
        if (from != _ownerOf[id]) revert InvalidFrom();
        if (to == address(0)) revert InvalidRecipient();
        if (!(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id])) {
            revert NotAuthorized();
        }

        _beforeTokenTransfer(from, to, id, data);

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);

        _afterTokenTransfer(from, to, id, data);
    }

    function safeTransferFrom(address from, address to, uint256 id, bytes calldata data) public virtual {
        _transferFrom(from, to, id, data);

        if (
            to.code.length != 0
                && ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data)
                    != ERC721TokenReceiver.onERC721Received.selector
        ) {
            revert UnsafeRecipient();
        }
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
            || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721
            || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id, bytes memory data) internal virtual {
        if (to == address(0)) revert InvalidRecipient();
        if (_ownerOf[id] != address(0)) revert AlreadyMinted();

        _beforeTokenTransfer(address(0), to, id, data);

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);

        _afterTokenTransfer(address(0), to, id, data);
    }

    function _burn(uint256 id, bytes calldata data) internal virtual {
        address owner = _ownerOf[id];

        if (owner == address(0)) revert NotMinted();

        _beforeTokenTransfer(owner, address(0), id, data);

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);

        _afterTokenTransfer(owner, address(0), id, data);
    }

    /*//////////////////////////////////////////////////////////////
                INTERNAL BEFORE/AFTER TRANSFER LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @dev Hook that is called before any token transfer. This includes minting and burning
    function _beforeTokenTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { }

    /// @dev Hook that is called after any token transfer. This includes minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { }

    function _requireMinted(uint256 id) internal view {
        if (_ownerOf[id] == address(0)) revert NotMinted();
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokeßns.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(address, address, uint256, bytes calldata) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { MarionetteIdLib, MarionetteId } from "./types/MarionetteId.sol";
import { MarionetteKey } from "./types/MarionetteKey.sol";

/// @notice Modified from OpenZeppelin's AccessControl contract (v4.9.0) to support MarionetteKey and MarionetteId
abstract contract AccessControl {
    using MarionetteIdLib for MarionetteKey;

    error OnlySelf();
    error MissingRole(bytes32 role, address account);

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``"s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(
        MarionetteId id, bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole
    );

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(MarionetteId id, bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(MarionetteId id, bytes32 indexed role, address indexed account, address indexed sender);

    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(MarionetteId => mapping(bytes32 => RoleData)) internal _roles;

    bytes32 public constant MARIONETTE_ADMIN_ROLE = 0x00;
    bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE");

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     */
    modifier onlyRole(MarionetteKey memory key, bytes32 role) {
        MarionetteId id = key.toId();
        _checkRole(id, role);
        _;
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(MarionetteId id, bytes32 role, address account) public view virtual returns (bool) {
        return _roles[id][role].members[account];
    }

    /**
     * @dev Revert with a standard message if `msg.sender` is missing `role`.
     * Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(MarionetteId id, bytes32 role) internal view virtual {
        _checkRole(id, role, msg.sender);
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     */
    function _checkRole(MarionetteId id, bytes32 role, address account) internal view virtual {
        if (!hasRole(id, role, account)) revert MissingRole(role, account);
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     */
    function getRoleAdmin(MarionetteKey memory key, bytes32 role) public view virtual returns (bytes32) {
        MarionetteId id = key.toId();
        return _roles[id][role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     */
    function grantRole(MarionetteKey memory key, bytes32 role, address account)
        public
        virtual
        onlyRole(key, getRoleAdmin(key, role))
    {
        MarionetteId id = key.toId();
        _grantRole(id, role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     */
    function revokeRole(MarionetteKey memory key, bytes32 role, address account)
        public
        virtual
        onlyRole(key, getRoleAdmin(key, role))
    {
        MarionetteId id = key.toId();
        _revokeRole(id, role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function"s
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(MarionetteKey memory key, bytes32 role, address account) public virtual {
        if (account != msg.sender) revert OnlySelf();
        MarionetteId id = key.toId();
        _revokeRole(id, role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(MarionetteId id, bytes32 role, address account) internal virtual {
        if (!hasRole(id, role, account)) {
            _roles[id][role].members[account] = true;
            emit RoleGranted(id, role, account, msg.sender);
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(MarionetteId id, bytes32 role, address account) internal virtual {
        if (hasRole(id, role, account)) {
            _roles[id][role].members[account] = false;
            emit RoleRevoked(id, role, account, msg.sender);
        }
    }
}

File 10 of 16 : FeeM.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

abstract contract FeeM {
    /// @dev Register my contract on Sonic FeeM
    function registerMe() internal {
        (bool _success, ) = address(0xDC2B0D2Dd2b7759D97D50db4eabDC36973110830)
            .call(abi.encodeWithSignature("selfRegister(uint256)", 28));
        require(_success, "FeeM registration failed");
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { MarionetteKey } from "../types/MarionetteKey.sol";
import { MarionetteId } from "../types/MarionetteId.sol";
import { Marionette } from "../libraries/Marionette.sol";
import { Incentive, IncentiveClaim } from "../types/Incentive.sol";

/**
 * @title IPuppeteer
 * @dev Interface for the Puppeteer contract.
 */
interface IPuppeteer {
    event Initialize(
        MarionetteKey indexed key,
        MarionetteId indexed id,
        string uri,
        address indexed admin,
        Marionette.VoteConfig voteConfig,
        Marionette.RewardConfig rewardConfig,
        Marionette.LockConfig lockConfig,
        bytes adapterData
    );

    event Mint(
        MarionetteId indexed id,
        uint256 indexed tokenId,
        uint256 indexed veId,
        address recipient,
        Marionette.RewardConfig rewardConfig,
        Marionette.LockConfig lockConfig,
        bytes adapterData
    );

    event Burn(MarionetteId indexed id, uint256 indexed tokenId, bytes adapterData);
    event SetCustomConfig(MarionetteId indexed id, uint256 tokenId, Marionette.ConfigType configType, bytes configData);
    event SetDefaultConfig(MarionetteId indexed id, Marionette.ConfigType configType, bytes configData);
    event SetPaused(MarionetteId indexed id, bool paused);
    event SetUri(MarionetteId indexed id, string uri);
    event Execute(MarionetteId indexed id, bytes adapterData);
    event Claim(MarionetteId indexed id, uint256 indexed tokenId, uint256 indexed veId, bytes adapterData);
    event Swap(MarionetteId indexed id, bytes adapterData);

    /**
     * @dev Initializes a new Marionette
     * @param key Marionette key
     * @param uri Marionette URI
     * @param defaultVoteConfig The default vote configuration
     * @param defaultRewardConfig The default reward configuration
     * @param defaultLockConfig The default lock configuration
     * @param adapterData Additional data to be used by the adapter contract
     */
    function initialize(
        MarionetteKey memory key,
        string calldata uri,
        Marionette.VoteConfig calldata defaultVoteConfig,
        Marionette.RewardConfig calldata defaultRewardConfig,
        Marionette.LockConfig calldata defaultLockConfig,
        bytes calldata adapterData
    ) external;

    /**
     * @dev Mints a new Marionette token and performs any additional adapter-specific actions
     * @param key Marionette key
     * @param veId veNFT ID in the voting escrow contract
     * @param rewardConfig Custom reward configuration
     * @param lockConfig Custom lock configuration
     * @param adapterData Additional data to be used by the adapter contract
     */
    function mint(
        MarionetteKey memory key,
        uint256 veId,
        Marionette.RewardConfig calldata rewardConfig,
        Marionette.LockConfig calldata lockConfig,
        bytes calldata adapterData
    ) external;

    /**
     * @dev Burns a Marionette NFT and performs any additional adapter-specific actions
     * @param key Marionette Key
     * @param tokenId The ID of the Marionette NFT to burn
     * @param adapterData Additional data to be used by the adapter contract
     */
    function burn(MarionetteKey memory key, uint256 tokenId, bytes calldata adapterData) external;

    /**
     * @dev Sets the default configuration for a Marionette instance.
     * @param key Marionette key
     * @param configType The type of configuration to set
     * @param configData The configuration data
     * @param adapterData Additional data to be used by the adapter contract
     */
    function setDefaultConfig(
        MarionetteKey memory key,
        Marionette.ConfigType calldata configType,
        bytes calldata configData,
        bytes calldata adapterData
    ) external;

    /**
     * @dev Sets the custom configuration for a Marionette
     * @param key Marionette key
     * @param tokenId The ID of the Marionette token
     * @param configType The type of configuration to set
     * @param configData The configuration data
     * @param adapterData Additional data to be used by the adapter contract
     */
    function setCustomConfig(
        MarionetteKey memory key,
        uint256 tokenId,
        Marionette.ConfigType calldata configType,
        bytes calldata configData,
        bytes calldata adapterData
    ) external;

    /**
     * @dev Executes a function on the Adapter contract using the provided key and adapter data
     * @param key Marionette key
     * @param adapterData Additional data to be used by the adapter contract
     */
    function execute(MarionetteKey memory key, bytes calldata adapterData) external;

    /**
     * @dev Sets Marionette paused state
     * @param key Marionette key
     * @param paused new paused state
     * @param adapterData Additional data to be used by the ISwapper contract
     */
    function setPaused(MarionetteKey memory key, bool paused, bytes calldata adapterData) external;

    /**
     * @dev Sets the URI for a given Marionette
     * @param key Marionette key
     * @param uri new URI
     */
    function setUri(MarionetteKey memory key, string calldata uri) external;

    /**
     * @dev Returns the current state of the Marionette
     * @param tokenId The ID of the Marionette to get the state of
     * @return A struct containing the current state of the Marionette
     */
    function getMarionette(uint256 tokenId) external view returns (Marionette.MarionetteState memory);

    /**
     * @dev Returns the current state of the Marionette key
     * @param key Marionette key
     * @return initialized Whether the key has been initialized
     * @return paused Whether the key is currently paused
     * @return uri The URI associated with the key
     * @return defaultVoteConfig The default vote configuration for the key
     * @return defaultRewardConfig The default reward configuration for the key
     * @return defaultLockConfig The default lock configuration for the key
     */
    function getState(MarionetteKey memory key)
        external
        view
        returns (
            bool initialized,
            bool paused,
            string memory uri,
            Marionette.VoteConfig memory defaultVoteConfig,
            Marionette.RewardConfig memory defaultRewardConfig,
            Marionette.LockConfig memory defaultLockConfig
        );
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

import {Ownable} from "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 15 of 16 : Incentive.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

struct Incentive {
    address token;
    bytes32 merkleRoot;
    uint256 activeAt;
}

struct IncentiveClaim {
    address token;
    address account;
    uint256 tokenId;
    uint256 amount;
    bytes32[] merkleProof;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "solmate/=lib/solmate/src/",
    "solady/=lib/solady/src/",
    "src/=src/",
    "test/=test/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AlreadyMinted","type":"error"},{"inputs":[],"name":"AlreadySubscribed","type":"error"},{"inputs":[],"name":"InvalidAdapterResponse","type":"error"},{"inputs":[],"name":"InvalidFrom","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidStatus","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"MissingRole","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotMinted","type":"error"},{"inputs":[],"name":"OnlyOwnerOrApproved","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"UninitializedOrPausedMarionette","type":"error"},{"inputs":[],"name":"UnsafeRecipient","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"veId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"Execute","type":"event"},{"anonymous":false,"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"indexed":true,"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":false,"internalType":"string","name":"uri","type":"string"},{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"components":[{"internalType":"address[]","name":"gauges","type":"address[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct Marionette.VoteConfig","name":"voteConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.RewardMode","name":"rewardMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct Marionette.RewardConfig","name":"rewardConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.LockMode","name":"lockMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct Marionette.LockConfig","name":"lockConfig","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"veId","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"enum Marionette.RewardMode","name":"rewardMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct Marionette.RewardConfig","name":"rewardConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.LockMode","name":"lockMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct Marionette.LockConfig","name":"lockConfig","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"bool","name":"vote","type":"bool"},{"internalType":"bool","name":"reward","type":"bool"},{"internalType":"bool","name":"lock","type":"bool"}],"indexed":false,"internalType":"struct Marionette.ConfigType","name":"configType","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"configData","type":"bytes"}],"name":"SetCustomConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"components":[{"internalType":"bool","name":"vote","type":"bool"},{"internalType":"bool","name":"reward","type":"bool"},{"internalType":"bool","name":"lock","type":"bool"}],"indexed":false,"internalType":"struct Marionette.ConfigType","name":"configType","type":"tuple"},{"indexed":false,"internalType":"bytes","name":"configData","type":"bytes"}],"name":"SetDefaultConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"SetPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"SetUri","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"MarionetteId","name":"id","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"KEEPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MARIONETTE_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getMarionette","outputs":[{"components":[{"internalType":"uint256","name":"veId","type":"uint256"},{"components":[{"internalType":"enum Marionette.RewardMode","name":"rewardMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.RewardConfig","name":"customRewardConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.LockMode","name":"lockMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.LockConfig","name":"customLockConfig","type":"tuple"}],"internalType":"struct Marionette.MarionetteState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"}],"name":"getState","outputs":[{"internalType":"bool","name":"initialized","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"string","name":"uri","type":"string"},{"components":[{"internalType":"address[]","name":"gauges","type":"address[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.VoteConfig","name":"defaultVoteConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.RewardMode","name":"rewardMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.RewardConfig","name":"defaultRewardConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.LockMode","name":"lockMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.LockConfig","name":"defaultLockConfig","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"uint256","name":"veId","type":"uint256"}],"name":"getVeIdTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"MarionetteId","name":"id","type":"bytes32"},{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"string","name":"uri","type":"string"},{"components":[{"internalType":"address[]","name":"gauges","type":"address[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.VoteConfig","name":"defaultVoteConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.RewardMode","name":"rewardMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.RewardConfig","name":"defaultRewardConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.LockMode","name":"lockMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.LockConfig","name":"defaultLockConfig","type":"tuple"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"uint256","name":"veId","type":"uint256"},{"components":[{"internalType":"enum Marionette.RewardMode","name":"rewardMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.RewardConfig","name":"rewardConfig","type":"tuple"},{"components":[{"internalType":"enum Marionette.LockMode","name":"lockMode","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Marionette.LockConfig","name":"lockConfig","type":"tuple"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"bool","name":"vote","type":"bool"},{"internalType":"bool","name":"reward","type":"bool"},{"internalType":"bool","name":"lock","type":"bool"}],"internalType":"struct Marionette.ConfigType","name":"configType","type":"tuple"},{"internalType":"bytes","name":"configData","type":"bytes"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"setCustomConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"components":[{"internalType":"bool","name":"vote","type":"bool"},{"internalType":"bool","name":"reward","type":"bool"},{"internalType":"bool","name":"lock","type":"bool"}],"internalType":"struct Marionette.ConfigType","name":"configType","type":"tuple"},{"internalType":"bytes","name":"configData","type":"bytes"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"setDefaultConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"adapterData","type":"bytes"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"protocol","type":"string"},{"internalType":"address","name":"veAddress","type":"address"},{"internalType":"uint24","name":"version","type":"uint24"}],"internalType":"struct Protocol","name":"protocol","type":"tuple"},{"internalType":"contract IAdapter","name":"adapter","type":"address"},{"internalType":"contract IRewardDistributor","name":"rewardDistributor","type":"address"}],"internalType":"struct MarionetteKey","name":"key","type":"tuple"},{"internalType":"string","name":"uri","type":"string"}],"name":"setUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToMarionetteId","outputs":[{"internalType":"MarionetteId","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"veTokenSubscribed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60806040908082523462000457578062004949803803809162000023828562000477565b83396020928391810103126200045757516001600160a01b039081811690819003620004575783519162000057836200045b565b600c83526b0a8e4caeccaca40ecca8aa8960a31b848401528451926200007d846200045b565b60078452660e8e4ecca8aa8960cb1b8585015280516001600160401b039490939085851162000274575f54946001938487811c971680156200044c575b898810146200036a578190601f97888111620003f9575b50899088831160011462000395575f9262000389575b50505f19600383901b1c191690841b175f555b80519086821162000274578354908482811c921680156200037e575b898310146200036a57818784931162000317575b508890878311600114620002b3575f92620002a7575b50505f19600383901b1c191690831b1782555b80156200029057600780546001600160a01b03199081169091556006805491821683179055875193167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a36009558381016307983f4560e21b8152601c60248301526024825260608201908282108583111762000274575f928392885251908273dc2b0d2dd2b7759d97d50db4eabdc369731108305af1913d1562000288573d908111620002745784519162000214908201601f191685018362000477565b81525f833d92013e5b15620002325750516144ad90816200049c8239f35b606491519062461bcd60e51b82526004820152601860248201527f4665654d20726567697374726174696f6e206661696c656400000000000000006044820152fd5b634e487b7160e01b5f52604160045260245ffd5b50506200021d565b8651631e4fbdf760e01b81525f6004820152602490fd5b015190505f8062000140565b90859350601f19831691845f528a5f20925f5b8c828210620003005750508411620002e7575b505050811b01825562000153565b01515f1960f88460031b161c191690555f8080620002d9565b8385015186558997909501949384019301620002c6565b909150845f52885f208780850160051c8201928b861062000360575b918791869594930160051c01915b828110620003515750506200012a565b5f815585945087910162000341565b9250819262000333565b634e487b7160e01b5f52602260045260245ffd5b91607f169162000116565b015190505f80620000e7565b90869350601f198316915f80528b5f20925f5b8d828210620003e25750508411620003c9575b505050811b015f55620000fa565b01515f1960f88460031b161c191690555f8080620003bb565b8385015186558a97909501949384019301620003a8565b9091505f8052895f208880850160051c8201928c861062000442575b918891869594930160051c01915b82811062000433575050620000d1565b5f815585945088910162000423565b9250819262000415565b96607f1696620000ba565b5f80fd5b604081019081106001600160401b038211176200027457604052565b601f909101601f19168101906001600160401b03821190821017620002745760405256fe60a0806040526004361015610012575f80fd5b5f3560e01c9081629a9b7b146137ba5750806301ffc9a71461370057806306fdde0314613659578063081812fc14613626578063095ea7b31461357d5780631a0d745514613428578063364bc15a146133ee57806345f51ea0146133d457806349cb877b146131905780634fdf096c146130c65780635da2a1481461256b578063614083c2146124015780636352211e146123d257806370a082311461236a578063715018a614612308578063767d375814611ca257806379ba509714611c0a5780638490e824146117065780638da5cb5b146116e0578063916aef691461169757806395d89b41146115b9578063987e24ae146112c1578063a22cb46514611240578063ae6cde0d14611216578063b1b44f23146111bd578063b88d4fde14610da9578063bbd987ab14610bee578063bf23fd2d14610b2c578063c87b56dd14610ad2578063d345ccd0146103f5578063de9dadf9146103a0578063e30c39781461037a578063e855014c14610321578063e985e9c5146102ce578063ec224ee214610275578063f2fde38b1461020c5763f82a0afa146101b2575f80fd5b34610208576102066102016101c636613b60565b9290916101d281613f22565b5f52600860205260405f20835f526020526101fc600160405f2001546101f783613f22565b61403e565b613f22565b61440f565b005b5f80fd5b346102085760203660031901126102085761022561394e565b61022d614095565b6001600160a01b0380911690816001600160a01b03196007541617600755600654167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b34610208576060366003190112610208576044356001600160a01b038116809103610208576004355f52600860205260405f206024355f5260205260405f20905f52602052602060ff60405f2054166040519015158152f35b34610208576040366003190112610208576102e761394e565b6102ef613964565b906001600160a01b038091165f52600560205260405f2091165f52602052602060ff60405f2054166040519015158152f35b346102085760403660031901126102085760043567ffffffffffffffff8111610208576101fc6103559136906004016139e0565b5f52600860205260405f206024355f526020526020600160405f200154604051908152f35b34610208575f3660031901126102085760206001600160a01b0360075416604051908152f35b34610208576103ae36613b60565b90336001600160a01b038316036103cb5761020161020693613f22565b60046040517f14d4a4e8000000000000000000000000000000000000000000000000000000008152fd5b346102085760031960a0368201126102085760043567ffffffffffffffff8111610208576104279036906004016139e0565b906044359167ffffffffffffffff8311610208576040828436030112610208576064359167ffffffffffffffff83116102085760409083360301126102085760843567ffffffffffffffff811161020857610486903690600401613aa3565b939092610491614369565b61049a83613f22565b926104a484613f9f565b60405192606060208501526104ff846104f16104de6104c96080840186600401613d5b565b838103601f1901604085015260048801613d5b565b828103601f190160608401528a8a613bd5565b03601f198101865285613844565b600e54965f198814610abe5760018801600e55600188015f52600c6020528560405f2055855f52600a60205260405f2061053c3684600401613e23565b6105493687600401613e23565b9060018b015f5260098301602052602060405f2091602435835560018301815161057281613b19565b61057b81613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e576105b5826105ac60028601546137d4565b60028601613dad565b602090601f8311600114610a525791806105e7926002945f926109c3575b50508160011b915f199060031b1c19161790565b9101555b60018a015f5260098201602052602060405f209160038301815161060e81613b19565b61061781613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e576106518261064860048601546137d4565b60048601613dad565b602090601f83116001146109ce5782600a959493600493610686935f926109c35750508160011b915f199060031b1c19161790565b9101555b6024355f52016020526001880160405f2055331561099957600188015f5260026020526001600160a01b03948560405f20541661096f57600189015f52600c60205260405f20545f52600b60205260405f20604051916106e98361380c565b6040516106f58161380c565b6106fe83613866565b815262ffffff60018401548a8116602084015260a01c1660408201528352876003816002850154169360208601948552015416604084015261073f83613f22565b5f52600a602052600960405f200160018c015f5260205287602060405f205494510151165f52600d60205260405f20835f5260205260ff60405f205416610945576107c3602091895f9451169060405194858094819363343b278f60e01b998a84528460048501523360248501526044840152608060648401526084830190613929565b03925af1801561093a576001600160e01b0319915f9161090b575b5016036108e1576108c16001946108b06108d7947fcc92a97118e4c878d6de7aecc51f34f42d7705085bae63e4210f765c28d097809860208d98335f526003825260405f208b81540190558a8a015f526002825260405f20336001600160a01b03198254161790556040519a8b9a01335f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4510151165f52600d60205260405f206024355f5260205260405f20600160ff19825416179055338752608060208801526080870190600401613d5b565b908582036040870152600401613d5b565b9083820360608501526001602435990197613bd5565b0390a46001600955005b60046040517fc8639962000000000000000000000000000000000000000000000000000000008152fd5b61092d915060203d602011610933575b6109258183613844565b810190613bb5565b8b6107de565b503d61091b565b6040513d5f823e3d90fd5b60046040517f5fd8a132000000000000000000000000000000000000000000000000000000008152fd5b60046040517fddefae28000000000000000000000000000000000000000000000000000000008152fd5b60046040517f9c8d2cd2000000000000000000000000000000000000000000000000000000008152fd5b015190508f806105d3565b90600484015f5260205f20915f5b601f1985168110610a26575092600492600192600a97969583601f19811610610a0e575b505050811b0191015561068a565b01515f1960f88460031b161c191690558e8080610a00565b919260206001819286850151815501940192016109dc565b634e487b7160e01b5f52604160045260245ffd5b90600284015f5260205f20915f5b601f1985168110610aa65750918391600193600295601f19811610610a8e575b505050811b019101556105eb565b01515f1960f88460031b161c191690558e8080610a80565b91926020600181928685015181550194019201610a60565b634e487b7160e01b5f52601160045260245ffd5b3461020857602036600319011261020857600435610aef816143f3565b5f52600c60205260405f20545f52600a602052610b28610b14600160405f2001613866565b604051918291602083526020830190613929565b0390f35b3461020857602080600319360112610208576009600435610b4b613efa565b50610b55816143f3565b805f52600c835260405f20545f52600a835260405f2090610b74613efa565b505f5201815260405f20610b2860405191610b8e8361380c565b80548352610bdb610bb36003610ba660018501614069565b9387870194855201614069565b9160408501928352604051958695818752519086015251606060408601526080850190613b37565b9051838203601f19016060850152613b37565b346102085760603660031901126102085767ffffffffffffffff60043581811161020857610c209036906004016139e0565b90610c29613ba6565b9060443590811161020857610c42903690600401613aa3565b610c4d849294613f22565b93610c5785613ff7565b60208080940151917304000000000000000000000000000000000000008316610d05575b50505050825f52600a815260405f208054921515908160ff8560081c16151514610cdb577f3a124f724f69accb9a3ebeeffa8015c57cd895408f8f3fedd5be1d6a5983caa59361ff008360081b169061ff001916179055604051908152a2005b60046040517ff525e320000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b0392610d60915f6040519586809581947f4f195105000000000000000000000000000000000000000000000000000000009a8b84523360048501528d15156024850152606060448501526064840191613bd5565b0393165af1801561093a576001600160e01b0319915f91610d8c575b5016036108e15783808281610c7b565b610da39150843d8611610933576109258183613844565b86610d7c565b3461020857608036600319011261020857610dc261394e565b610dca613964565b6044359160643567ffffffffffffffff811161020857610dee903690600401613aa3565b9290845f52602091600283526001600160a01b0390818060405f205416951694850361119357818116918215610999578533148015611175575b801561115f575b1561113557610e3f3688866139aa565b885f52600c865260405f20545f52600b86528560405f2091604051610e638161380c565b604051610e6f8161380c565b610e7885613866565b815262ffffff60018601548781168684015260a01c166040820152815284600381600287015416958584019687520154166040820152610eb781613f22565b5f52600a8352600960405f20018c5f52835260405f205490858b15948592839661110e575b50505061094557899489938015611107575b80156110e7575b61105f575b50505050505f526003845260405f205f198154019055815f5260405f2060018154019055865f526002845260405f206001600160a01b03199083828254161790556004855260405f209081541690558682867fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4610f7b3687856139aa565b503b15159485610fbd575b50505050509050610f9357005b60046040517f3da63931000000000000000000000000000000000000000000000000000000008152fd5b8395505f6110169597604051968795869485937f150b7a02000000000000000000000000000000000000000000000000000000009c8d865233600487015260248601526044850152608060648501526084840191613bd5565b03925af190811561093a576001600160e01b0319925f92611042575b5050161415808280808080610f86565b6110589250803d10610933576109258183613844565b8380611032565b61109d945116905f60405180968195829463343b278f60e01b9a8b855260048501528c60248501526044840152608060648401526084830190613929565b03925af1801561093a576001600160e01b0319915f916110ca575b5016036108e157848885818080610efa565b6110e19150873d8911610933576109258183613844565b8a6110b8565b507380000000000000000000000000000000000000008551161515610ef5565b505f610eee565b90919250510151165f52600d895260405f20815f52895260ff60405f205416858a8f610edc565b60046040517fea8e4eb5000000000000000000000000000000000000000000000000000000008152fd5b50875f52600485528060405f2054163314610e2f565b50855f526005855260405f20335f52855260ff60405f205416610e28565b60046040517f20994242000000000000000000000000000000000000000000000000000000008152fd5b346102085760403660031901126102085760043567ffffffffffffffff8111610208576101fc6111f19136906004016139e0565b5f52600a602052600a60405f20016024355f52602052602060405f2054604051908152f35b34610208576020366003190112610208576004355f52600c602052602060405f2054604051908152f35b346102085760403660031901126102085761125961394e565b611261613ba6565b335f5260056020526001600160a01b0360405f20921691825f5260205260405f209015159060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b346102085760603660031901126102085767ffffffffffffffff600435818111610208576112f39036906004016139e0565b602435916044359081116102085761130f903690600401613aa3565b611317614369565b61132083613f22565b9261132a84613f9f565b61133485336142b9565b845f52602090600282526001600160a01b03938460405f20541694851561158f578561142d856113653689876139aa565b8b5f52600c825260405f20545f52600b825260405f206113da60405161138a8161380c565b6040516113968161380c565b61139f84613866565b815262ffffff60018501548a81168884015260a01c166040820152815287600381600286015416948784019586520154166040820152613f22565b5f52600a8352600960405f20018d5f5283528560405f2054915116905f60405180968195829463343b278f60e01b9a8b855260048501528460248501526044840152608060648401526084830190613929565b03925af1801561093a576001600160e01b0319915f91611572575b5016036108e1578361156893895f897fd809c572ff50b9615dc7c8d7f51fec6ca944c63d476accf7a86c759374b518e09a825260038552604082208219815401905582825260028552604082206001600160a01b03199081815416905560048652604083209081541690557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a46114e23688866139aa565b50510151165f52600d835260405f20865f52600a8452600960405f2001885f52845260405f20545f52835260405f2060ff198154169055865f52600c83525f6040812055855f52600a8352600960405f2001875f528352611557600360405f205f8155611551600182016143a4565b016143a4565b604051938385948552840191613bd5565b0390a36001600955005b6115899150873d8911610933576109258183613844565b8b611448565b60046040517f4d5e5fb3000000000000000000000000000000000000000000000000000000008152fd5b34610208575f366003190112610208576040515f600182600154926115dd846137d4565b92838352602094856001821691825f1461167757505060011461161c575b5061160892500383613844565b610b28604051928284938452830190613929565b84915060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6905f915b85831061165f5750506116089350820101856115fb565b80548389018501528794508693909201918101611648565b60ff19168582015261160895151560051b85010192508791506115fb9050565b34610208576040366003190112610208576001600160a01b036116b861394e565b165f52600d60205260405f206024355f52602052602060ff60405f2054166040519015158152f35b34610208575f3660031901126102085760206001600160a01b0360065416604051908152f35b346102085760031960e0368201126102085760043567ffffffffffffffff8111610208576117389036906004016139e0565b60603660431901126102085760a43567ffffffffffffffff811161020857611764903690600401613aa3565b9260c43567ffffffffffffffff811161020857611785903690600401613aa3565b91611792602435336142b9565b602061179d86613f22565b956117a787613f9f565b0151907320000000000000000000000000000000000000008216611b26575b50505050815f52600a60205260405f20926040516117e38161380c565b6044358015158103610208578152606435908115158203610208576020810191825260843580151581036102085760408201526118213684866139aa565b91516119e9575b60400151611885575b50907f0ff02dbda49d1d200fdced84b11f0993013b07d4624643d56e527a8f6a195b1c91611880604051928392602435845261186f60208501613ec5565b60a0608085015260a0840191613bd5565b0390a2005b61189a81602080600994518301019101614325565b9590506024355f52016020526020600460405f206003810187516118bd81613b19565b6118c681613b19565b60ff80198354169116179055019401519384519467ffffffffffffffff8611610a3e576118fd866118f784546137d4565b84613dad565b602090601f871160011461196357958061194e927f0ff02dbda49d1d200fdced84b11f0993013b07d4624643d56e527a8f6a195b1c97985f926119585750508160011b915f199060031b1c19161790565b90555b8392611831565b0151905088806105d3565b90601f19871691835f5260205f20925f5b8181106119d157509160019391897f0ff02dbda49d1d200fdced84b11f0993013b07d4624643d56e527a8f6a195b1c999a94106119b9575b505050811b019055611951565b01515f1960f88460031b161c191690558780806119ac565b92936020600181928786015181550195019301611974565b6119fc6020835184010160208401614325565b506024355f526009870160205260405f20906020600191600184018151611a2281613b19565b611a2b81613b19565b60ff8019835416911617905501519081519167ffffffffffffffff8311610a3e57611a6683611a5d60028701546137d4565b60028701613dad565b602091601f8411600114611ab25750826040959493600293611a9c935f92611aa75750508160011b915f199060031b1c19161790565b9101555b9050611828565b015190508c806105d3565b9190600285015f5260205f20925f905b601f1986168210611b0d57505092600292600192604097969583601f19811610611af5575b505050811b01910155611aa0565b01515f1960f88460031b161c191690558b8080611ae7565b9092936020828192878601518155019501930190611ac2565b855f52600a60205260405f206009016024355f5260205260405f20549360405193849283927fc027774f0000000000000000000000000000000000000000000000000000000097888552336004860152602485015260448401611b8890613ec5565b60e060a4850152611b9d60e485018c8b613bd5565b918483030160c4850152611bb092613bd5565b03916001600160a01b031691815a6020945f91f1801561093a576001600160e01b0319915f91611beb575b5016036108e157838080806117c6565b611c04915060203d602011610933576109258183613844565b86611bdb565b34610208575f366003190112610208576007546001600160a01b033381831603611c72576001600160a01b03198092166007556006549133908316176006553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b346102085760031960c0368201126102085760043567ffffffffffffffff608052608051811161020857611cda9036906004016139e0565b606036602319011261020857608435608051811161020857611d00903690600401613aa3565b60a435608051811161020857611d1b82913690600401613aa3565b611d2786939293613f22565b95611d3187613ff7565b6020938480920151876001600160a01b039a8b7340000000000000000000000000000000000000008416612251575b5050505050505050835f52600a815260405f2090604051611d808161380c565b602496873580151581036102085782526044358015158103610208578383019081526064359182151583036102085760408401928352611dc136888a6139aa565b9351612078575b5051611f74575b51611e1c575b857f148308a842355fbe1f185663b4e0b252e76c8da58ec5fa0bf450a9d400b0212c8686611880604051928392611e0b84613e90565b608060608501526080840191613bd5565b6008611e318284808095518301019101614156565b9580925060079150018551611e4581613b19565b611e4e81613b19565b60ff80198354169116179055019201518051966080518811611f625750611e7f87611e7985546137d4565b85613dad565b81601f8811600114611edb57509580611ecf927f148308a842355fbe1f185663b4e0b252e76c8da58ec5fa0bf450a9d400b0212c97985f926119585750508160011b915f199060031b1c19161790565b90555b83928580611dd5565b9190601f198816845f52835f20935f905b828210611f4a5750509160019391897f148308a842355fbe1f185663b4e0b252e76c8da58ec5fa0bf450a9d400b0212c999a9410611f32575b505050811b019055611ed2565b01515f1960f88460031b161c19169055878080611f25565b80600186978294978701518155019601940190611eec565b634e487b7160e01b5f5260416004525ffd5b611f85838351840101848401614156565b509050600585018151611f9781613b19565b611fa081613b19565b60ff801983541691161790558360068601910151805190608051821161206557611fce82611e7985546137d4565b8590601f831160011461200257611ffb92915f9183611aa75750508160011b915f199060031b1c19161790565b9055611dcf565b90601f19831691845f52875f20925f5b8982821061204f575050908460019594939210612037575b505050811b019055611dcf565b01515f1960f88460031b161c191690558b808061202a565b6001859682939686015181550195019301612012565b8a634e487b7160e01b5f5260416004525ffd5b612089858551860101868601614156565b5050906002870190825191825191608051831161221757680100000000000000009384841161223e5789906120c3858554818755866140a9565b01915f52885f20905f5b84811061222a57505050505060038701868301518051926080518411612217578311612204578790612104848454818655856140a9565b01905f52865f205f5b8381106121f2575050505060406004870191015180519060805182116121df5761213b82611e7985546137d4565b8690601f831160011461217c5761216892915f91836121715750508160011b915f199060031b1c19161790565b90555b89611dc8565b015190508d806105d3565b90601f19831691845f52885f20925f5b8a8282106121c95750509084600195949392106121b1575b505050811b01905561216b565b01515f1960f88460031b161c191690558c80806121a4565b600185968293968601518155019501930161218c565b8b634e487b7160e01b5f5260416004525ffd5b8251828201559188019160010161210d565b8c634e487b7160e01b5f5260416004525ffd5b8d634e487b7160e01b5f5260416004525ffd5b8351821683820155928a01926001016120cd565b8e634e487b7160e01b5f5260416004525ffd5b6122ac926122bb5f93604051998a98899788957f85ad8432000000000000000000000000000000000000000000000000000000009e8f885233600489015261229b60248901613e90565b60c0608489015260c4880191613bd5565b928584030160a4860152613bd5565b0393165af1801561093a576001600160e01b0319915f916122eb575b5016036108e157818682818087818b611d60565b6123029150843d8611610933576109258183613844565b886122d7565b34610208575f36600319011261020857612320614095565b5f6001600160a01b036001600160a01b03198060075416600755600654908116600655167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610208576020366003190112610208576001600160a01b0361238b61394e565b1680156123a8575f526003602052602060405f2054604051908152f35b60046040517fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b346102085760203660031901126102085760206123f0600435613e72565b6001600160a01b0360405191168152f35b346102085761241b61241236613ad1565b91929092613f22565b9161242583613ff7565b825f52602090600a825260405f2061243e3685846139aa565b60018092019181519167ffffffffffffffff8311610a3e5761246a8361246486546137d4565b86613dad565b8591601f84116001146124df5750827ff878379401b7106f0505e17f9d1685ae35bdf56bcc0584fbead76082e10408479796959361188095936124c1935f926124d45750508160011b915f199060031b1c19161790565b9055604051938385948552840191613bd5565b015190508a806105d3565b9190601f198416855f52875f20935f905b8282106125545750509260019285927ff878379401b7106f0505e17f9d1685ae35bdf56bcc0584fbead76082e10408479a99989661188098961061253c575b505050811b019055611557565b01515f1960f88460031b161c1916905589808061252f565b8385015186559485019493890193908901906124f0565b346102085760c03660031901126102085760043567ffffffffffffffff81116102085761259c9036906004016139e0565b60243567ffffffffffffffff8111610208576125bc903690600401613aa3565b919067ffffffffffffffff6044351161020857606060443536036003190112610208576064359067ffffffffffffffff82116102085760406003198336030112610208576084359367ffffffffffffffff851161020857604060031986360301126102085760a43567ffffffffffffffff811161020857612641903690600401613aa3565b909561264b614095565b61265486613f22565b95865f52600a60205260ff60405f20541661309c57855f602061270f6001600160a01b0382860151168c6040519485809481938c6126fd8d6126e87f1e817d7a000000000000000000000000000000000000000000000000000000009d8e885233600489015260a060248901526126d360a48901604435600401613c94565b8881036003190160448a015290600401613d5b565b86810360031901606488015290600401613d5b565b84810360031901608486015291613bd5565b03925af1801561093a576001600160e01b0319915f9161307d575b5016036108e157865f52600b60205260405f208151805180519067ffffffffffffffff8211610a3e576127618261246486546137d4565b602090601f83116001146130155761278f92915f91836121715750508160011b915f199060031b1c19161790565b82555b60018201906001600160a01b036020820151167fffffffffffffffffff000000000000000000000000000000000000000000000076ffffff00000000000000000000000000000000000000006040855494015160a01b16921617179055600281016001600160a01b036020840151166001600160a01b031982541617905560036001600160a01b036040840151166001600160a01b0319828401541617910155865f52600a60205260405f206128493686886139aa565b6040516128558161380c565b6044356004013567ffffffffffffffff81116102085736602382604435010112156102085760048160443501013561288c81613df0565b9161289a6040519384613844565b81835260208301903660248460051b836044350101011161020857906024826044350101915b60248460051b826044350101018310612ff9575050505081526024604435013567ffffffffffffffff81116102085736602382604435010112156102085760048160443501013561291081613df0565b9161291e6040519384613844565b81835260208301903660248460051b836044350101011161020857906024826044350101915b60248460051b826044350101018310612fe45750505050602082015260448035013567ffffffffffffffff81116102085761298790600436916044350101613e08565b6040820152612999368a600401613e23565b906129a73687600401613e23565b845461ffff19166101011785558351909367ffffffffffffffff8211610a3e576129e1826129d860018901546137d4565b60018901613dad565b602090601f8311600114612f7657612a0f92915f91836109c35750508160011b915f199060031b1c19161790565b60018501555b805180519067ffffffffffffffff8211610a3e57680100000000000000008211610a3e5760028601805483825560209291612a519185916140a9565b01600286015f5260205f205f5b838110612f595750505050602081015180519067ffffffffffffffff8211610a3e57680100000000000000008211610a3e5760038601805483825560209291612aa89185916140a9565b01600386015f5260205f205f5b838110612f4557505050506040015180519067ffffffffffffffff8211610a3e57612af082612ae760048801546137d4565b60048801613dad565b602090601f8311600114612ed6579180612b2292602095945f926109c35750508160011b915f199060031b1c19161790565b60048501555b600584018151612b3781613b19565b612b4081613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e57612b7a82612b7160068701546137d4565b60068701613dad565b602090601f8311600114612e67579180612bac92602095945f92612e5c5750508160011b915f199060031b1c19161790565b60068401555b600783018151612bc181613b19565b612bca81613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e57612c0482612bfb60088601546137d4565b60088601613dad565b602090601f8311600114612dc05793612d41936008612c6585612d519996612d30967f3027341f34815cca50944a0e25775777a107c67be84b8e4f93815309c616d4b99e9d9c9a5f92612db55750508160011b915f199060031b1c19161790565b9101555b8a5f52600860205260405f205f805260205260405f20335f5260205260ff60405f20541615612d56575b6080604051826001600160a01b0360408395519262ffffff826020612cbf875189815193849201613908565b601f80199101168701958560208201511687520151166020850152826020820151168285015201511660608201520301902098612d1f612d0c604051998a9960a08b5260a08b0191613bd5565b88810360208a0152604435600401613c94565b908782036040890152600401613d5b565b908582036060870152600401613d5b565b9083820360808501523398613bd5565b0390a4005b8a5f52600860205260405f205f805260205260405f20335f5260205260405f20600160ff198254161790556040518b815233905f7ffd42b803bd411d88d791473b7eff0fda06e0a418bb50cd5040b3c0a73a6add4260203393a4612c93565b015190505f806105d3565b90600884015f5260205f20915f5b601f1985168110612e445750936008600185612d30957f3027341f34815cca50944a0e25775777a107c67be84b8e4f93815309c616d4b99d9c9b9995612d4199612d519c99601f19811610612e2c575b505050811b01910155612c69565b01515f1960f88460031b161c191690555f8080612e1e565b91926020600181928685015181550194019201612dce565b015190508e806105d3565b90600685015f5260205f20915f5b601f1985168110612ebe575091839160019360209695601f19811610612ea6575b505050811b016006840155612bb2565b01515f1960f88460031b161c191690558d8080612e96565b91926020600181928685015181550194019201612e75565b90600486015f5260205f20915f5b601f1985168110612f2d575091839160019360209695601f19811610612f15575b505050811b016004850155612b28565b01515f1960f88460031b161c191690558e8080612f05565b91926020600181928685015181550194019201612ee4565b600190602084519401938184015501612ab5565b60019060206001600160a01b038551169401938184015501612a5e565b9190600187015f5260205f20905f935b601f1984168510612fc9576001945083601f19811610612fb1575b505050811b016001850155612a15565b01515f1960f88460031b161c191690558e8080612fa1565b81810151835560209485019460019093019290910190612f86565b60208060249385358152019301929150612944565b6020806024936130088661397a565b81520193019291506128c0565b9190845f5260205f20905f935b601f1984168510613062576001945083601f1981161061304a575b505050811b018255612792565b01515f1960f88460031b161c191690558c808061303d565b81810151835560209485019460019093019290910190613022565b613096915060203d602011610933576109258183613844565b8b61272a565b60046040517f0dc149f0000000000000000000000000000000000000000000000000000000008152fd5b34610208576130d436613b60565b906130de83613f22565b5f526131076020936008855260405f20835f5285526101fc600160405f2001546101f783613f22565b92835f526008815260405f20825f5281526001600160a01b0360405f20931692835f52815260ff60405f2054161561313b57005b7ffd42b803bd411d88d791473b7eff0fda06e0a418bb50cd5040b3c0a73a6add4290845f526008815260405f20835f52815260405f20845f52815260405f20600160ff198254161790556040519485523394a4005b34610208576020806003193601126102085760043567ffffffffffffffff8111610208576131c56131e59136906004016139e0565b6131cd613bf5565b506131d6613c14565b506131df613c14565b50613f22565b5f52600a815260405f206131f7613bf5565b50613200613c14565b50613209613c14565b508054906001906002810161321f838301613866565b926040519161322d8361380c565b60405190818882549182815201915f52885f20905f5b8181106133b85750505081613259910382613844565b82526003830195604051809788918382549182815201915f52835f20905f5b8181106133a2575050509061328e910388613844565b8083019687526132a060048501613866565b91604084019283526132ec6132c360076132bc60058901614069565b9701614069565b9660ff6040519981811615158b5260081c161515848a015260c060408a015260c0890190613929565b9787890360608901526060890194519460608a5285518091528360808b019601905f5b818110613386575050505193888103838a01528280865192838152019501925f5b828110613373578980610b288b6133658f6133578d8f928e51906040818403910152613929565b908582036080870152613b37565b9083820360a0850152613b37565b8451875295810195938101938301613330565b82516001600160a01b031688529685019691850191840161330f565b825484528b945092850192918601918601613278565b82546001600160a01b03168452928a0192918501918501613243565b34610208575f3660031901126102085760206040515f8152f35b34610208575f3660031901126102085760206040517ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab8152f35b346102085761343636613ad1565b61343f83613f22565b9261344984613f9f565b835f526020906008825260405f207ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab90815f52835260405f20335f52835260ff60405f2054161561355f5750816001600160a01b039101511660405182817f1cff79cd000000000000000000000000000000000000000000000000000000009384825233600483015260406024830152815f816134ea604482018b8d613bd5565b03925af1801561093a576001600160e01b0319915f91613542575b5016036108e1576118807f24e793c46ba99c2162df48f5c34139e5a5a8e3a5953088dff8365ed072ae998693604051938385948552840191613bd5565b6135599150843d8611610933576109258183613844565b87613505565b604490604051906301d4003760e61b82526004820152336024820152fd5b346102085760403660031901126102085761359661394e565b60243590815f5260026020526001600160a01b038060405f205416908133141580613605575b61113557835f52600460205260405f20921691826001600160a01b03198254161790557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4005b50815f52600560205260405f20335f5260205260ff60405f205416156135bc565b34610208576020366003190112610208576004355f52600460205260206001600160a01b0360405f205416604051908152f35b34610208575f366003190112610208576040515f8054908261367a836137d4565b91828252602093600190856001821691825f146116775750506001146136a7575061160892500383613844565b5f808052859250907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8583106136e85750506116089350820101856115fb565b805483890185015287945086939092019181016136d1565b34610208576020366003190112610208576004356001600160e01b0319811680910361020857807f01ffc9a70000000000000000000000000000000000000000000000000000000060209214908115613790575b8115613766575b506040519015158152f35b7f5b5e139f000000000000000000000000000000000000000000000000000000009150148261375b565b7f80ac58cd0000000000000000000000000000000000000000000000000000000081149150613754565b34610208575f36600319011261020857602090600e548152f35b90600182811c92168015613802575b60208310146137ee57565b634e487b7160e01b5f52602260045260245ffd5b91607f16916137e3565b6060810190811067ffffffffffffffff821117610a3e57604052565b6040810190811067ffffffffffffffff821117610a3e57604052565b90601f8019910116810190811067ffffffffffffffff821117610a3e57604052565b9060405191825f8254613878816137d4565b908184526020946001916001811690815f146138e657506001146138a8575b5050506138a692500383613844565b565b5f90815285812095935091905b8183106138ce5750506138a693508201015f8080613897565b855488840185015294850194879450918301916138b5565b925050506138a694925060ff191682840152151560051b8201015f8080613897565b5f5b8381106139195750505f910152565b818101518382015260200161390a565b9060209161394281518092818552858086019101613908565b601f01601f1916010190565b600435906001600160a01b038216820361020857565b602435906001600160a01b038216820361020857565b35906001600160a01b038216820361020857565b67ffffffffffffffff8111610a3e57601f01601f191660200190565b9291926139b68261398e565b916139c46040519384613844565b829481845281830111610208578281602093845f960137010152565b91909160608184031261020857604080516139fa8161380c565b809483359067ffffffffffffffff9182811161020857850160608183031261020857845192613a288461380c565b813590811161020857810182601f82011215610208578592816020613a4f933591016139aa565b8352613a5d6020820161397a565b6020840152013562ffffff811681036102085783820152815260208301356001600160a01b03938482168203610208578391602084015201359283168303610208570152565b9181601f840112156102085782359167ffffffffffffffff8311610208576020838186019501011161020857565b9060406003198301126102085767ffffffffffffffff6004358181116102085783613afe916004016139e0565b9260243591821161020857613b1591600401613aa3565b9091565b60041115613b2357565b634e487b7160e01b5f52602160045260245ffd5b9060406020613b5d938051613b4b81613b19565b84520151918160208201520190613929565b90565b6060600319820112610208576004359067ffffffffffffffff821161020857613b8b916004016139e0565b90602435906044356001600160a01b03811681036102085790565b60243590811515820361020857565b9081602091031261020857516001600160e01b0319811681036102085790565b908060209392818452848401375f828201840152601f01601f1916010190565b60405190613c028261380c565b60606040838281528260208201520152565b60405190613c2182613828565b60606020835f81520152565b9035601e198236030181121561020857016020813591019167ffffffffffffffff8211610208578160051b3603831361020857565b9035601e198236030181121561020857016020813591019167ffffffffffffffff821161020857813603831361020857565b906060810191613ca48180613c2d565b606084529384905260808301935f5b818110613d3257505050613cca6020820182613c2d565b838592950360208501528082527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811161020857613b5d94602092613d1e9260051b80928583013701926040810190613c62565b929093604083828403019101520191613bd5565b9091946001906001600160a01b03613d498861397a565b16815260209081019601929101613cb3565b90813591600483101561020857613d8760409184613d7b613b5d96613b19565b84526020810190613c62565b9190928160208201520191613bd5565b818110613da2575050565b5f8155600101613d97565b9190601f8111613dbc57505050565b6138a6925f5260205f20906020601f840160051c83019310613de6575b601f0160051c0190613d97565b9091508190613dd9565b67ffffffffffffffff8111610a3e5760051b60200190565b9080601f8301121561020857816020613b5d933591016139aa565b91906040838203126102085760405190613e3c82613828565b81938035600481101561020857835260208101359167ffffffffffffffff831161020857602092613e6d9201613e08565b910152565b5f5260026020526001600160a01b0360405f205416801561158f5790565b602435801515809103610208578152604435801515809103610208576020820152606435908115158092036102085760400152565b604435801515809103610208578152606435801515809103610208576020820152608435908115158092036102085760400152565b60405190613f078261380c565b815f8152613f13613c14565b60208201526040613e6d613c14565b604051613f99816020810193602085528051606060408401526040613f548251606060a0870152610100860190613929565b6020838101516001600160a01b0390811660c08801529383015162ffffff1660e08701528401518316606086015292015116608083015203601f198101835282613844565b51902090565b5f52600a60205260405f205460ff811615908115613fe9575b50613fbf57565b60046040517f571ad9a4000000000000000000000000000000000000000000000000000000008152fd5b60ff915060081c165f613fb8565b5f52600860205260405f205f805260205260405f20335f5260205260ff60405f2054161561402157565b60446040516301d4003760e61b81525f6004820152336024820152fd5b5f52600860205260405f20815f5260205260405f20335f5260205260ff60405f2054161561355f5750565b9060405161407681613828565b6020613e6d6001839560ff81541661408d81613b19565b855201613866565b6001600160a01b03600654163303611c7257565b918181106140b657505050565b6138a6925f5260205f209182019101613d97565b81601f820112156102085780516140e08161398e565b926140ee6040519485613844565b8184526020828401011161020857613b5d9160208085019101613908565b9190604083820312610208576040519061412582613828565b81938051600481101561020857835260208101519167ffffffffffffffff831161020857602092613e6d92016140ca565b90916060828403126102085781519167ffffffffffffffff92838111610208578101936060858203126102085760409384516141918161380c565b86518281116102085787019683601f890112156102085787516020986141b682613df0565b916141c38a519384613844565b8083528a8084019160051b83010191878311610208578b01905b82821061429a5750505082528781015183811161020857810184601f8201121561020857805161420c81613df0565b916142198a519384613844565b8183528a8084019260051b82010191878311610208578b809201905b83821061428b575050905083015286810151908382116102085761425b918591016140ca565b8682015295830151818111610208578261427691850161410c565b9483015190811161020857613b5d920161410c565b81518152908201908201614235565b81516001600160a01b0381168103610208578152908b01908b016141dd565b6001600160a01b039081806142cd85613e72565b1691161415918261430b575b50506142e157565b60046040517faf38dd8c000000000000000000000000000000000000000000000000000000008152fd5b9091505f52600460205260405f2054163314155f806142d9565b9190916040818403126102085780519267ffffffffffffffff93848111610208578161435291840161410c565b93602083015190811161020857613b5d920161410c565b60026009541461437a576002600955565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b6001905f8155016143b581546137d4565b90816143bf575050565b81601f5f93116001146143d0575055565b9080839182526143ef601f60208420940160051c840160018501613d97565b5555565b5f5260026020526001600160a01b0360405f2054161561158f57565b9190825f52602060088152604090815f20835f5281526001600160a01b03825f20941693845f52815260ff825f20541661444b575b5050505050565b7fd66c534cd858591594a10d499350afab118f989fe4f96e96f29a18de6c309f8f91855f5260088252805f20845f528252805f20855f528252805f2060ff198154169055519485523394a45f8080808061444456fea164736f6c6343000818000a00000000000000000000000010b34b53b5989aa893c18e7fad4c460f98ce3847

Deployed Bytecode

0x60a0806040526004361015610012575f80fd5b5f3560e01c9081629a9b7b146137ba5750806301ffc9a71461370057806306fdde0314613659578063081812fc14613626578063095ea7b31461357d5780631a0d745514613428578063364bc15a146133ee57806345f51ea0146133d457806349cb877b146131905780634fdf096c146130c65780635da2a1481461256b578063614083c2146124015780636352211e146123d257806370a082311461236a578063715018a614612308578063767d375814611ca257806379ba509714611c0a5780638490e824146117065780638da5cb5b146116e0578063916aef691461169757806395d89b41146115b9578063987e24ae146112c1578063a22cb46514611240578063ae6cde0d14611216578063b1b44f23146111bd578063b88d4fde14610da9578063bbd987ab14610bee578063bf23fd2d14610b2c578063c87b56dd14610ad2578063d345ccd0146103f5578063de9dadf9146103a0578063e30c39781461037a578063e855014c14610321578063e985e9c5146102ce578063ec224ee214610275578063f2fde38b1461020c5763f82a0afa146101b2575f80fd5b34610208576102066102016101c636613b60565b9290916101d281613f22565b5f52600860205260405f20835f526020526101fc600160405f2001546101f783613f22565b61403e565b613f22565b61440f565b005b5f80fd5b346102085760203660031901126102085761022561394e565b61022d614095565b6001600160a01b0380911690816001600160a01b03196007541617600755600654167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b34610208576060366003190112610208576044356001600160a01b038116809103610208576004355f52600860205260405f206024355f5260205260405f20905f52602052602060ff60405f2054166040519015158152f35b34610208576040366003190112610208576102e761394e565b6102ef613964565b906001600160a01b038091165f52600560205260405f2091165f52602052602060ff60405f2054166040519015158152f35b346102085760403660031901126102085760043567ffffffffffffffff8111610208576101fc6103559136906004016139e0565b5f52600860205260405f206024355f526020526020600160405f200154604051908152f35b34610208575f3660031901126102085760206001600160a01b0360075416604051908152f35b34610208576103ae36613b60565b90336001600160a01b038316036103cb5761020161020693613f22565b60046040517f14d4a4e8000000000000000000000000000000000000000000000000000000008152fd5b346102085760031960a0368201126102085760043567ffffffffffffffff8111610208576104279036906004016139e0565b906044359167ffffffffffffffff8311610208576040828436030112610208576064359167ffffffffffffffff83116102085760409083360301126102085760843567ffffffffffffffff811161020857610486903690600401613aa3565b939092610491614369565b61049a83613f22565b926104a484613f9f565b60405192606060208501526104ff846104f16104de6104c96080840186600401613d5b565b838103601f1901604085015260048801613d5b565b828103601f190160608401528a8a613bd5565b03601f198101865285613844565b600e54965f198814610abe5760018801600e55600188015f52600c6020528560405f2055855f52600a60205260405f2061053c3684600401613e23565b6105493687600401613e23565b9060018b015f5260098301602052602060405f2091602435835560018301815161057281613b19565b61057b81613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e576105b5826105ac60028601546137d4565b60028601613dad565b602090601f8311600114610a525791806105e7926002945f926109c3575b50508160011b915f199060031b1c19161790565b9101555b60018a015f5260098201602052602060405f209160038301815161060e81613b19565b61061781613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e576106518261064860048601546137d4565b60048601613dad565b602090601f83116001146109ce5782600a959493600493610686935f926109c35750508160011b915f199060031b1c19161790565b9101555b6024355f52016020526001880160405f2055331561099957600188015f5260026020526001600160a01b03948560405f20541661096f57600189015f52600c60205260405f20545f52600b60205260405f20604051916106e98361380c565b6040516106f58161380c565b6106fe83613866565b815262ffffff60018401548a8116602084015260a01c1660408201528352876003816002850154169360208601948552015416604084015261073f83613f22565b5f52600a602052600960405f200160018c015f5260205287602060405f205494510151165f52600d60205260405f20835f5260205260ff60405f205416610945576107c3602091895f9451169060405194858094819363343b278f60e01b998a84528460048501523360248501526044840152608060648401526084830190613929565b03925af1801561093a576001600160e01b0319915f9161090b575b5016036108e1576108c16001946108b06108d7947fcc92a97118e4c878d6de7aecc51f34f42d7705085bae63e4210f765c28d097809860208d98335f526003825260405f208b81540190558a8a015f526002825260405f20336001600160a01b03198254161790556040519a8b9a01335f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a4510151165f52600d60205260405f206024355f5260205260405f20600160ff19825416179055338752608060208801526080870190600401613d5b565b908582036040870152600401613d5b565b9083820360608501526001602435990197613bd5565b0390a46001600955005b60046040517fc8639962000000000000000000000000000000000000000000000000000000008152fd5b61092d915060203d602011610933575b6109258183613844565b810190613bb5565b8b6107de565b503d61091b565b6040513d5f823e3d90fd5b60046040517f5fd8a132000000000000000000000000000000000000000000000000000000008152fd5b60046040517fddefae28000000000000000000000000000000000000000000000000000000008152fd5b60046040517f9c8d2cd2000000000000000000000000000000000000000000000000000000008152fd5b015190508f806105d3565b90600484015f5260205f20915f5b601f1985168110610a26575092600492600192600a97969583601f19811610610a0e575b505050811b0191015561068a565b01515f1960f88460031b161c191690558e8080610a00565b919260206001819286850151815501940192016109dc565b634e487b7160e01b5f52604160045260245ffd5b90600284015f5260205f20915f5b601f1985168110610aa65750918391600193600295601f19811610610a8e575b505050811b019101556105eb565b01515f1960f88460031b161c191690558e8080610a80565b91926020600181928685015181550194019201610a60565b634e487b7160e01b5f52601160045260245ffd5b3461020857602036600319011261020857600435610aef816143f3565b5f52600c60205260405f20545f52600a602052610b28610b14600160405f2001613866565b604051918291602083526020830190613929565b0390f35b3461020857602080600319360112610208576009600435610b4b613efa565b50610b55816143f3565b805f52600c835260405f20545f52600a835260405f2090610b74613efa565b505f5201815260405f20610b2860405191610b8e8361380c565b80548352610bdb610bb36003610ba660018501614069565b9387870194855201614069565b9160408501928352604051958695818752519086015251606060408601526080850190613b37565b9051838203601f19016060850152613b37565b346102085760603660031901126102085767ffffffffffffffff60043581811161020857610c209036906004016139e0565b90610c29613ba6565b9060443590811161020857610c42903690600401613aa3565b610c4d849294613f22565b93610c5785613ff7565b60208080940151917304000000000000000000000000000000000000008316610d05575b50505050825f52600a815260405f208054921515908160ff8560081c16151514610cdb577f3a124f724f69accb9a3ebeeffa8015c57cd895408f8f3fedd5be1d6a5983caa59361ff008360081b169061ff001916179055604051908152a2005b60046040517ff525e320000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b0392610d60915f6040519586809581947f4f195105000000000000000000000000000000000000000000000000000000009a8b84523360048501528d15156024850152606060448501526064840191613bd5565b0393165af1801561093a576001600160e01b0319915f91610d8c575b5016036108e15783808281610c7b565b610da39150843d8611610933576109258183613844565b86610d7c565b3461020857608036600319011261020857610dc261394e565b610dca613964565b6044359160643567ffffffffffffffff811161020857610dee903690600401613aa3565b9290845f52602091600283526001600160a01b0390818060405f205416951694850361119357818116918215610999578533148015611175575b801561115f575b1561113557610e3f3688866139aa565b885f52600c865260405f20545f52600b86528560405f2091604051610e638161380c565b604051610e6f8161380c565b610e7885613866565b815262ffffff60018601548781168684015260a01c166040820152815284600381600287015416958584019687520154166040820152610eb781613f22565b5f52600a8352600960405f20018c5f52835260405f205490858b15948592839661110e575b50505061094557899489938015611107575b80156110e7575b61105f575b50505050505f526003845260405f205f198154019055815f5260405f2060018154019055865f526002845260405f206001600160a01b03199083828254161790556004855260405f209081541690558682867fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4610f7b3687856139aa565b503b15159485610fbd575b50505050509050610f9357005b60046040517f3da63931000000000000000000000000000000000000000000000000000000008152fd5b8395505f6110169597604051968795869485937f150b7a02000000000000000000000000000000000000000000000000000000009c8d865233600487015260248601526044850152608060648501526084840191613bd5565b03925af190811561093a576001600160e01b0319925f92611042575b5050161415808280808080610f86565b6110589250803d10610933576109258183613844565b8380611032565b61109d945116905f60405180968195829463343b278f60e01b9a8b855260048501528c60248501526044840152608060648401526084830190613929565b03925af1801561093a576001600160e01b0319915f916110ca575b5016036108e157848885818080610efa565b6110e19150873d8911610933576109258183613844565b8a6110b8565b507380000000000000000000000000000000000000008551161515610ef5565b505f610eee565b90919250510151165f52600d895260405f20815f52895260ff60405f205416858a8f610edc565b60046040517fea8e4eb5000000000000000000000000000000000000000000000000000000008152fd5b50875f52600485528060405f2054163314610e2f565b50855f526005855260405f20335f52855260ff60405f205416610e28565b60046040517f20994242000000000000000000000000000000000000000000000000000000008152fd5b346102085760403660031901126102085760043567ffffffffffffffff8111610208576101fc6111f19136906004016139e0565b5f52600a602052600a60405f20016024355f52602052602060405f2054604051908152f35b34610208576020366003190112610208576004355f52600c602052602060405f2054604051908152f35b346102085760403660031901126102085761125961394e565b611261613ba6565b335f5260056020526001600160a01b0360405f20921691825f5260205260405f209015159060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b346102085760603660031901126102085767ffffffffffffffff600435818111610208576112f39036906004016139e0565b602435916044359081116102085761130f903690600401613aa3565b611317614369565b61132083613f22565b9261132a84613f9f565b61133485336142b9565b845f52602090600282526001600160a01b03938460405f20541694851561158f578561142d856113653689876139aa565b8b5f52600c825260405f20545f52600b825260405f206113da60405161138a8161380c565b6040516113968161380c565b61139f84613866565b815262ffffff60018501548a81168884015260a01c166040820152815287600381600286015416948784019586520154166040820152613f22565b5f52600a8352600960405f20018d5f5283528560405f2054915116905f60405180968195829463343b278f60e01b9a8b855260048501528460248501526044840152608060648401526084830190613929565b03925af1801561093a576001600160e01b0319915f91611572575b5016036108e1578361156893895f897fd809c572ff50b9615dc7c8d7f51fec6ca944c63d476accf7a86c759374b518e09a825260038552604082208219815401905582825260028552604082206001600160a01b03199081815416905560048652604083209081541690557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a46114e23688866139aa565b50510151165f52600d835260405f20865f52600a8452600960405f2001885f52845260405f20545f52835260405f2060ff198154169055865f52600c83525f6040812055855f52600a8352600960405f2001875f528352611557600360405f205f8155611551600182016143a4565b016143a4565b604051938385948552840191613bd5565b0390a36001600955005b6115899150873d8911610933576109258183613844565b8b611448565b60046040517f4d5e5fb3000000000000000000000000000000000000000000000000000000008152fd5b34610208575f366003190112610208576040515f600182600154926115dd846137d4565b92838352602094856001821691825f1461167757505060011461161c575b5061160892500383613844565b610b28604051928284938452830190613929565b84915060015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6905f915b85831061165f5750506116089350820101856115fb565b80548389018501528794508693909201918101611648565b60ff19168582015261160895151560051b85010192508791506115fb9050565b34610208576040366003190112610208576001600160a01b036116b861394e565b165f52600d60205260405f206024355f52602052602060ff60405f2054166040519015158152f35b34610208575f3660031901126102085760206001600160a01b0360065416604051908152f35b346102085760031960e0368201126102085760043567ffffffffffffffff8111610208576117389036906004016139e0565b60603660431901126102085760a43567ffffffffffffffff811161020857611764903690600401613aa3565b9260c43567ffffffffffffffff811161020857611785903690600401613aa3565b91611792602435336142b9565b602061179d86613f22565b956117a787613f9f565b0151907320000000000000000000000000000000000000008216611b26575b50505050815f52600a60205260405f20926040516117e38161380c565b6044358015158103610208578152606435908115158203610208576020810191825260843580151581036102085760408201526118213684866139aa565b91516119e9575b60400151611885575b50907f0ff02dbda49d1d200fdced84b11f0993013b07d4624643d56e527a8f6a195b1c91611880604051928392602435845261186f60208501613ec5565b60a0608085015260a0840191613bd5565b0390a2005b61189a81602080600994518301019101614325565b9590506024355f52016020526020600460405f206003810187516118bd81613b19565b6118c681613b19565b60ff80198354169116179055019401519384519467ffffffffffffffff8611610a3e576118fd866118f784546137d4565b84613dad565b602090601f871160011461196357958061194e927f0ff02dbda49d1d200fdced84b11f0993013b07d4624643d56e527a8f6a195b1c97985f926119585750508160011b915f199060031b1c19161790565b90555b8392611831565b0151905088806105d3565b90601f19871691835f5260205f20925f5b8181106119d157509160019391897f0ff02dbda49d1d200fdced84b11f0993013b07d4624643d56e527a8f6a195b1c999a94106119b9575b505050811b019055611951565b01515f1960f88460031b161c191690558780806119ac565b92936020600181928786015181550195019301611974565b6119fc6020835184010160208401614325565b506024355f526009870160205260405f20906020600191600184018151611a2281613b19565b611a2b81613b19565b60ff8019835416911617905501519081519167ffffffffffffffff8311610a3e57611a6683611a5d60028701546137d4565b60028701613dad565b602091601f8411600114611ab25750826040959493600293611a9c935f92611aa75750508160011b915f199060031b1c19161790565b9101555b9050611828565b015190508c806105d3565b9190600285015f5260205f20925f905b601f1986168210611b0d57505092600292600192604097969583601f19811610611af5575b505050811b01910155611aa0565b01515f1960f88460031b161c191690558b8080611ae7565b9092936020828192878601518155019501930190611ac2565b855f52600a60205260405f206009016024355f5260205260405f20549360405193849283927fc027774f0000000000000000000000000000000000000000000000000000000097888552336004860152602485015260448401611b8890613ec5565b60e060a4850152611b9d60e485018c8b613bd5565b918483030160c4850152611bb092613bd5565b03916001600160a01b031691815a6020945f91f1801561093a576001600160e01b0319915f91611beb575b5016036108e157838080806117c6565b611c04915060203d602011610933576109258183613844565b86611bdb565b34610208575f366003190112610208576007546001600160a01b033381831603611c72576001600160a01b03198092166007556006549133908316176006553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b346102085760031960c0368201126102085760043567ffffffffffffffff608052608051811161020857611cda9036906004016139e0565b606036602319011261020857608435608051811161020857611d00903690600401613aa3565b60a435608051811161020857611d1b82913690600401613aa3565b611d2786939293613f22565b95611d3187613ff7565b6020938480920151876001600160a01b039a8b7340000000000000000000000000000000000000008416612251575b5050505050505050835f52600a815260405f2090604051611d808161380c565b602496873580151581036102085782526044358015158103610208578383019081526064359182151583036102085760408401928352611dc136888a6139aa565b9351612078575b5051611f74575b51611e1c575b857f148308a842355fbe1f185663b4e0b252e76c8da58ec5fa0bf450a9d400b0212c8686611880604051928392611e0b84613e90565b608060608501526080840191613bd5565b6008611e318284808095518301019101614156565b9580925060079150018551611e4581613b19565b611e4e81613b19565b60ff80198354169116179055019201518051966080518811611f625750611e7f87611e7985546137d4565b85613dad565b81601f8811600114611edb57509580611ecf927f148308a842355fbe1f185663b4e0b252e76c8da58ec5fa0bf450a9d400b0212c97985f926119585750508160011b915f199060031b1c19161790565b90555b83928580611dd5565b9190601f198816845f52835f20935f905b828210611f4a5750509160019391897f148308a842355fbe1f185663b4e0b252e76c8da58ec5fa0bf450a9d400b0212c999a9410611f32575b505050811b019055611ed2565b01515f1960f88460031b161c19169055878080611f25565b80600186978294978701518155019601940190611eec565b634e487b7160e01b5f5260416004525ffd5b611f85838351840101848401614156565b509050600585018151611f9781613b19565b611fa081613b19565b60ff801983541691161790558360068601910151805190608051821161206557611fce82611e7985546137d4565b8590601f831160011461200257611ffb92915f9183611aa75750508160011b915f199060031b1c19161790565b9055611dcf565b90601f19831691845f52875f20925f5b8982821061204f575050908460019594939210612037575b505050811b019055611dcf565b01515f1960f88460031b161c191690558b808061202a565b6001859682939686015181550195019301612012565b8a634e487b7160e01b5f5260416004525ffd5b612089858551860101868601614156565b5050906002870190825191825191608051831161221757680100000000000000009384841161223e5789906120c3858554818755866140a9565b01915f52885f20905f5b84811061222a57505050505060038701868301518051926080518411612217578311612204578790612104848454818655856140a9565b01905f52865f205f5b8381106121f2575050505060406004870191015180519060805182116121df5761213b82611e7985546137d4565b8690601f831160011461217c5761216892915f91836121715750508160011b915f199060031b1c19161790565b90555b89611dc8565b015190508d806105d3565b90601f19831691845f52885f20925f5b8a8282106121c95750509084600195949392106121b1575b505050811b01905561216b565b01515f1960f88460031b161c191690558c80806121a4565b600185968293968601518155019501930161218c565b8b634e487b7160e01b5f5260416004525ffd5b8251828201559188019160010161210d565b8c634e487b7160e01b5f5260416004525ffd5b8d634e487b7160e01b5f5260416004525ffd5b8351821683820155928a01926001016120cd565b8e634e487b7160e01b5f5260416004525ffd5b6122ac926122bb5f93604051998a98899788957f85ad8432000000000000000000000000000000000000000000000000000000009e8f885233600489015261229b60248901613e90565b60c0608489015260c4880191613bd5565b928584030160a4860152613bd5565b0393165af1801561093a576001600160e01b0319915f916122eb575b5016036108e157818682818087818b611d60565b6123029150843d8611610933576109258183613844565b886122d7565b34610208575f36600319011261020857612320614095565b5f6001600160a01b036001600160a01b03198060075416600755600654908116600655167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610208576020366003190112610208576001600160a01b0361238b61394e565b1680156123a8575f526003602052602060405f2054604051908152f35b60046040517fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b346102085760203660031901126102085760206123f0600435613e72565b6001600160a01b0360405191168152f35b346102085761241b61241236613ad1565b91929092613f22565b9161242583613ff7565b825f52602090600a825260405f2061243e3685846139aa565b60018092019181519167ffffffffffffffff8311610a3e5761246a8361246486546137d4565b86613dad565b8591601f84116001146124df5750827ff878379401b7106f0505e17f9d1685ae35bdf56bcc0584fbead76082e10408479796959361188095936124c1935f926124d45750508160011b915f199060031b1c19161790565b9055604051938385948552840191613bd5565b015190508a806105d3565b9190601f198416855f52875f20935f905b8282106125545750509260019285927ff878379401b7106f0505e17f9d1685ae35bdf56bcc0584fbead76082e10408479a99989661188098961061253c575b505050811b019055611557565b01515f1960f88460031b161c1916905589808061252f565b8385015186559485019493890193908901906124f0565b346102085760c03660031901126102085760043567ffffffffffffffff81116102085761259c9036906004016139e0565b60243567ffffffffffffffff8111610208576125bc903690600401613aa3565b919067ffffffffffffffff6044351161020857606060443536036003190112610208576064359067ffffffffffffffff82116102085760406003198336030112610208576084359367ffffffffffffffff851161020857604060031986360301126102085760a43567ffffffffffffffff811161020857612641903690600401613aa3565b909561264b614095565b61265486613f22565b95865f52600a60205260ff60405f20541661309c57855f602061270f6001600160a01b0382860151168c6040519485809481938c6126fd8d6126e87f1e817d7a000000000000000000000000000000000000000000000000000000009d8e885233600489015260a060248901526126d360a48901604435600401613c94565b8881036003190160448a015290600401613d5b565b86810360031901606488015290600401613d5b565b84810360031901608486015291613bd5565b03925af1801561093a576001600160e01b0319915f9161307d575b5016036108e157865f52600b60205260405f208151805180519067ffffffffffffffff8211610a3e576127618261246486546137d4565b602090601f83116001146130155761278f92915f91836121715750508160011b915f199060031b1c19161790565b82555b60018201906001600160a01b036020820151167fffffffffffffffffff000000000000000000000000000000000000000000000076ffffff00000000000000000000000000000000000000006040855494015160a01b16921617179055600281016001600160a01b036020840151166001600160a01b031982541617905560036001600160a01b036040840151166001600160a01b0319828401541617910155865f52600a60205260405f206128493686886139aa565b6040516128558161380c565b6044356004013567ffffffffffffffff81116102085736602382604435010112156102085760048160443501013561288c81613df0565b9161289a6040519384613844565b81835260208301903660248460051b836044350101011161020857906024826044350101915b60248460051b826044350101018310612ff9575050505081526024604435013567ffffffffffffffff81116102085736602382604435010112156102085760048160443501013561291081613df0565b9161291e6040519384613844565b81835260208301903660248460051b836044350101011161020857906024826044350101915b60248460051b826044350101018310612fe45750505050602082015260448035013567ffffffffffffffff81116102085761298790600436916044350101613e08565b6040820152612999368a600401613e23565b906129a73687600401613e23565b845461ffff19166101011785558351909367ffffffffffffffff8211610a3e576129e1826129d860018901546137d4565b60018901613dad565b602090601f8311600114612f7657612a0f92915f91836109c35750508160011b915f199060031b1c19161790565b60018501555b805180519067ffffffffffffffff8211610a3e57680100000000000000008211610a3e5760028601805483825560209291612a519185916140a9565b01600286015f5260205f205f5b838110612f595750505050602081015180519067ffffffffffffffff8211610a3e57680100000000000000008211610a3e5760038601805483825560209291612aa89185916140a9565b01600386015f5260205f205f5b838110612f4557505050506040015180519067ffffffffffffffff8211610a3e57612af082612ae760048801546137d4565b60048801613dad565b602090601f8311600114612ed6579180612b2292602095945f926109c35750508160011b915f199060031b1c19161790565b60048501555b600584018151612b3781613b19565b612b4081613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e57612b7a82612b7160068701546137d4565b60068701613dad565b602090601f8311600114612e67579180612bac92602095945f92612e5c5750508160011b915f199060031b1c19161790565b60068401555b600783018151612bc181613b19565b612bca81613b19565b60ff80198354169116179055015180519067ffffffffffffffff8211610a3e57612c0482612bfb60088601546137d4565b60088601613dad565b602090601f8311600114612dc05793612d41936008612c6585612d519996612d30967f3027341f34815cca50944a0e25775777a107c67be84b8e4f93815309c616d4b99e9d9c9a5f92612db55750508160011b915f199060031b1c19161790565b9101555b8a5f52600860205260405f205f805260205260405f20335f5260205260ff60405f20541615612d56575b6080604051826001600160a01b0360408395519262ffffff826020612cbf875189815193849201613908565b601f80199101168701958560208201511687520151166020850152826020820151168285015201511660608201520301902098612d1f612d0c604051998a9960a08b5260a08b0191613bd5565b88810360208a0152604435600401613c94565b908782036040890152600401613d5b565b908582036060870152600401613d5b565b9083820360808501523398613bd5565b0390a4005b8a5f52600860205260405f205f805260205260405f20335f5260205260405f20600160ff198254161790556040518b815233905f7ffd42b803bd411d88d791473b7eff0fda06e0a418bb50cd5040b3c0a73a6add4260203393a4612c93565b015190505f806105d3565b90600884015f5260205f20915f5b601f1985168110612e445750936008600185612d30957f3027341f34815cca50944a0e25775777a107c67be84b8e4f93815309c616d4b99d9c9b9995612d4199612d519c99601f19811610612e2c575b505050811b01910155612c69565b01515f1960f88460031b161c191690555f8080612e1e565b91926020600181928685015181550194019201612dce565b015190508e806105d3565b90600685015f5260205f20915f5b601f1985168110612ebe575091839160019360209695601f19811610612ea6575b505050811b016006840155612bb2565b01515f1960f88460031b161c191690558d8080612e96565b91926020600181928685015181550194019201612e75565b90600486015f5260205f20915f5b601f1985168110612f2d575091839160019360209695601f19811610612f15575b505050811b016004850155612b28565b01515f1960f88460031b161c191690558e8080612f05565b91926020600181928685015181550194019201612ee4565b600190602084519401938184015501612ab5565b60019060206001600160a01b038551169401938184015501612a5e565b9190600187015f5260205f20905f935b601f1984168510612fc9576001945083601f19811610612fb1575b505050811b016001850155612a15565b01515f1960f88460031b161c191690558e8080612fa1565b81810151835560209485019460019093019290910190612f86565b60208060249385358152019301929150612944565b6020806024936130088661397a565b81520193019291506128c0565b9190845f5260205f20905f935b601f1984168510613062576001945083601f1981161061304a575b505050811b018255612792565b01515f1960f88460031b161c191690558c808061303d565b81810151835560209485019460019093019290910190613022565b613096915060203d602011610933576109258183613844565b8b61272a565b60046040517f0dc149f0000000000000000000000000000000000000000000000000000000008152fd5b34610208576130d436613b60565b906130de83613f22565b5f526131076020936008855260405f20835f5285526101fc600160405f2001546101f783613f22565b92835f526008815260405f20825f5281526001600160a01b0360405f20931692835f52815260ff60405f2054161561313b57005b7ffd42b803bd411d88d791473b7eff0fda06e0a418bb50cd5040b3c0a73a6add4290845f526008815260405f20835f52815260405f20845f52815260405f20600160ff198254161790556040519485523394a4005b34610208576020806003193601126102085760043567ffffffffffffffff8111610208576131c56131e59136906004016139e0565b6131cd613bf5565b506131d6613c14565b506131df613c14565b50613f22565b5f52600a815260405f206131f7613bf5565b50613200613c14565b50613209613c14565b508054906001906002810161321f838301613866565b926040519161322d8361380c565b60405190818882549182815201915f52885f20905f5b8181106133b85750505081613259910382613844565b82526003830195604051809788918382549182815201915f52835f20905f5b8181106133a2575050509061328e910388613844565b8083019687526132a060048501613866565b91604084019283526132ec6132c360076132bc60058901614069565b9701614069565b9660ff6040519981811615158b5260081c161515848a015260c060408a015260c0890190613929565b9787890360608901526060890194519460608a5285518091528360808b019601905f5b818110613386575050505193888103838a01528280865192838152019501925f5b828110613373578980610b288b6133658f6133578d8f928e51906040818403910152613929565b908582036080870152613b37565b9083820360a0850152613b37565b8451875295810195938101938301613330565b82516001600160a01b031688529685019691850191840161330f565b825484528b945092850192918601918601613278565b82546001600160a01b03168452928a0192918501918501613243565b34610208575f3660031901126102085760206040515f8152f35b34610208575f3660031901126102085760206040517ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab8152f35b346102085761343636613ad1565b61343f83613f22565b9261344984613f9f565b835f526020906008825260405f207ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab90815f52835260405f20335f52835260ff60405f2054161561355f5750816001600160a01b039101511660405182817f1cff79cd000000000000000000000000000000000000000000000000000000009384825233600483015260406024830152815f816134ea604482018b8d613bd5565b03925af1801561093a576001600160e01b0319915f91613542575b5016036108e1576118807f24e793c46ba99c2162df48f5c34139e5a5a8e3a5953088dff8365ed072ae998693604051938385948552840191613bd5565b6135599150843d8611610933576109258183613844565b87613505565b604490604051906301d4003760e61b82526004820152336024820152fd5b346102085760403660031901126102085761359661394e565b60243590815f5260026020526001600160a01b038060405f205416908133141580613605575b61113557835f52600460205260405f20921691826001600160a01b03198254161790557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4005b50815f52600560205260405f20335f5260205260ff60405f205416156135bc565b34610208576020366003190112610208576004355f52600460205260206001600160a01b0360405f205416604051908152f35b34610208575f366003190112610208576040515f8054908261367a836137d4565b91828252602093600190856001821691825f146116775750506001146136a7575061160892500383613844565b5f808052859250907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8583106136e85750506116089350820101856115fb565b805483890185015287945086939092019181016136d1565b34610208576020366003190112610208576004356001600160e01b0319811680910361020857807f01ffc9a70000000000000000000000000000000000000000000000000000000060209214908115613790575b8115613766575b506040519015158152f35b7f5b5e139f000000000000000000000000000000000000000000000000000000009150148261375b565b7f80ac58cd0000000000000000000000000000000000000000000000000000000081149150613754565b34610208575f36600319011261020857602090600e548152f35b90600182811c92168015613802575b60208310146137ee57565b634e487b7160e01b5f52602260045260245ffd5b91607f16916137e3565b6060810190811067ffffffffffffffff821117610a3e57604052565b6040810190811067ffffffffffffffff821117610a3e57604052565b90601f8019910116810190811067ffffffffffffffff821117610a3e57604052565b9060405191825f8254613878816137d4565b908184526020946001916001811690815f146138e657506001146138a8575b5050506138a692500383613844565b565b5f90815285812095935091905b8183106138ce5750506138a693508201015f8080613897565b855488840185015294850194879450918301916138b5565b925050506138a694925060ff191682840152151560051b8201015f8080613897565b5f5b8381106139195750505f910152565b818101518382015260200161390a565b9060209161394281518092818552858086019101613908565b601f01601f1916010190565b600435906001600160a01b038216820361020857565b602435906001600160a01b038216820361020857565b35906001600160a01b038216820361020857565b67ffffffffffffffff8111610a3e57601f01601f191660200190565b9291926139b68261398e565b916139c46040519384613844565b829481845281830111610208578281602093845f960137010152565b91909160608184031261020857604080516139fa8161380c565b809483359067ffffffffffffffff9182811161020857850160608183031261020857845192613a288461380c565b813590811161020857810182601f82011215610208578592816020613a4f933591016139aa565b8352613a5d6020820161397a565b6020840152013562ffffff811681036102085783820152815260208301356001600160a01b03938482168203610208578391602084015201359283168303610208570152565b9181601f840112156102085782359167ffffffffffffffff8311610208576020838186019501011161020857565b9060406003198301126102085767ffffffffffffffff6004358181116102085783613afe916004016139e0565b9260243591821161020857613b1591600401613aa3565b9091565b60041115613b2357565b634e487b7160e01b5f52602160045260245ffd5b9060406020613b5d938051613b4b81613b19565b84520151918160208201520190613929565b90565b6060600319820112610208576004359067ffffffffffffffff821161020857613b8b916004016139e0565b90602435906044356001600160a01b03811681036102085790565b60243590811515820361020857565b9081602091031261020857516001600160e01b0319811681036102085790565b908060209392818452848401375f828201840152601f01601f1916010190565b60405190613c028261380c565b60606040838281528260208201520152565b60405190613c2182613828565b60606020835f81520152565b9035601e198236030181121561020857016020813591019167ffffffffffffffff8211610208578160051b3603831361020857565b9035601e198236030181121561020857016020813591019167ffffffffffffffff821161020857813603831361020857565b906060810191613ca48180613c2d565b606084529384905260808301935f5b818110613d3257505050613cca6020820182613c2d565b838592950360208501528082527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811161020857613b5d94602092613d1e9260051b80928583013701926040810190613c62565b929093604083828403019101520191613bd5565b9091946001906001600160a01b03613d498861397a565b16815260209081019601929101613cb3565b90813591600483101561020857613d8760409184613d7b613b5d96613b19565b84526020810190613c62565b9190928160208201520191613bd5565b818110613da2575050565b5f8155600101613d97565b9190601f8111613dbc57505050565b6138a6925f5260205f20906020601f840160051c83019310613de6575b601f0160051c0190613d97565b9091508190613dd9565b67ffffffffffffffff8111610a3e5760051b60200190565b9080601f8301121561020857816020613b5d933591016139aa565b91906040838203126102085760405190613e3c82613828565b81938035600481101561020857835260208101359167ffffffffffffffff831161020857602092613e6d9201613e08565b910152565b5f5260026020526001600160a01b0360405f205416801561158f5790565b602435801515809103610208578152604435801515809103610208576020820152606435908115158092036102085760400152565b604435801515809103610208578152606435801515809103610208576020820152608435908115158092036102085760400152565b60405190613f078261380c565b815f8152613f13613c14565b60208201526040613e6d613c14565b604051613f99816020810193602085528051606060408401526040613f548251606060a0870152610100860190613929565b6020838101516001600160a01b0390811660c08801529383015162ffffff1660e08701528401518316606086015292015116608083015203601f198101835282613844565b51902090565b5f52600a60205260405f205460ff811615908115613fe9575b50613fbf57565b60046040517f571ad9a4000000000000000000000000000000000000000000000000000000008152fd5b60ff915060081c165f613fb8565b5f52600860205260405f205f805260205260405f20335f5260205260ff60405f2054161561402157565b60446040516301d4003760e61b81525f6004820152336024820152fd5b5f52600860205260405f20815f5260205260405f20335f5260205260ff60405f2054161561355f5750565b9060405161407681613828565b6020613e6d6001839560ff81541661408d81613b19565b855201613866565b6001600160a01b03600654163303611c7257565b918181106140b657505050565b6138a6925f5260205f209182019101613d97565b81601f820112156102085780516140e08161398e565b926140ee6040519485613844565b8184526020828401011161020857613b5d9160208085019101613908565b9190604083820312610208576040519061412582613828565b81938051600481101561020857835260208101519167ffffffffffffffff831161020857602092613e6d92016140ca565b90916060828403126102085781519167ffffffffffffffff92838111610208578101936060858203126102085760409384516141918161380c565b86518281116102085787019683601f890112156102085787516020986141b682613df0565b916141c38a519384613844565b8083528a8084019160051b83010191878311610208578b01905b82821061429a5750505082528781015183811161020857810184601f8201121561020857805161420c81613df0565b916142198a519384613844565b8183528a8084019260051b82010191878311610208578b809201905b83821061428b575050905083015286810151908382116102085761425b918591016140ca565b8682015295830151818111610208578261427691850161410c565b9483015190811161020857613b5d920161410c565b81518152908201908201614235565b81516001600160a01b0381168103610208578152908b01908b016141dd565b6001600160a01b039081806142cd85613e72565b1691161415918261430b575b50506142e157565b60046040517faf38dd8c000000000000000000000000000000000000000000000000000000008152fd5b9091505f52600460205260405f2054163314155f806142d9565b9190916040818403126102085780519267ffffffffffffffff93848111610208578161435291840161410c565b93602083015190811161020857613b5d920161410c565b60026009541461437a576002600955565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b6001905f8155016143b581546137d4565b90816143bf575050565b81601f5f93116001146143d0575055565b9080839182526143ef601f60208420940160051c840160018501613d97565b5555565b5f5260026020526001600160a01b0360405f2054161561158f57565b9190825f52602060088152604090815f20835f5281526001600160a01b03825f20941693845f52815260ff825f20541661444b575b5050505050565b7fd66c534cd858591594a10d499350afab118f989fe4f96e96f29a18de6c309f8f91855f5260088252805f20845f528252805f20855f528252805f2060ff198154169055519485523394a45f8080808061444456fea164736f6c6343000818000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000010b34b53b5989aa893c18e7fad4c460f98ce3847

-----Decoded View---------------
Arg [0] : _owner (address): 0x10b34B53b5989Aa893c18e7fAD4c460f98cE3847

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000010b34b53b5989aa893c18e7fad4c460f98ce3847


Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
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  ]
[ 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.