Contract 0x8d24EF5B84d99b1871Eef84b4999b97B96eCfba7

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x7a4383f8a50581278a7f47e41c6dde3a4f546399721df667b9f6a0e065aabf520x6080604016859812022-04-08 13:43:12300 days 3 hrs agoLido: Deployer IN  Create: Withdrawal0 MOVR0.00142737
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
Withdrawal

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 6 : Withdrawal.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;

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

import "WithdrawalQueue.sol";
import "ILido.sol";

contract Withdrawal is Initializable {
    using WithdrawalQueue for WithdrawalQueue.Queue;

    // Element removed from queue
    event ElementRemoved(uint256 elementId);

    // Element added to queue
    event ElementAdded(uint256 elementId);

    // New redeem request added
    event RedeemRequestAdded(address indexed user, uint256 shares, uint256 batchId);

    // xcKSM claimed by user
    event Claimed(address indexed user, uint256 claimedAmount);

    // Losses ditributed to contract
    event LossesDistributed(uint256 losses);

    // stKSM smart contract
    ILido public stKSM;

    // xcKSM precompile
    IERC20 public xcKSM;

    // withdrawal queue
    WithdrawalQueue.Queue public queue;

    // batch id => price for pool shares to xcKSM 
    // to retrive xcKSM amount for user: user_pool_shares * batchSharePrice[batch_id]
    mapping(uint256 => uint256) public batchSharePrice;

    struct Request {
        uint256 share;
        uint256 batchId;
    }

    // user's withdrawal requests (unclaimed)
    mapping(address => Request[]) public userRequests;

    // total virtual xcKSM amount on contract
    uint256 public totalVirtualXcKSMAmount;

    // total amount of xcKSM pool shares
    uint256 public totalXcKSMPoolShares;

    // stKSM(xcKSM) virtual amount for batch
    uint256 public batchVirtualXcKSMAmount;

    // Last Id of queue element which can be claimed
    uint256 public claimableId;

    // Balance for claiming
    uint256 public pendingForClaiming;

    // max amount of requests in parallel
    uint16 internal constant MAX_REQUESTS = 20;


    modifier onlyLido() {
        require(msg.sender == address(stKSM), "WITHDRAWAL: CALLER_NOT_LIDO");
        _;
    }

    /**
    * @notice Initialize redeemPool contract.
    * @param _cap - cap for queue
    * @param _xcKSM - xcKSM precompile address
    */
    function initialize(
        uint256 _cap,
        address _xcKSM
    ) external initializer {
        require(_cap > 0, "WITHDRAWAL: INCORRECT_CAP");
        require(_xcKSM != address(0), "WITHDRAWAL: INCORRECT_XCKSM_ADDRESS");
        queue.init(_cap);
        xcKSM = IERC20(_xcKSM);
    }

    /**
    * @notice Set stKSM contract address, allowed to only once
    * @param _stKSM stKSM contract address
    */
    function setStKSM(address _stKSM) external {
        require(address(stKSM) == address(0), "WITHDRAWAL: STKSM_ALREADY_DEFINED");
        require(_stKSM != address(0), "WITHDRAWAL: INCORRECT_STKSM_ADDRESS");

        stKSM = ILido(_stKSM);
    }

    /**
    * @notice Burn pool shares from first element of queue and move index for allow claiming. After that add new batch
    */
    function newEra() external onlyLido {
        uint256 newXcKSMAmount = xcKSM.balanceOf(address(this)) - pendingForClaiming;

        if ((newXcKSMAmount > 0) && (queue.size > 0)) {
            (WithdrawalQueue.Batch memory topBatch, uint256 topId) = queue.top();
            // batchSharePrice = pool_xcKSM_balance / pool_shares
            // when user try to claim: user_KSM = user_pool_share * batchSharePrice
            uint256 sharePriceForBatch = getBatchSharePrice(topBatch);
            uint256 xcKSMForBatch = topBatch.batchTotalShares * sharePriceForBatch / 10**12;
            if (newXcKSMAmount >= xcKSMForBatch) {
                batchSharePrice[topId] = sharePriceForBatch;

                totalXcKSMPoolShares -= topBatch.batchXcKSMShares;
                totalVirtualXcKSMAmount -= xcKSMForBatch;
                // NOTE: In case when losses occur due to rounding it is possible to 
                // totalVirtualXcKSMAmount > 0 and totalXcKSMPoolShares = 0
                if (totalXcKSMPoolShares == 0) {
                    totalVirtualXcKSMAmount = 0;
                }

                claimableId = topId;
                pendingForClaiming += xcKSMForBatch;

                queue.pop();

                emit ElementRemoved(topId);
            }
        }

        if ((batchVirtualXcKSMAmount > 0) && (queue.size < queue.cap)) {
            uint256 batchKSMPoolShares = getKSMPoolShares(batchVirtualXcKSMAmount);

            // NOTE: batch total shares = batch xcKSM amount, because 1 share = 1 xcKSM
            WithdrawalQueue.Batch memory newBatch = WithdrawalQueue.Batch(batchVirtualXcKSMAmount, batchKSMPoolShares);
            uint256 newId = queue.push(newBatch);

            totalVirtualXcKSMAmount += batchVirtualXcKSMAmount;
            totalXcKSMPoolShares += batchKSMPoolShares;

            batchVirtualXcKSMAmount = 0;

            emit ElementAdded(newId);
        }
    }

    /**
    * @notice Returns total virtual xcKSM balance of contract for which losses can be applied
    */
    function totalBalanceForLosses() external view returns (uint256) {
        return totalVirtualXcKSMAmount + batchVirtualXcKSMAmount;
    }

    /**
    * @notice function returns xcKSM amount that should be available for claiming after batch remove
    * @param _batchShift batch shift from first element
    */
    function getxcKSMBalanceForBatch(uint256 _batchShift) external view returns (uint256) {
        (WithdrawalQueue.Batch memory specificBatch, ) = queue.element(_batchShift);
        // batchSharePrice = pool_xcKSM_balance / pool_shares
        // when user try to claim: user_KSM = user_pool_share * batchSharePrice
        uint256 sharePriceForBatch = getBatchSharePrice(specificBatch);
        uint256 xcKSMForBatch = specificBatch.batchTotalShares * sharePriceForBatch / 10**12;
        return xcKSMForBatch;
    }

    /**
    * @notice function returns specific batch from queue
    * @param _batchShift batch shift from first element
    */
    function getQueueBatch(uint256 _batchShift) external view returns (WithdrawalQueue.Batch memory) {
        (WithdrawalQueue.Batch memory specificBatch, ) = queue.element(_batchShift);
        return specificBatch;
    }

    /**
    * @notice 1. Mint equal amount of pool shares for user 
    * @notice 2. Adjust current amount of virtual xcKSM on Withdrawal contract
    * @notice 3. Burn shares on LIDO side
    * @param _from user address for minting
    * @param _amount amount of stKSM which user wants to redeem
    */
    function redeem(address _from, uint256 _amount) external onlyLido {
        // NOTE: user share in batch = user stKSM balance in specific batch
        require(userRequests[_from].length < MAX_REQUESTS, "WITHDRAWAL: REQUEST_CAP_EXCEEDED");
        batchVirtualXcKSMAmount += _amount;

        Request memory req = Request(_amount, queue.nextId());
        userRequests[_from].push(req);

        emit RedeemRequestAdded(_from, req.share, req.batchId);
    }

    /**
    * @notice Returns available for claiming xcKSM amount for user
    * @param _holder user address for claiming
    */
    function claim(address _holder) external onlyLido returns (uint256) {
        // go through claims and check if unlocked than just transfer xcKSMs
        uint256 readyToClaim = 0;
        uint256 readyToClaimCount = 0;
        Request[] storage requests = userRequests[_holder];

        for (uint256 i = 0; i < requests.length; ++i) {
            if (requests[i].batchId <= claimableId) {
                readyToClaim += requests[i].share * batchSharePrice[requests[i].batchId] / 10**12;
                readyToClaimCount += 1;
            }
            else {
                requests[i - readyToClaimCount] = requests[i];
            }
        }

        // remove claimed items
        for (uint256 i = 0; i < readyToClaimCount; ++i) { requests.pop(); }

        require(readyToClaim <= xcKSM.balanceOf(address(this)), "WITHDRAWAL: CLAIM_EXCEEDS_BALANCE");
        xcKSM.transfer(_holder, readyToClaim);
        pendingForClaiming -= readyToClaim;

        emit Claimed(_holder, readyToClaim);

        return readyToClaim;
    }

    /**
    * @notice Apply losses to current stKSM shares on this contract
    * @param _losses user address for claiming
    */
    function ditributeLosses(uint256 _losses) external onlyLido {
        totalVirtualXcKSMAmount -= _losses;
        emit LossesDistributed(_losses);
    }

    /**
    * @notice Check available for claim xcKSM balance for user
    * @param _holder user address
    */
    function getRedeemStatus(address _holder) external view returns(uint256 _waiting, uint256 _available) {
        Request[] storage requests = userRequests[_holder];

        for (uint256 i = 0; i < requests.length; ++i) {
            if (requests[i].batchId <= claimableId) {
                _available += requests[i].share * batchSharePrice[requests[i].batchId] / 10**12;
            }
            else {
                _waiting += requests[i].share * getBatchSharePrice(queue.findBatch(requests[i].batchId)) / 10**12;
            }
        }
        return (_waiting, _available);
    }

    /**
    * @notice Calculate share price to KSM for specific batch
    * @param _batch batch
    */
    function getBatchSharePrice(WithdrawalQueue.Batch memory _batch) internal view returns (uint256) {
        uint256 batchKSMPrice;
        if (totalXcKSMPoolShares > 0) {
            // user_xcKSM = user_batch_share * batch_share_price
            // batch_share_price = (1 / batch_total_shares) * batch_pool_shares * (total_xcKSM / total_pool_shares)
            if (_batch.batchTotalShares > 0) {
                batchKSMPrice = (10**12 * _batch.batchXcKSMShares * totalVirtualXcKSMAmount) / 
                                (_batch.batchTotalShares * totalXcKSMPoolShares);
            }
            else {
                // NOTE: This means that batch not added to queue currently
                if (batchVirtualXcKSMAmount > 0) {
                    batchKSMPrice = (10**12 * getKSMPoolShares(batchVirtualXcKSMAmount) * totalVirtualXcKSMAmount) / 
                                    (batchVirtualXcKSMAmount * totalXcKSMPoolShares);
                }
            }
        }
        else {
            // NOTE: This means that we have only one batch that no in the pool (batch share price == 10**12)
            if (batchVirtualXcKSMAmount > 0) {
                batchKSMPrice = 10**12;
            }
        }
        return batchKSMPrice;
    }

    /**
    * @notice Calculate shares amount in KSM pool for specific xcKSM amount
    * @param _amount amount of xcKSM tokens
    */
    function getKSMPoolShares(uint256 _amount) internal view returns (uint256) {
        if (totalVirtualXcKSMAmount > 0) {
            return _amount * totalXcKSMPoolShares / totalVirtualXcKSMAmount;
        }
        return _amount;
    }
}

