Contract 0x4bea5e06cb0536cfd5fe32a3f3a20495fabedfd8

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x00fc5e8eb83b881f772e5ca020dafd02478b6c7edb210756f6e2a3b8a0583efb0x6080604014836262022-02-14 15:26:30408 days 4 hrs agoLido: Deployer IN  Create: Controller0 MOVR0.002611877
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Controller

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 10 : Controller.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "IERC20.sol";
import "Initializable.sol";

import "IRelayEncoder.sol";
import "IxTokens.sol";
import "IXcmTransactor.sol";
import "ILedger.sol";
import "IAuthManager.sol";
import "ILido.sol";



contract Controller is Initializable {
    // Event emitted when weight updated
    event WeightUpdated (
        uint8 index,
        uint64 newValue
    );

    // Event emitted when bond called on relay chain
    event Bond (
        address caller,
        bytes32 stash,
        bytes32 controller,
        uint256 amount
    );

    // Event emitted when bond extra called on relay chain
    event BondExtra (
        address caller,
        bytes32 stash,
        uint256 amount
    );

    // Event emitted when unbond on relay chain
    event Unbond (
        address caller,
        bytes32 stash,
        uint256 amount
    );

    // Event emitted when rebond called on relay chain
    event Rebond (
        address caller,
        bytes32 stash,
        uint256 amount
    );

    // Event emitted when withdraw called on relay chain
    event Withdraw (
        address caller,
        bytes32 stash
    );

    // Event emitted when nominate called on relay chain
    event Nominate (
        address caller,
        bytes32 stash,
        bytes32[] validators
    );

    // Event emitted when chill called on relay chain
    event Chill (
        address caller,
        bytes32 stash
    );

    // Event emitted when transfer vKSM from parachain to relay chain called
    event TransferToRelaychain (
        address from,
        bytes32 to,
        uint256 amount
    );

    // Event emitted when transfer KSM from relay chain to parachain called
    event TransferToParachain (
        bytes32 from,
        address to,
        uint256 amount
    );

    // ledger controller account
    uint16 public rootDerivativeIndex;

    // vKSM precompile
    IERC20 internal VKSM;

    // relay call builder precompile
    IRelayEncoder internal RELAY_ENCODER;

    // xcm transactor precompile
    IXcmTransactor internal XCM_TRANSACTOR;

    // xTokens precompile
    IxTokens internal X_TOKENS;

    // LIDO address
    address public LIDO;

    // first hex for encodeTransfer (defines parachain ID, 2023 for Kusama)
    bytes public hex1;

    // second hex for encodeTransfer (defines asset for transfer, fungible)
    bytes public hex2;

    // hex for determination pallet (0x1801 for Kusama)
    bytes public asDerevativeHex;

    // Second layer derivative-proxy account to index
    mapping(address => uint16) public senderToIndex;

    // Index to second layer derivative-proxy account
    mapping(uint16 => bytes32) public indexToAccount;

    // Enumerator for weights
    enum WEIGHT {
        AS_DERIVATIVE,              // 410_000_000
        BOND_BASE,                  // 600_000_000
        BOND_EXTRA_BASE,            // 1_100_000_000
        UNBOND_BASE,                // 1_250_000_000
        WITHDRAW_UNBONDED_BASE,     // 500_000_000
        WITHDRAW_UNBONDED_PER_UNIT, // 60_000
        REBOND_BASE,                // 1_200_000_000
        REBOND_PER_UNIT,            // 40_000
        CHILL_BASE,                 // 900_000_000
        NOMINATE_BASE,              // 1_000_000_000
        NOMINATE_PER_UNIT,          // 31_000_000
        TRANSFER_TO_PARA_BASE,      // 700_000_000
        TRANSFER_TO_RELAY_BASE      // 4_000_000_000
    }

    // Constant for max weight
    uint64 public MAX_WEIGHT;// = 1_835_300_000;

    // Array with current weights
    uint64[] public weights;

    // Parachain side fee on reverse transfer
    uint256 public REVERSE_TRANSFER_FEE;// = 4_000_000

    // Relay side fee on transfer
    uint256 public TRANSFER_FEE;// = 18_900_000_000

    // Controller manager role
    bytes32 internal constant ROLE_CONTROLLER_MANAGER = keccak256("ROLE_CONTROLLER_MANAGER");

    // Allows function calls only for registered ledgers
    modifier onlyRegistred() {
        require(senderToIndex[msg.sender] != 0, "CONTROLLER: UNREGISTERED_SENDER");
        _;
    }

    // Allows function calls only for members with role
    modifier auth(bytes32 role) {
        require(IAuthManager(ILido(LIDO).AUTH_MANAGER()).has(role, msg.sender), "CONTROLLER: UNAUTHOROZED");
        _;
    }

    // Allows function calls only for LIDO contract
    modifier onlyLido() {
        require(msg.sender == LIDO, "CONTROLLER: CALLER_NOT_LIDO");
        _;
    }

    /**
    * @notice Initialize ledger contract.
    * @param _rootDerivativeIndex - stash account id
    * @param _vKSM - vKSM contract address
    * @param _relayEncoder - relayEncoder(relaychain calls builder) contract address
    * @param _xcmTransactor - xcmTransactor(relaychain calls relayer) contract address
    * @param _xTokens - minimal allowed nominator balance
    * @param _hex1 - first hex for encodeTransfer
    * @param _hex2 - second hex for encodeTransfer
    * @param _asDerevativeHex - hex for as derevative call
    */
    function initialize(
        uint16 _rootDerivativeIndex,
        address _vKSM,
        address _relayEncoder,
        address _xcmTransactor,
        address _xTokens,
        bytes calldata _hex1,
        bytes calldata _hex2,
        bytes calldata _asDerevativeHex
    ) external initializer {
        require(address(VKSM) == address(0), "CONTROLLER: ALREADY_INITIALIZED");

        rootDerivativeIndex = _rootDerivativeIndex;

        VKSM = IERC20(_vKSM);
        RELAY_ENCODER = IRelayEncoder(_relayEncoder);
        XCM_TRANSACTOR = IXcmTransactor(_xcmTransactor);
        X_TOKENS = IxTokens(_xTokens);

        hex1 = _hex1;
        hex2 = _hex2;
        asDerevativeHex = _asDerevativeHex;
    }

    /**
    * @notice Get current weight by enum
    * @param weightType - enum index of weight
    */
    function getWeight(WEIGHT weightType) public view returns(uint64) {
        return weights[uint256(weightType)];
    }

    /**
    * @notice Set new max weight. Can be called only by ROLE_CONTROLLER_MANAGER
    * @param _maxWeight - max weight
    */
    function setMaxWeight(uint64 _maxWeight) external auth(ROLE_CONTROLLER_MANAGER) {
        MAX_WEIGHT = _maxWeight;
    }

    /**
    * @notice Set new REVERSE_TRANSFER_FEE
    * @param _reverseTransferFee - new fee
    */
    function setReverseTransferFee(uint256 _reverseTransferFee) external auth(ROLE_CONTROLLER_MANAGER) {
        REVERSE_TRANSFER_FEE = _reverseTransferFee;
    }

    /**
    * @notice Set new TRANSFER_FEE
    * @param _transferFee - new fee
    */
    function setTransferFee(uint256 _transferFee) external auth(ROLE_CONTROLLER_MANAGER) {
        TRANSFER_FEE = _transferFee;
    }
    /**
    * @notice Set new hexes parametes for encodeTransfer
    * @param _hex1 - first hex for encodeTransfer
    * @param _hex2 - second hex for encodeTransfer
    * @param _asDerevativeHex - hex for as derevative call
    */
    function updateHexParameters(bytes calldata _hex1, bytes calldata _hex2, bytes calldata _asDerevativeHex) external auth(ROLE_CONTROLLER_MANAGER) {
        hex1 = _hex1;
        hex2 = _hex2;
        asDerevativeHex = _asDerevativeHex;
    }

    /**
    * @notice Set LIDO address. Function can be called only once
    * @param _lido - LIDO address
    */
    function setLido(address _lido) external {
        require(LIDO == address(0) && _lido != address(0), "CONTROLLER: LIDO_ALREADY_INITIALIZED");
        LIDO = _lido;
    }

    /**
    * @notice Update weights array. Weight updated only if weight = _weight | 1 << 65
    * @param _weights - weights array
    */
    function setWeights(
        uint128[] calldata _weights
    ) external auth(ROLE_CONTROLLER_MANAGER) {
        require(_weights.length == uint256(type(WEIGHT).max) + 1, "CONTROLLER: WRONG_WEIGHTS_SIZE");
        for (uint256 i = 0; i < _weights.length; ++i) {
            if ((_weights[i] >> 64) > 0) { // if _weights[i] = _weights[i] | 1 << 65 we must update i-th weight
                if (weights.length == i) {
                    weights.push(0);
                }

                weights[i] = uint64(_weights[i]);
                emit WeightUpdated(uint8(i), weights[i]);
            }
        }
    }

    /**
    * @notice Register new ledger contract
    * @param index - index of ledger contract
    * @param accountId - relay chain address of ledger
    * @param paraAddress - parachain address of ledger
    */
    function newSubAccount(uint16 index, bytes32 accountId, address paraAddress) external onlyLido {
        require(indexToAccount[index + 1] == bytes32(0), "CONTROLLER: ALREADY_REGISTERED");

        senderToIndex[paraAddress] = index + 1;
        indexToAccount[index + 1] = accountId;
    }

    /**
    * @notice Unregister ledger contract
    * @param paraAddress - parachain address of ledger
    */
    function deleteSubAccount(address paraAddress) external onlyLido {
        require(senderToIndex[paraAddress] > 0, "CONTROLLER: UNREGISTERED_LEDGER");

        delete indexToAccount[senderToIndex[paraAddress]];
        delete senderToIndex[paraAddress];
    }

    /**
    * @notice Nominate validators from ledger on relay chain
    * @param validators - validators addresses to nominate
    */
    function nominate(bytes32[] calldata validators) external onlyRegistred {
        uint256[] memory convertedValidators = new uint256[](validators.length);
        for (uint256 i = 0; i < validators.length; ++i) {
            convertedValidators[i] = uint256(validators[i]);
        }
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.NOMINATE_BASE) + getWeight(WEIGHT.NOMINATE_PER_UNIT) * uint64(validators.length),
            RELAY_ENCODER.encode_nominate(convertedValidators)
        );

        emit Nominate(msg.sender, getSenderAccount(), validators);
    }

    /**
    * @notice Bond KSM of ledger on relay chain
    * @param controller - controller which used to bond
    * @param amount - amount of KSM to bond
    */
    function bond(bytes32 controller, uint256 amount) external onlyRegistred {
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.BOND_BASE),
            RELAY_ENCODER.encode_bond(uint256(controller), amount, bytes(hex"00"))
        );

        emit Bond(msg.sender, getSenderAccount(), controller, amount);
    }

    /**
    * @notice Bond extra KSM of ledger on relay chain
    * @param amount - extra amount of KSM to bond
    */
    function bondExtra(uint256 amount) external onlyRegistred {
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.BOND_EXTRA_BASE),
            RELAY_ENCODER.encode_bond_extra(amount)
        );

        emit BondExtra(msg.sender, getSenderAccount(), amount);
    }

    /**
    * @notice Unbond KSM of ledger on relay chain
    * @param amount - amount of KSM to unbond
    */
    function unbond(uint256 amount) external onlyRegistred {
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.UNBOND_BASE),
            RELAY_ENCODER.encode_unbond(amount)
        );

        emit Unbond(msg.sender, getSenderAccount(), amount);
    }

    /**
    * @notice Withdraw unbonded tokens (move unbonded tokens to free)
    * @param slashingSpans - number of slashes received by ledger in case if we trying set ledger bonded balance < min, 
    in other cases = 0
    */
    function withdrawUnbonded(uint32 slashingSpans) external onlyRegistred {
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.WITHDRAW_UNBONDED_BASE) + getWeight(WEIGHT.WITHDRAW_UNBONDED_PER_UNIT) * slashingSpans,
            RELAY_ENCODER.encode_withdraw_unbonded(slashingSpans)
        );

        emit Withdraw(msg.sender, getSenderAccount());
    }

    /**
    * @notice Rebond KSM of ledger from unbonded chunks on relay chain
    * @param amount - amount of KSM to rebond
    * @param unbondingChunks - amount of unbonding chunks to rebond
    */
    function rebond(uint256 amount, uint256 unbondingChunks) external onlyRegistred {
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.REBOND_BASE) + getWeight(WEIGHT.REBOND_PER_UNIT) * uint64(unbondingChunks),
            RELAY_ENCODER.encode_rebond(amount)
        );

        emit Rebond(msg.sender, getSenderAccount(), amount);
    }

    /**
    * @notice Put ledger to chill mode
    */
    function chill() external onlyRegistred {
        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.CHILL_BASE),
            RELAY_ENCODER.encode_chill()
        );

        emit Chill(msg.sender, getSenderAccount());
    }

    /**
    * @notice Transfer KSM from relay chain to parachain
    * @param amount - amount of KSM to transfer
    */
    function transferToParachain(uint256 amount) external onlyRegistred {
        // to - msg.sender, from - getSenderIndex()
        uint256 parachain_fee = REVERSE_TRANSFER_FEE;

        callThroughDerivative(
            getSenderIndex(),
            getWeight(WEIGHT.TRANSFER_TO_PARA_BASE),
            //encodeReverseTransfer(msg.sender, amount)
            encodeLimitReserveTransfer(msg.sender, amount, getWeight(WEIGHT.TRANSFER_TO_PARA_BASE))
        );

        // compensate parachain side fee on reverse transfer
        if (amount <= parachain_fee) {
            // if amount less than fee just transfer amount
            VKSM.transfer(msg.sender, amount);
        }
        else {
            // else just compensate fee
            VKSM.transfer(msg.sender, parachain_fee);
        }

        emit TransferToParachain(getSenderAccount(), msg.sender, amount);
    }

    /**
    * @notice Transfer vKSM from parachain to relay chain
    * @param amount - amount of vKSM to transfer
    */
    function transferToRelaychain(uint256 amount) external onlyRegistred {
        // to - getSenderIndex(), from - msg.sender
        VKSM.transferFrom(msg.sender, address(this), amount);
        IxTokens.Multilocation memory destination;
        destination.parents = 1;
        destination.interior = new bytes[](1);
        destination.interior[0] = bytes.concat(bytes1(hex"01"), getSenderAccount(), bytes1(hex"00")); // X2, NetworkId: Any
        X_TOKENS.transfer_with_fee(address(VKSM), amount, TRANSFER_FEE, destination, getWeight(WEIGHT.TRANSFER_TO_RELAY_BASE));

        emit TransferToRelaychain(msg.sender, getSenderAccount(), amount);
    }

    /**
    * @notice Get index of registered ledger
    */
    function getSenderIndex() internal returns(uint16) {
        return senderToIndex[msg.sender] - 1;
    }

    /**
    * @notice Get relay chain address of msg.sender
    */
    function getSenderAccount() internal returns(bytes32) {
        return indexToAccount[senderToIndex[msg.sender]];
    }

    /**
    * @notice Send call to relay cahin through xcm transactor
    * @param index - index of ledger on relay chain
    * @param weight - fees on tx execution
    * @param call - bytes for tx execution
    */
    function callThroughDerivative(uint16 index, uint64 weight, bytes memory call) internal {
        bytes memory le_index = new bytes(2);
        le_index[0] = bytes1(uint8(index));
        le_index[1] = bytes1(uint8(index >> 8));

        uint64 total_weight = weight + getWeight(WEIGHT.AS_DERIVATIVE);
        require(total_weight <= MAX_WEIGHT, "CONTROLLER: TOO_MUCH_WEIGHT");

        XCM_TRANSACTOR.transact_through_derivative(
            0, // The transactor to be used
            rootDerivativeIndex, // The index to be used
            address(VKSM), // Address of the currencyId of the asset to be used for fees
            total_weight, // The weight we want to buy in the destination chain
            bytes.concat(asDerevativeHex, le_index, call) // The inner call to be executed in the destination chain
        );
    }

    /**
    * @notice Encoding bytes to call transfer on relay chain
    * @param to - address of KSM receiver
    * @param amount - amount of KSM to send
    */
    function encodeReverseTransfer(address to, uint256 amount) internal returns(bytes memory) {
        return bytes.concat(
            hex1,
            abi.encodePacked(to),
            hex2,
            scaleCompactUint(amount),
            hex"00000000"
        );
    }

    /**
    * @notice Encoding bytes to call limit reserve transfer on relay chain
    * @param to - address of KSM receiver
    * @param amount - amount of KSM to send
    * @param weight - weight for xcm call
    */
    function encodeLimitReserveTransfer(address to, uint256 amount, uint64 weight) internal returns(bytes memory) {
        return bytes.concat(
            hex1,
            abi.encodePacked(to),
            hex2,
            scaleCompactUint(amount),
            hex"0000000001",
            scaleCompactUint(uint256(weight))
        );
    }

    /**
    * @notice Converting uint256 value to le bytes
    * @param value - uint256 value
    * @param len - length of output bytes array
    */
    function toLeBytes(uint256 value, uint256 len) internal returns(bytes memory) {
        bytes memory out = new bytes(len);
        for (uint256 idx = 0; idx < len; ++idx) {
            out[idx] = bytes1(uint8(value));
            value = value >> 8;
        }
        return out;
    }

    /**
    * @notice Converting uint256 value to bytes
    * @param value - uint256 value
    */
    function scaleCompactUint(uint256 value) internal returns(bytes memory) {
        if (value < 1<<6) {
            return toLeBytes(value << 2, 1);
        }
        else if(value < 1 << 14) {
            return toLeBytes((value << 2) + 1, 2);
        }
        else if(value < 1 << 30) {
            return toLeBytes((value << 2) + 2, 4);
        }
        else {
            uint256 numBytes = 0;
            {
                uint256 m = value;
                for (; numBytes < 256 && m != 0; ++numBytes) {
                    m = m >> 8;
                }
            }

            bytes memory out = new bytes(numBytes + 1);
            out[0] = bytes1(uint8(((numBytes - 4) << 2) + 3));
            for (uint256 i = 0; i < numBytes; ++i) {
                out[i + 1] = bytes1(uint8(value & 0xFF));
                value = value >> 8;
            }
            return out;
        }
    }
}