File 2 of 6 : 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 3 of 6 : 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 4 of 6 : WithdrawalQueue.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;

library WithdrawalQueue {
    struct Batch {
        uint256 batchTotalShares; // Total shares amount for batch
        uint256 batchXcKSMShares; // Batch xcKSM shares in xcKSM pool
    }

    struct Queue {
        Batch[] items;
        uint256[] ids;

        uint256 first;
        uint256 size;
        uint256 cap;
        uint256 id;
    }

    /**
    * @notice Queue initialization
    * @param queue queue for initializing
    * @param cap max amount of elements in the queue
    */
    function init(Queue storage queue, uint256 cap) internal {
        for (uint256 i = 0; i < cap; ++i) {
            queue.items.push(Batch(0, 0));
        }
        queue.ids = new uint256[](cap);
        queue.first = 0;
        queue.size = 0;
        queue.size = 0;
        queue.cap = cap;
    }

    /**
    * @notice Add element to the end of queue
    * @param queue current queue
    * @param elem element for adding
    */
    function push(Queue storage queue, Batch memory elem) internal returns (uint256 _id) {
        require(queue.size < queue.cap, "WithdrawalQueue: capacity exceeded");
        uint256 lastIndex = (queue.first + queue.size) % queue.cap;
        queue.items[lastIndex] = elem;
        queue.id++;
        queue.ids[lastIndex] = queue.id;
        queue.size++;
        return queue.id;
    }

    /**
    * @notice Remove element from top of the queue
    * @param queue current queue
    */
    function pop(Queue storage queue) internal returns (Batch memory _item, uint256 _id) {
        require(queue.size > 0, "WithdrawalQueue: queue is empty");
        _item = queue.items[queue.first];
        _id = queue.ids[queue.first];
        queue.first = (queue.first + 1) % queue.cap;
        queue.size--;
    }

    /**
    * @notice Return batch for specific index
    * @param queue current queue
    * @param index index of batch
    */
    function findBatch(Queue storage queue, uint256 index) internal view returns (Batch memory _item) {
        uint256 startIndex = queue.ids[queue.first];
        if (index >= startIndex) {
            if ((index - startIndex) < queue.size) {
                return queue.items[(queue.first + (index - startIndex)) % queue.cap];
            }
        }
        return Batch(0, 0);
    }

    /**
    * @notice Return first element of the queue
    * @param queue current queue
    */
    function top(Queue storage queue) internal view returns (Batch memory _item, uint256 _id) {
        require(queue.size > 0, "WithdrawalQueue: queue is empty");
        _item = queue.items[queue.first];
        _id = queue.ids[queue.first];
    }

    /**
    * @notice Return specific element of the queue
    * @param queue current queue
    * @param shift element shift from top id
    */
    function element(Queue storage queue, uint256 shift) internal view returns (Batch memory _item, uint256 _id) {
        require(queue.size > 0, "WithdrawalQueue: queue is empty");
        require(shift < queue.size, "WithdrawalQueue: index outside queue");
        uint256 index = (queue.first + shift) % queue.cap;
        _item = queue.items[index];
        _id = queue.ids[index];
    }

    /**
    * @notice Return last element of the queue
    * @param queue current queue
    */
    function last(Queue storage queue) internal view returns (Batch memory _item, uint256 _id) {
        require(queue.size > 0, "WithdrawalQueue: queue is empty");
        uint256 lastIndex = (queue.first + queue.size - 1) % queue.cap;
        _item = queue.items[lastIndex];
        _id = queue.ids[lastIndex];
    }

    /**
    * @notice Return last element id + 1
    * @param queue current queue
    */
    function nextId(Queue storage queue) internal view returns (uint256 _id) {
        _id = queue.id + 1;
    }
}

File 5 of 6 : 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 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 transferFromLedger(uint256 amount, uint256 excess) external;

    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);
}

File 6 of 6 : 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;
    }
}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"elementId","type":"uint256"}],"name":"ElementAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"elementId","type":"uint256"}],"name":"ElementRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"losses","type":"uint256"}],"name":"LossesDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"batchId","type":"uint256"}],"name":"RedeemRequestAdded","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"batchSharePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchVirtualXcKSMAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimableId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_losses","type":"uint256"}],"name":"ditributeLosses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_batchShift","type":"uint256"}],"name":"getQueueBatch","outputs":[{"components":[{"internalType":"uint256","name":"batchTotalShares","type":"uint256"},{"internalType":"uint256","name":"batchXcKSMShares","type":"uint256"}],"internalType":"struct WithdrawalQueue.Batch","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"}],"name":"getRedeemStatus","outputs":[{"internalType":"uint256","name":"_waiting","type":"uint256"},{"internalType":"uint256","name":"_available","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_batchShift","type":"uint256"}],"name":"getxcKSMBalanceForBatch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cap","type":"uint256"},{"internalType":"address","name":"_xcKSM","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"newEra","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingForClaiming","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"queue","outputs":[{"internalType":"uint256","name":"first","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stKSM","type":"address"}],"name":"setStKSM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stKSM","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBalanceForLosses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVirtualXcKSMAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalXcKSMPoolShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userRequests","outputs":[{"internalType":"uint256","name":"share","type":"uint256"},{"internalType":"uint256","name":"batchId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xcKSM","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506118df806100206000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806362cf1182116100ad578063b946b71211610071578063b946b7121461026f578063da35a26f1461029d578063e10d29ee146102b0578063e111e44a146102e6578063e45aeda1146102ef57600080fd5b806362cf1182146102185780637b2077271461022b5780639756438914610233578063a0965af41461023c578063aff799101461025c57600080fd5b8063263cb6b6116100f4578063263cb6b6146101b857806339085301146101e05780633dbfe6cb146101e95780634f5b636c146101f25780635068231f1461020557600080fd5b8063036ec066146101315780630e910c171461014c57806315cda1701461017d5780631e83409a146101925780631e9a6950146101a5575b600080fd5b6101396102f8565b6040519081526020015b60405180910390f35b600054610165906201000090046001600160a01b031681565b6040516001600160a01b039091168152602001610143565b61019061018b36600461165b565b61030f565b005b6101396101a036600461165b565b610409565b6101906101b336600461167d565b610772565b6101cb6101c636600461167d565b6108c7565b60408051928352602083019190915201610143565b610139600c5481565b610139600e5481565b6101906102003660046116a7565b610903565b6101396102133660046116a7565b610980565b600154610165906001600160a01b031681565b6101906109c9565b610139600b5481565b61013961024a3660046116a7565b60086020526000908152604090205481565b6101cb61026a36600461165b565b610c50565b61028261027d3660046116a7565b610dc8565b60408051825181526020928301519281019290925201610143565b6101906102ab3660046116c0565b610df1565b6004546005546006546007546102c69392919084565b604080519485526020850193909352918301526060820152608001610143565b610139600d5481565b610139600a5481565b6000600c54600a5461030a9190611702565b905090565b6000546201000090046001600160a01b03161561037d5760405162461bcd60e51b815260206004820152602160248201527f5749544844524157414c3a2053544b534d5f414c52454144595f444546494e456044820152601160fa1b60648201526084015b60405180910390fd5b6001600160a01b0381166103df5760405162461bcd60e51b815260206004820152602360248201527f5749544844524157414c3a20494e434f52524543545f53544b534d5f4144445260448201526245535360e81b6064820152608401610374565b600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b600080546201000090046001600160a01b0316331461043a5760405162461bcd60e51b81526004016103749061171a565b6001600160a01b03821660009081526009602052604081208190815b815481101561058a57600d5482828154811061047457610474611751565b9060005260206000209060020201600101541161051e5764e8d4a51000600860008484815481106104a7576104a7611751565b9060005260206000209060020201600101548152602001908152602001600020548383815481106104da576104da611751565b9060005260206000209060020201600001546104f69190611767565b610500919061179c565b61050a9085611702565b9350610517600184611702565b925061057a565b81818154811061053057610530611751565b906000526020600020906002020182848361054b91906117b0565b8154811061055b5761055b611751565b6000918252602090912082546002909202019081556001918201549101555b610583816117c7565b9050610456565b5060005b828110156105d457818054806105a6576105a66117e0565b6000828152602081206002600019909301928302018181556001015590556105cd816117c7565b905061058e565b506001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561061d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064191906117f6565b83111561069a5760405162461bcd60e51b815260206004820152602160248201527f5749544844524157414c3a20434c41494d5f455843454544535f42414c414e436044820152604560f81b6064820152608401610374565b60015460405163a9059cbb60e01b81526001600160a01b038781166004830152602482018690529091169063a9059cbb906044016020604051808303816000875af11580156106ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610711919061180f565b5082600e600082825461072491906117b0565b90915550506040518381526001600160a01b038616907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a250909150505b919050565b6000546201000090046001600160a01b031633146107a25760405162461bcd60e51b81526004016103749061171a565b6001600160a01b03821660009081526009602052604090205460141161080a5760405162461bcd60e51b815260206004820181905260248201527f5749544844524157414c3a20524551554553545f4341505f45584345454445446044820152606401610374565b80600c600082825461081c9190611702565b92505081905550600060405180604001604052808381526020016108406002610f7e565b90526001600160a01b03841660008181526009602090815260408083208054600181810183559185529383902086516002909502018481559286015192018290555193945091927f4d78899c3f146fbd6f7785cdffdcd04c3ebec37360e3013cb521324632eb2d86926108ba928252602082015260400190565b60405180910390a2505050565b600960205281600052604060002081815481106108e357600080fd5b600091825260209091206002909102018054600190910154909250905082565b6000546201000090046001600160a01b031633146109335760405162461bcd60e51b81526004016103749061171a565b80600a600082825461094591906117b0565b90915550506040518181527f18d7ff5061dc5fa3e9d0e114f717c584c7c71cfdbf7afdecd92cefc75daaa8609060200160405180910390a150565b60008061098e600284610f97565b509050600061099c826110c0565b9050600064e8d4a510008284600001516109b69190611767565b6109c0919061179c565b95945050505050565b6000546201000090046001600160a01b031633146109f95760405162461bcd60e51b81526004016103749061171a565b600e546001546040516370a0823160e01b8152306004820152600092916001600160a01b0316906370a0823190602401602060405180830381865afa158015610a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6a91906117f6565b610a7491906117b0565b9050600081118015610a87575060055415155b15610b9057600080610a996002611165565b915091506000610aa8836110c0565b9050600064e8d4a51000828560000151610ac29190611767565b610acc919061179c565b9050808510610b8b5760008381526008602090815260408220849055850151600b805491929091610afe9084906117b0565b9250508190555080600a6000828254610b1791906117b0565b9091555050600b54600003610b2c576000600a555b82600d8190555080600e6000828254610b459190611702565b90915550610b5590506002611211565b50506040518381527fcec9cdff740b6d842df3489c0dcafe7e1592acfcdae1e8e5daed0378935144aa9060200160405180910390a15b505050505b6000600c54118015610ba55750600654600554105b15610c4d576000610bb7600c546112f9565b60408051808201909152600c548152602081018290529091506000610bdd600283611322565b9050600c54600a6000828254610bf39190611702565b9250508190555082600b6000828254610c0c9190611702565b90915550506000600c556040518181527f36441530b7e50b8d3b0d7edad61c8773152306fe8d81d836f663711cc6c36df29060200160405180910390a15050505b50565b6001600160a01b03811660009081526009602052604081208190815b8154811015610dc157600d54828281548110610c8a57610c8a611751565b90600052602060002090600202016001015411610d275764e8d4a5100060086000848481548110610cbd57610cbd611751565b906000526020600020906002020160010154815260200190815260200160002054838381548110610cf057610cf0611751565b906000526020600020906002020160000154610d0c9190611767565b610d16919061179c565b610d209084611702565b9250610db1565b64e8d4a51000610d6c610d67848481548110610d4557610d45611751565b906000526020600020906002020160010154600261144590919063ffffffff16565b6110c0565b838381548110610d7e57610d7e611751565b906000526020600020906002020160000154610d9a9190611767565b610da4919061179c565b610dae9085611702565b93505b610dba816117c7565b9050610c6c565b5050915091565b60408051808201909152600080825260208201526000610de9600284610f97565b509392505050565b600054610100900460ff1680610e0a575060005460ff16155b610e6d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610374565b600054610100900460ff16158015610e8f576000805461ffff19166101011790555b60008311610edf5760405162461bcd60e51b815260206004820152601960248201527f5749544844524157414c3a20494e434f52524543545f434150000000000000006044820152606401610374565b6001600160a01b038216610f415760405162461bcd60e51b815260206004820152602360248201527f5749544844524157414c3a20494e434f52524543545f58434b534d5f4144445260448201526245535360e81b6064820152608401610374565b610f4c600284611528565b600180546001600160a01b0319166001600160a01b0384161790558015610f79576000805461ff00191690555b505050565b600081600501546001610f919190611702565b92915050565b6040805180820190915260008082526020820152600080846003015411610fd05760405162461bcd60e51b815260040161037490611831565b8360030154831061102f5760405162461bcd60e51b8152602060048201526024808201527f5769746864726177616c51756575653a20696e646578206f75747369646520716044820152637565756560e01b6064820152608401610374565b600084600401548486600201546110469190611702565b6110509190611868565b905084600001818154811061106757611067611751565b90600052602060002090600202016040518060400160405290816000820154815260200160018201548152505092508460010181815481106110ab576110ab611751565b90600052602060002001549150509250929050565b6000806000600b5411156111505782511561111657600b5483516110e49190611767565b600a5460208501516110fb9064e8d4a51000611767565b6111059190611767565b61110f919061179c565b9050610f91565b600c541561114b57600b54600c5461112e9190611767565b600a5461113c600c546112f9565b6110fb9064e8d4a51000611767565b610f91565b600c5415610f91575064e8d4a5100092915050565b604080518082019091526000808252602082015260008083600301541161119e5760405162461bcd60e51b815260040161037490611831565b826000018360020154815481106111b7576111b7611751565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250509150826001018360020154815481106111ff576111ff611751565b90600052602060002001549050915091565b604080518082019091526000808252602082015260008083600301541161124a5760405162461bcd60e51b815260040161037490611831565b8260000183600201548154811061126357611263611751565b9060005260206000209060020201604051806040016040529081600082015481526020016001820154815250509150826001018360020154815481106112ab576112ab611751565b906000526020600020015490508260040154836002015460016112ce9190611702565b6112d89190611868565b60028401556003830180549060006112ef8361187c565b9190505550915091565b600a546000901561131e57600a54600b546113149084611767565b610f91919061179c565b5090565b600082600401548360030154106113865760405162461bcd60e51b815260206004820152602260248201527f5769746864726177616c51756575653a20636170616369747920657863656564604482015261195960f21b6064820152608401610374565b60008360040154846003015485600201546113a19190611702565b6113ab9190611868565b9050828460000182815481106113c3576113c3611751565b6000918252602080832084516002909302019182559290920151600190920191909155600585018054916113f6836117c7565b9190505550836005015484600101828154811061141557611415611751565b600091825260208220019190915560038501805491611433836117c7565b90915550505060059092015492915050565b604080518082019091526000808252602082015260008360010184600201548154811061147457611474611751565b9060005260206000200154905080831061150c57600384015461149782856117b0565b101561150c57600484015484906114ae83866117b0565b86600201546114bd9190611702565b6114c79190611868565b815481106114d7576114d7611751565b906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050915050610f91565b5050604080518082019091526000808252602082015292915050565b60005b8181101561157c57604080518082019091526000808252602080830182815286546001818101895588855292909320935160029093029093019182559151910155611575816117c7565b905061152b565b508067ffffffffffffffff81111561159657611596611893565b6040519080825280602002602001820160405280156115bf578160200160208202803683370190505b5080516115d69160018501916020909101906115ed565b506000600283018190556003830155600490910155565b828054828255906000526020600020908101928215611628579160200282015b8281111561162857825182559160200191906001019061160d565b5061131e9291505b8082111561131e5760008155600101611630565b80356001600160a01b038116811461076d57600080fd5b60006020828403121561166d57600080fd5b61167682611644565b9392505050565b6000806040838503121561169057600080fd5b61169983611644565b946020939093013593505050565b6000602082840312156116b957600080fd5b5035919050565b600080604083850312156116d357600080fd5b823591506116e360208401611644565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b60008219821115611715576117156116ec565b500190565b6020808252601b908201527f5749544844524157414c3a2043414c4c45525f4e4f545f4c49444f0000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615611781576117816116ec565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826117ab576117ab611786565b500490565b6000828210156117c2576117c26116ec565b500390565b6000600182016117d9576117d96116ec565b5060010190565b634e487b7160e01b600052603160045260246000fd5b60006020828403121561180857600080fd5b5051919050565b60006020828403121561182157600080fd5b8151801515811461167657600080fd5b6020808252601f908201527f5769746864726177616c51756575653a20717565756520697320656d70747900604082015260600190565b60008261187757611877611786565b500690565b60008161188b5761188b6116ec565b506000190190565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220c4ebfe9b98d076781be2334876eb28616f11930cff879e2b0d20eb25113397b064736f6c634300080d0033

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.