File 2 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 3 of 10 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

File 4 of 10 : IRelayEncoder.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author The Moonbeam Team
/// @title The interface through which solidity contracts will interact with Relay Encoder
/// We follow this same interface including four-byte function selectors, in the precompile that
/// wraps the pallet
interface IRelayEncoder {
    // dev Encode 'bond' relay call
    // Selector: 31627376
    // @param controller_address: Address of the controller
    // @param amount: The amount to bond
    // @param reward_destination: the account that should receive the reward
    // @returns The bytes associated with the encoded call
    function encode_bond(uint256 controller_address, uint256 amount, bytes memory reward_destination) external pure returns (bytes memory result);

    // dev Encode 'bond_extra' relay call
    // Selector: 49def326
    // @param amount: The extra amount to bond
    // @returns The bytes associated with the encoded call
    function encode_bond_extra(uint256 amount) external pure returns (bytes memory result);

    // dev Encode 'unbond' relay call
    // Selector: bc4b2187
    // @param amount: The amount to unbond
    // @returns The bytes associated with the encoded call
    function encode_unbond(uint256 amount) external pure returns (bytes memory result);

    // dev Encode 'withdraw_unbonded' relay call
    // Selector: 2d220331
    // @param slashes: Weight hint, number of slashing spans
    // @returns The bytes associated with the encoded call
    function encode_withdraw_unbonded(uint32 slashes) external pure returns (bytes memory result);

    // dev Encode 'validate' relay call
    // Selector: 3a0d803a
    // @param comission: Comission of the validator as parts_per_billion
    // @param blocked: Whether or not the validator is accepting more nominations
    // @returns The bytes associated with the encoded call
    // selector: 3a0d803a
    function encode_validate(uint256 comission, bool blocked) external pure returns (bytes memory result);

    // dev Encode 'nominate' relay call
    // Selector: a7cb124b
    // @param nominees: An array of AccountIds corresponding to the accounts we will nominate
    // @param blocked: Whether or not the validator is accepting more nominations
    // @returns The bytes associated with the encoded call
    function encode_nominate(uint256 [] memory nominees) external pure returns (bytes memory result);

    // dev Encode 'chill' relay call
    // Selector: bc4b2187
    // @returns The bytes associated with the encoded call
    function encode_chill() external pure returns (bytes memory result);

    // dev Encode 'set_payee' relay call
    // Selector: 9801b147
    // @param reward_destination: the account that should receive the reward
    // @returns The bytes associated with the encoded call
    function encode_set_payee(bytes memory reward_destination) external pure returns (bytes memory result);

    // dev Encode 'set_controller' relay call
    // Selector: 7a8f48c2
    // @param controller: The controller address
    // @returns The bytes associated with the encoded call
    function encode_set_controller(uint256 controller) external pure returns (bytes memory result);

    // dev Encode 'rebond' relay call
    // Selector: add6b3bf
    // @param amount: The amount to rebond
    // @returns The bytes associated with the encoded call
    function encode_rebond(uint256 amount) external pure returns (bytes memory result);
}

File 5 of 10 : IxTokens.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title Xtokens Interface
 *
 * The interface through which solidity contracts will interact with xtokens pallet
 *
 */
interface IxTokens {
    // A multilocation is defined by its number of parents and the encoded junctions (interior)
    struct Multilocation {
        uint8 parents;
        bytes [] interior;
    }

    /** Transfer a token through XCM based on its currencyId
     *
     * @dev The token transfer burns/transfers the corresponding amount before sending
     * @param currency_address The ERC20 address of the currency we want to transfer
     * @param amount The amount of tokens we want to transfer
     * @param destination The Multilocation to which we want to send the tokens
     * @param weight The weight we want to buy in the destination chain
     */
    function transfer(address currency_address, uint256 amount, Multilocation memory destination, uint64 weight) external;

    /** Transfer a token through XCM based on its currencyId
     *
     * @dev The token transfer burns/transfers the corresponding amount before sending
     * @param currency_address The ERC20 address of the currency we want to transfer
     * @param amount The amount of tokens we want to transfer
     * @param fee The amount of fees
     * @param destination The Multilocation to which we want to send the tokens
     * @param weight The weight we want to buy in the destination chain
     */
    function transfer_with_fee(address currency_address, uint256 amount, uint256 fee, Multilocation memory destination, uint64 weight) external;

    /** Transfer a token through XCM based on its currencyId
     *
     * @dev The token transfer burns/transfers the corresponding amount before sending
     * @param asset The asset we want to transfer, defined by its multilocation. Currently only Concrete Fungible assets
     * @param amount The amount of tokens we want to transfer
     * @param destination The Multilocation to which we want to send the tokens
     * @param weight The weight we want to buy in the destination chain
     */
    function transfer_multiasset(Multilocation memory asset, uint256 amount, Multilocation memory destination, uint64 weight) external;
}

// Function selector reference
// {
// "b9f813ff": "transfer(address,uint256,(uint8,bytes[]),uint64)",
// "b38c60fa": "transfer_multiasset((uint8,bytes[]),uint256,(uint8,bytes[]),uint64)"
//}

File 6 of 10 : IXcmTransactor.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title Xcm Transactor Interface
 *
 * The interface through which solidity contracts will interact with xcm transactor pallet
 *
 */
interface IXcmTransactor {
    // A multilocation is defined by its number of parents and the encoded junctions (interior)
    struct Multilocation {
        uint8 parents;
        bytes [] interior;
    }

    /** Get index of an account in xcm transactor
     *
     * @param index The index of which we want to retrieve the account
     */
    function index_to_account(uint16 index) external view returns(address);

    /** Get transact info of a multilocation
     * Selector 71b0edfa
     * @param multilocation The location for which we want to retrieve transact info
     */
    function transact_info(Multilocation memory multilocation)
        external view  returns(uint64, uint256, uint64, uint64, uint256);

    /** Transact through XCM using fee based on its multilocation
     *
     * @dev The token transfer burns/transfers the corresponding amount before sending
     * @param transactor The transactor to be used
     * @param index The index to be used
     * @param fee_asset The asset in which we want to pay fees.
     * It has to be a reserve of the destination chain
     * @param weight The weight we want to buy in the destination chain
     * @param inner_call The inner call to be executed in the destination chain
     */
    function transact_through_derivative_multilocation(
        uint8 transactor,
        uint16 index,
        Multilocation memory fee_asset,
        uint64 weight,
        bytes memory inner_call
    ) external;

    /** Transact through XCM using fee based on its currency_id
     *
     * @dev The token transfer burns/transfers the corresponding amount before sending
     * @param transactor The transactor to be used
     * @param index The index to be used
     * @param currency_id Address of the currencyId of the asset to be used for fees
     * It has to be a reserve of the destination chain
     * @param weight The weight we want to buy in the destination chain
     * @param inner_call The inner call to be executed in the destination chain
     */
    function transact_through_derivative(
        uint8 transactor,
        uint16 index,
        address currency_id,
        uint64 weight,
        bytes memory inner_call
    ) external;
}

File 7 of 10 : ILedger.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "Types.sol";

interface ILedger {
    function initialize(
        bytes32 _stashAccount,
        bytes32 controllerAccount,
        address vKSM,
        address controller,
        uint128 minNominatorBalance,
        address lido,
        uint128 _minimumBalance,
        uint256 _maxUnlockingChunks
    ) external;

    function pushData(uint64 eraId, Types.OracleData calldata staking) external;

    function nominate(bytes32[] calldata validators) external;

    function status() external view returns (Types.LedgerStatus);

    function isEmpty() external view returns (bool);

    function stashAccount() external view returns (bytes32);

    function totalBalance() external view returns (uint128);

    function setRelaySpecs(uint128 minNominatorBalance, uint128 minimumBalance, uint256 _maxUnlockingChunks) external;

    function cachedTotalBalance() external view returns (uint128);
}

File 8 of 10 : Types.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Types {
    struct Fee{
        uint16 total;
        uint16 operators;
        uint16 developers;
        uint16 treasury;
    }

    struct Stash {
        bytes32 stashAccount;
        uint64  eraId;
    }

    enum LedgerStatus {
        // bonded but not participate in staking
        Idle,
        // participate as nominator
        Nominator,
        // participate as validator
        Validator,
        // not bonded not participate in staking
        None
    }

    struct UnlockingChunk {
        uint128 balance;
        uint64 era;
    }

    struct OracleData {
        bytes32 stashAccount;
        bytes32 controllerAccount;
        LedgerStatus stakeStatus;
        // active part of stash balance
        uint128 activeBalance;
        // locked for stake stash balance.
        uint128 totalBalance;
        // totalBalance = activeBalance + sum(unlocked.balance)
        UnlockingChunk[] unlocking;
        uint32[] claimedRewards;
        // stash account balance. It includes locked (totalBalance) balance assigned
        // to a controller.
        uint128 stashBalance;
        // slashing spans for ledger
        uint32 slashingSpans;
    }

    struct RelaySpec {
        uint16 maxValidatorsPerLedger;
        uint128 minNominatorBalance;
        uint128 ledgerMinimumActiveBalance;
        uint256 maxUnlockingChunks;
    }
}

File 9 of 10 : IAuthManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IAuthManager {
    function has(bytes32 role, address member) external view returns (bool);

    function add(bytes32 role, address member) external;

    function remove(bytes32 role, address member) external;
}

File 10 of 10 : ILido.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "Types.sol";

interface ILido {
    function MAX_ALLOWABLE_DIFFERENCE() external view returns(uint128);

    function developers() external view returns(address);

    function deposit(uint256 amount) external returns (uint256);
    
    function distributeRewards(uint256 totalRewards, uint256 ledgerBalance) external;

    function distributeLosses(uint256 totalLosses, uint256 ledgerBalance) external;

    function getStashAccounts() external view returns (bytes32[] memory);

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

    function ledgerStake(address ledger) external view returns (uint256);

    function ledgerShares(address ledger) external view returns (uint256);

    function avaliableForStake() external view returns (uint256);

    function transferFromLedger(uint256 amount) external;

    function transferToLedger(uint256 amount) external;

    function flushStakes() external;

    function findLedger(bytes32 stash) external view returns (address);

    function AUTH_MANAGER() external returns(address);

    function ORACLE_MASTER() external view returns (address);

    function getPooledKSMByShares(uint256 sharesAmount) external view returns (uint256);

    function getSharesByPooledKSM(uint256 amount) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

Settings
{
  "evmVersion": "istanbul",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "libraries": {
    "Controller.sol": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"controller","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Bond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BondExtra","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"}],"name":"Chill","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"},{"indexed":false,"internalType":"bytes32[]","name":"validators","type":"bytes32[]"}],"name":"Nominate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Rebond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"from","type":"bytes32"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferToParachain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"bytes32","name":"to","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferToRelaychain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unbond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"index","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"newValue","type":"uint64"}],"name":"WeightUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stash","type":"bytes32"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WEIGHT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REVERSE_TRANSFER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asDerevativeHex","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"controller","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bondExtra","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paraAddress","type":"address"}],"name":"deleteSubAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Controller.WEIGHT","name":"weightType","type":"uint8"}],"name":"getWeight","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hex1","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hex2","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"indexToAccount","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_rootDerivativeIndex","type":"uint16"},{"internalType":"address","name":"_vKSM","type":"address"},{"internalType":"address","name":"_relayEncoder","type":"address"},{"internalType":"address","name":"_xcmTransactor","type":"address"},{"internalType":"address","name":"_xTokens","type":"address"},{"internalType":"bytes","name":"_hex1","type":"bytes"},{"internalType":"bytes","name":"_hex2","type":"bytes"},{"internalType":"bytes","name":"_asDerevativeHex","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"accountId","type":"bytes32"},{"internalType":"address","name":"paraAddress","type":"address"}],"name":"newSubAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"validators","type":"bytes32[]"}],"name":"nominate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unbondingChunks","type":"uint256"}],"name":"rebond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rootDerivativeIndex","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"senderToIndex","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_lido","type":"address"}],"name":"setLido","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_maxWeight","type":"uint64"}],"name":"setMaxWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reverseTransferFee","type":"uint256"}],"name":"setReverseTransferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_transferFee","type":"uint256"}],"name":"setTransferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128[]","name":"_weights","type":"uint128[]"}],"name":"setWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferToParachain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferToRelaychain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unbond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_hex1","type":"bytes"},{"internalType":"bytes","name":"_hex2","type":"bytes"},{"internalType":"bytes","name":"_asDerevativeHex","type":"bytes"}],"name":"updateHexParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"weights","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"slashingSpans","type":"uint32"}],"name":"withdrawUnbonded","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50612e4d806100206000396000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c80638b21f17011610104578063a83427fd116100a2578063c210aefd11610071578063c210aefd14610414578063e4a28a5214610427578063eaca88de1461043a578063f5330e961461044d57600080fd5b8063a83427fd146103b7578063aac271ed146103db578063ac91326d146103ee578063b5f163ff1461040157600080fd5b806392ceb703116100de57806392ceb703146103495780639632acf7146103745780639dad7d1314610387578063a68a740c1461039057600080fd5b80638b21f170146102f85780638f02bb5b1461032357806391b00a301461033657600080fd5b80634a055eb71161017c5780635d4ebc401161014b5780635d4ebc40146102ac578063657a8bba146102bf5780637d774e31146102d25780637f3e3f3b146102e557600080fd5b80634a055eb71461026057806351f9321514610273578063548a6706146102865780635aa411751461029957600080fd5b80632b8a3ae6116101b85780632b8a3ae61461021957806336265192146102215780633fdc4f361461023857806349e5c7ae1461025857600080fd5b8062244eb8146101de5780630b2f9ad5146101fc57806327de9e3214610204575b600080fd5b6101e6610460565b6040516101f39190612442565b60405180910390f35b6101e66104ee565b61021761021236600461245c565b6104fb565b005b610217610645565b61022a600d5481565b6040519081526020016101f3565b61022a610246366004612487565b60096020526000908152604090205481565b6101e6610745565b61021761026e3660046124a2565b610752565b6102176102813660046124cb565b6108a9565b6102176102943660046124ed565b6109b1565b6102176102a736600461255b565b610ab9565b6102176102ba36600461245c565b610c1c565b6102176102cd3660046124cb565b610dff565b6102176102e0366004612617565b610f03565b6102176102f3366004612678565b610f9e565b60045461030b906001600160a01b031681565b6040516001600160a01b0390911681526020016101f3565b61021761033136600461245c565b6112ee565b61021761034436600461245c565b611427565b61035c6103573660046126b9565b611560565b6040516001600160401b0390911681526020016101f3565b6102176103823660046126da565b6115b6565b61022a600c5481565b6000546103a49062010000900461ffff1681565b60405161ffff90911681526020016101f3565b6103a46103c5366004612617565b60086020526000908152604090205461ffff1681565b6102176103e9366004612617565b6116e6565b6102176103fc36600461271a565b6117e6565b61035c61040f36600461245c565b6119ea565b61021761042236600461245c565b611a27565b600a5461035c906001600160401b031681565b61021761044836600461245c565b611c78565b61021761045b366004612678565b611d37565b6007805461046d9061280d565b80601f01602080910402602001604051908101604052809291908181526020018280546104999061280d565b80156104e65780601f106104bb576101008083540402835291602001916104e6565b820191906000526020600020905b8154815290600101906020018083116104c957829003601f168201915b505050505081565b6006805461046d9061280d565b3360009081526008602052604090205461ffff166105345760405162461bcd60e51b815260040161052b90612848565b60405180910390fd5b6105cf61053f611ece565b6105496003611560565b600154604051632cd6121760e01b8152600481018690526001600160a01b0390911690632cd61217906024015b60006040518083038186803b15801561058e57600080fd5b505afa1580156105a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105ca9190810190612895565b611ef3565b7fde937a10138f92e89b0d77ec07df274c490249fe93b77ed997a71754168ffd9d336106183360009081526008602090815260408083205461ffff168352600990915290205490565b604080516001600160a01b039093168352602083019190915281018390526060015b60405180910390a150565b3360009081526008602052604090205461ffff166106755760405162461bcd60e51b815260040161052b90612848565b6106d8610680611ece565b61068a6008611560565b600160009054906101000a90046001600160a01b03166001600160a01b031663bc4b21876040518163ffffffff1660e01b815260040160006040518083038186803b15801561058e57600080fd5b7fba6e8b6a3abbc5a52acdb23c508cb348f0698caf25b067a2bb3b013967b7e27b336107213360009081526008602090815260408083205461ffff168352600990915290205490565b604080516001600160a01b03909316835260208301919091520160405180910390a1565b6005805461046d9061280d565b600080516020612df8833981519152600460009054906101000a90046001600160a01b03166001600160a01b031663a1e206c76040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156107b157600080fd5b505af11580156107c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e99190612941565b604051633bfc46cb60e21b8152600481018390523360248201526001600160a01b03919091169063eff11b2c9060440160206040518083038186803b15801561083157600080fd5b505afa158015610845573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610869919061295e565b6108855760405162461bcd60e51b815260040161052b90612980565b50600a805467ffffffffffffffff19166001600160401b0392909216919091179055565b3360009081526008602052604090205461ffff166108d95760405162461bcd60e51b815260040161052b90612848565b6109336108e4611ece565b6108ee6001611560565b6001805460408051808201825292835260006020840152516318b139bb60e11b81526001600160a01b03909116916331627376916105769189918991906004016129b7565b7fd5dbc8fa383c86d1f241084297dadc2b7c6c247092d1714f8de1c4a9cf866a9d3361097c3360009081526008602090815260408083205461ffff168352600990915290205490565b604080516001600160a01b03909316835260208301919091528101849052606081018390526080015b60405180910390a15050565b3360009081526008602052604090205461ffff166109e15760405162461bcd60e51b815260040161052b90612848565b610a516109ec611ece565b8263ffffffff166109fd6005611560565b610a0791906129f5565b610a116004611560565b610a1b9190612a24565b600154604051632d22033160e01b815263ffffffff861660048201526001600160a01b0390911690632d22033190602401610576565b7fb18c630f7b4f080f2ce1a87d68860e67aef56b0978e448ed92312da4eebeb16033610a9a3360009081526008602090815260408083205461ffff168352600990915290205490565b604080516001600160a01b03909316835260208301919091520161063a565b600080516020612df8833981519152600460009054906101000a90046001600160a01b03166001600160a01b031663a1e206c76040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b1857600080fd5b505af1158015610b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b509190612941565b604051633bfc46cb60e21b8152600481018390523360248201526001600160a01b03919091169063eff11b2c9060440160206040518083038186803b158015610b9857600080fd5b505afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd0919061295e565b610bec5760405162461bcd60e51b815260040161052b90612980565b610bf860058888612351565b50610c0560068686612351565b50610c1260078484612351565b5050505050505050565b3360009081526008602052604090205461ffff16610c4c5760405162461bcd60e51b815260040161052b90612848565b600c54610c78610c5a611ece565b610c64600b611560565b6105ca3386610c73600b611560565b6120a2565b808211610d105760005460405163a9059cbb60e01b8152336004820152602481018490526401000000009091046001600160a01b03169063a9059cbb90604401602060405180830381600087803b158015610cd257600080fd5b505af1158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0a919061295e565b50610d9d565b60005460405163a9059cbb60e01b8152336004820152602481018390526401000000009091046001600160a01b03169063a9059cbb90604401602060405180830381600087803b158015610d6357600080fd5b505af1158015610d77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9b919061295e565b505b7f1f6ca76d5d6a8880c6019f026dbdc28fb59227f3effef64eecc4216b30f5b10a610de53360009081526008602090815260408083205461ffff168352600990915290205490565b6040805191825233602083015281018490526060016109a5565b3360009081526008602052604090205461ffff16610e2f5760405162461bcd60e51b815260040161052b90612848565b610e94610e3a611ece565b82610e456007611560565b610e4f91906129f5565b610e596006611560565b610e639190612a24565b60015460405163add6b3bf60e01b8152600481018790526001600160a01b039091169063add6b3bf90602401610576565b7f83a9fc7121ede847212810044c9749bb4dd5b6febfa9ad3742eb3d40075962d633610edd3360009081526008602090815260408083205461ffff168352600990915290205490565b604080516001600160a01b039093168352602083019190915281018490526060016109a5565b6004546001600160a01b0316158015610f2457506001600160a01b03811615155b610f7c5760405162461bcd60e51b8152602060048201526024808201527f434f4e54524f4c4c45523a204c49444f5f414c52454144595f494e495449414c6044820152631256915160e21b606482015260840161052b565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020612df8833981519152600460009054906101000a90046001600160a01b03166001600160a01b031663a1e206c76040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610ffd57600080fd5b505af1158015611011573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110359190612941565b604051633bfc46cb60e21b8152600481018390523360248201526001600160a01b03919091169063eff11b2c9060440160206040518083038186803b15801561107d57600080fd5b505afa158015611091573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b5919061295e565b6110d15760405162461bcd60e51b815260040161052b90612980565b6110dd600c6001612a65565b821461112b5760405162461bcd60e51b815260206004820152601e60248201527f434f4e54524f4c4c45523a2057524f4e475f574549474854535f53495a450000604482015260640161052b565b60005b828110156112e8576000604085858481811061114c5761114c612a7d565b90506020020160208101906111619190612a93565b6001600160801b0316901c6001600160801b031611156112d857600b548114156111d957600b80546001810182556000919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db96004820401805460039092166008026101000a6001600160401b03021990911690555b8383828181106111eb576111eb612a7d565b90506020020160208101906112009190612a93565b600b828154811061121357611213612a7d565b90600052602060002090600491828204019190066008026101000a8154816001600160401b0302191690836001600160401b031602179055507feaeb3c7640733be05f48249c359ca80c384f5e76d5f39b80ea1c8d1fd86e146881600b838154811061128157611281612a7d565b90600052602060002090600491828204019190066008029054906101000a90046001600160401b03166040516112cf92919060ff9290921682526001600160401b0316602082015260400190565b60405180910390a15b6112e181612abc565b905061112e565b50505050565b600080516020612df8833981519152600460009054906101000a90046001600160a01b03166001600160a01b031663a1e206c76040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561134d57600080fd5b505af1158015611361573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113859190612941565b604051633bfc46cb60e21b8152600481018390523360248201526001600160a01b03919091169063eff11b2c9060440160206040518083038186803b1580156113cd57600080fd5b505afa1580156113e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611405919061295e565b6114215760405162461bcd60e51b815260040161052b90612980565b50600d55565b600080516020612df8833981519152600460009054906101000a90046001600160a01b03166001600160a01b031663a1e206c76040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561148657600080fd5b505af115801561149a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114be9190612941565b604051633bfc46cb60e21b8152600481018390523360248201526001600160a01b03919091169063eff11b2c9060440160206040518083038186803b15801561150657600080fd5b505afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e919061295e565b61155a5760405162461bcd60e51b815260040161052b90612980565b50600c55565b6000600b82600c81111561157657611576612a4f565b8154811061158657611586612a7d565b90600052602060002090600491828204019190066008029054906101000a90046001600160401b03169050919050565b6004546001600160a01b031633146116105760405162461bcd60e51b815260206004820152601b60248201527f434f4e54524f4c4c45523a2043414c4c45525f4e4f545f4c49444f0000000000604482015260640161052b565b6000600981611620866001612ad7565b61ffff1661ffff16815260200190815260200160002054146116845760405162461bcd60e51b815260206004820152601e60248201527f434f4e54524f4c4c45523a20414c52454144595f524547495354455245440000604482015260640161052b565b61168f836001612ad7565b6001600160a01b0382166000908152600860205260408120805461ffff191661ffff939093169290921790915582906009906116cc866001612ad7565b61ffff168152602081019190915260400160002055505050565b6004546001600160a01b031633146117405760405162461bcd60e51b815260206004820152601b60248201527f434f4e54524f4c4c45523a2043414c4c45525f4e4f545f4c49444f0000000000604482015260640161052b565b6001600160a01b03811660009081526008602052604090205461ffff166117a95760405162461bcd60e51b815260206004820152601f60248201527f434f4e54524f4c4c45523a20554e524547495354455245445f4c454447455200604482015260640161052b565b6001600160a01b03166000818152600860208181526040808420805461ffff16855260098352908420849055939092529052805461ffff19169055565b600054610100900460ff16806117ff575060005460ff16155b6118625760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161052b565b600054610100900460ff16158015611884576000805461ffff19166101011790555b60005464010000000090046001600160a01b0316156118e55760405162461bcd60e51b815260206004820152601f60248201527f434f4e54524f4c4c45523a20414c52454144595f494e495449414c495a454400604482015260640161052b565b8b600060026101000a81548161ffff021916908361ffff1602179055508a600060046101000a8154816001600160a01b0302191690836001600160a01b0316021790555089600160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555088600260006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087600360006101000a8154816001600160a01b0302191690836001600160a01b031602179055508686600591906119af929190612351565b506119bc60068686612351565b506119c960078484612351565b5080156119dc576000805461ff00191690555b505050505050505050505050565b600b81815481106119fa57600080fd5b9060005260206000209060049182820401919006600802915054906101000a90046001600160401b031681565b3360009081526008602052604090205461ffff16611a575760405162461bcd60e51b815260040161052b90612848565b6000546040516323b872dd60e01b8152336004820152306024820152604481018390526401000000009091046001600160a01b0316906323b872dd90606401602060405180830381600087803b158015611ab057600080fd5b505af1158015611ac4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae8919061295e565b506040805180820182526060602082015260018082528251818152808401909352909190816020015b6060815260200190600190039081611b11579050506020820152600160f81b611b573360009081526008602090815260408083205461ffff168352600990915290205490565b6040516001600160f81b031990921660208301526021820152600060418201526042016040516020818303038152906040528160200151600081518110611ba057611ba0612a7d565b6020908102919091010152600354600054600d546001600160a01b03928316926394f691159264010000000090041690859085611bdd600c611560565b6040518663ffffffff1660e01b8152600401611bfd959493929190612af4565b600060405180830381600087803b158015611c1757600080fd5b505af1158015611c2b573d6000803e3d6000fd5b505050507fa3b72c7718d9c57429d6b0e8ddc6d5e70a150a59d8794a9d90e1b2e4c79ae5b333610edd3360009081526008602090815260408083205461ffff168352600990915290205490565b3360009081526008602052604090205461ffff16611ca85760405162461bcd60e51b815260040161052b90612848565b611cee611cb3611ece565b611cbd6002611560565b6001546040516324ef799360e11b8152600481018690526001600160a01b03909116906349def32690602401610576565b7f3ce484d3b4411b803fda21e2ce839ca75fc0ecf3039ab59bc40c71c647032536336106183360009081526008602090815260408083205461ffff168352600990915290205490565b3360009081526008602052604090205461ffff16611d675760405162461bcd60e51b815260040161052b90612848565b6000816001600160401b03811115611d8157611d8161287f565b604051908082528060200260200182016040528015611daa578160200160208202803683370190505b50905060005b82811015611e0157838382818110611dca57611dca612a7d565b9050602002013560001c828281518110611de657611de6612a7d565b6020908102919091010152611dfa81612abc565b9050611db0565b50611e66611e0d611ece565b83611e18600a611560565b611e2291906129f5565b611e2c6009611560565b611e369190612a24565b60015460405163a7cb124b60e01b81526001600160a01b039091169063a7cb124b90610576908790600401612ba4565b7f06591922aa31e57deb079e867d22c7a53032ead799b82fcf4ce6470fba36d49033611eaf3360009081526008602090815260408083205461ffff168352600990915290205490565b8585604051611ec19493929190612be8565b60405180910390a1505050565b33600090815260086020526040812054611eee9060019061ffff16612c3d565b905090565b6040805160028082528183019092526000916020820181803683370190505090508360f81b81600081518110611f2b57611f2b612a7d565b60200101906001600160f81b031916908160001a90535060088461ffff16901c60f81b81600181518110611f6157611f61612a7d565b60200101906001600160f81b031916908160001a9053506000611f846000611560565b611f8e9085612a24565b600a549091506001600160401b039081169082161115611ff05760405162461bcd60e51b815260206004820152601b60248201527f434f4e54524f4c4c45523a20544f4f5f4d5543485f5745494748540000000000604482015260640161052b565b600254600080546040516001600160a01b039384169363267d4062939261ffff620100008204169264010000000090910490911690869061203a906007908a908c90602001612cfa565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401612069959493929190612d33565b600060405180830381600087803b15801561208357600080fd5b505af1158015612097573d6000803e3d6000fd5b505050505050505050565b604051606084811b6bffffffffffffffffffffffff191660208301529060059060340160405160208183030381529060405260066120df8661211d565b6120f1866001600160401b031661211d565b604051602001612105959493929190612d79565b60405160208183030381529060405290509392505050565b6060604082101561213d57612137600283901b60016122b9565b92915050565b61400082101561216057612137612159600284901b6001612a65565b60026122b9565b63400000008210156121845761213761217d600284811b90612a65565b60046122b9565b6000825b6101008210801561219857508015155b156121b05760081c6121a982612abc565b9150612188565b5060006121be826001612a65565b6001600160401b038111156121d5576121d561287f565b6040519080825280601f01601f1916602001820160405280156121ff576020820181803683370190505b509050600261220f600484612de0565b61221b911b6003612a65565b60f81b8160008151811061223157612231612a7d565b60200101906001600160f81b031916908160001a90535060005b828110156122ac576001600160f81b031960f886901b168261226e836001612a65565b8151811061227e5761227e612a7d565b60200101906001600160f81b031916908160001a90535060089490941c936122a581612abc565b905061224b565b509392505050565b919050565b60606000826001600160401b038111156122d5576122d561287f565b6040519080825280601f01601f1916602001820160405280156122ff576020820181803683370190505b50905060005b838110156122ac578460f81b82828151811061232357612323612a7d565b60200101906001600160f81b031916908160001a90535060089490941c9361234a81612abc565b9050612305565b82805461235d9061280d565b90600052602060002090601f01602090048101928261237f57600085556123c5565b82601f106123985782800160ff198235161785556123c5565b828001600101855582156123c5579182015b828111156123c55782358255916020019190600101906123aa565b506123d19291506123d5565b5090565b5b808211156123d157600081556001016123d6565b60005b838110156124055781810151838201526020016123ed565b838111156112e85750506000910152565b6000815180845261242e8160208601602086016123ea565b601f01601f19169290920160200192915050565b6020815260006124556020830184612416565b9392505050565b60006020828403121561246e57600080fd5b5035919050565b803561ffff811681146122b457600080fd5b60006020828403121561249957600080fd5b61245582612475565b6000602082840312156124b457600080fd5b81356001600160401b038116811461245557600080fd5b600080604083850312156124de57600080fd5b50508035926020909101359150565b6000602082840312156124ff57600080fd5b813563ffffffff8116811461245557600080fd5b60008083601f84011261252557600080fd5b5081356001600160401b0381111561253c57600080fd5b60208301915083602082850101111561255457600080fd5b9250929050565b6000806000806000806060878903121561257457600080fd5b86356001600160401b038082111561258b57600080fd5b6125978a838b01612513565b909850965060208901359150808211156125b057600080fd5b6125bc8a838b01612513565b909650945060408901359150808211156125d557600080fd5b506125e289828a01612513565b979a9699509497509295939492505050565b6001600160a01b038116811461260957600080fd5b50565b80356122b4816125f4565b60006020828403121561262957600080fd5b8135612455816125f4565b60008083601f84011261264657600080fd5b5081356001600160401b0381111561265d57600080fd5b6020830191508360208260051b850101111561255457600080fd5b6000806020838503121561268b57600080fd5b82356001600160401b038111156126a157600080fd5b6126ad85828601612634565b90969095509350505050565b6000602082840312156126cb57600080fd5b8135600d811061245557600080fd5b6000806000606084860312156126ef57600080fd5b6126f884612475565b925060208401359150604084013561270f816125f4565b809150509250925092565b60008060008060008060008060008060006101008c8e03121561273c57600080fd5b6127458c612475565b9a5061275360208d0161260c565b995061276160408d0161260c565b985061276f60608d0161260c565b975061277d60808d0161260c565b96506001600160401b038060a08e0135111561279857600080fd5b6127a88e60a08f01358f01612513565b909750955060c08d01358110156127be57600080fd5b6127ce8e60c08f01358f01612513565b909550935060e08d01358110156127e457600080fd5b506127f58d60e08e01358e01612513565b81935080925050509295989b509295989b9093969950565b600181811c9082168061282157607f821691505b6020821081141561284257634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252601f908201527f434f4e54524f4c4c45523a20554e524547495354455245445f53454e44455200604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156128a757600080fd5b81516001600160401b03808211156128be57600080fd5b818401915084601f8301126128d257600080fd5b8151818111156128e4576128e461287f565b604051601f8201601f19908116603f0116810190838211818310171561290c5761290c61287f565b8160405282815287602084870101111561292557600080fd5b6129368360208301602088016123ea565b979650505050505050565b60006020828403121561295357600080fd5b8151612455816125f4565b60006020828403121561297057600080fd5b8151801515811461245557600080fd5b60208082526018908201527f434f4e54524f4c4c45523a20554e415554484f524f5a45440000000000000000604082015260600190565b8381528260208201526060604082015260006129d66060830184612416565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b0380831681851681830481118215151615612a1b57612a1b6129df565b02949350505050565b60006001600160401b03808316818516808303821115612a4657612a466129df565b01949350505050565b634e487b7160e01b600052602160045260246000fd5b60008219821115612a7857612a786129df565b500190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612aa557600080fd5b81356001600160801b038116811461245557600080fd5b6000600019821415612ad057612ad06129df565b5060010190565b600061ffff808316818516808303821115612a4657612a466129df565b60018060a01b038616815260006020868184015285604084015260a0606084015260e0830160ff86511660a085015281860151604060c086015281815180845261010093508387019150838160051b8801019350848301925060005b81811015612b7e5760ff19888603018352612b6c858551612416565b94509285019291850191600101612b50565b5050506001600160401b0386166080860152509150612b9a9050565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612bdc57835183529284019291840191600101612bc0565b50909695505050505050565b6001600160a01b038516815260208101849052606060408201819052810182905260006001600160fb1b03831115612c1f57600080fd5b8260051b808560808501376000920160800191825250949350505050565b600061ffff83811690831681811015612c5857612c586129df565b039392505050565b8054600090600181811c9080831680612c7a57607f831692505b6020808410821415612c9c57634e487b7160e01b600052602260045260246000fd5b818015612cb05760018114612cc157612cee565b60ff19861689528489019650612cee565b60008881526020902060005b86811015612ce65781548b820152908501908301612ccd565b505084890196505b50505050505092915050565b6000612d068286612c60565b8451612d168183602089016123ea565b8451910190612d298183602088016123ea565b0195945050505050565b60ff8616815261ffff851660208201526001600160a01b03841660408201526001600160401b038316606082015260a06080820181905260009061293690830184612416565b6000612d858288612c60565b8651612d95818360208b016123ea565b612da181830188612c60565b9150508451612db48183602089016123ea565b600160d81b91019081528351612dd18160058401602088016123ea565b01600501979650505050505050565b600082821015612df257612df26129df565b50039056fec782482f4fcb342b5dc312c5a088cff7e4984bcf7803f44f6541f05e6fd4ce48a2646970667358221220af6230985ba98f4bccf516d442dcd358d9b9c7b90e9a92bca9dee39755b80f5764736f6c63430008090033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.