ETH Price: $2,903.62 (+2.90%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw184319242023-10-26 4:10:47379 days ago1698293447IN
0x1Eb06EaE...811B59E63
0 ETH0.0028752325.05190504
Withdraw158373462022-10-27 5:33:35743 days ago1666848815IN
0x1Eb06EaE...811B59E63
0 ETH0.000908239.27465751
Withdraw158044862022-10-22 15:17:11747 days ago1666451831IN
0x1Eb06EaE...811B59E63
0 ETH0.0028701725
Withdraw157668432022-10-17 9:09:23752 days ago1665997763IN
0x1Eb06EaE...811B59E63
0 ETH0.0013514211.77127972
Withdraw153325182022-08-13 9:08:28817 days ago1660381708IN
0x1Eb06EaE...811B59E63
0 ETH0.000918458
Withdraw151070272022-07-09 7:25:40853 days ago1657351540IN
0x1Eb06EaE...811B59E63
0 ETH0.000918458
Withdraw150429312022-06-29 3:06:31863 days ago1656471991IN
0x1Eb06EaE...811B59E63
0 ETH0.0048218942
Withdraw150364692022-06-27 21:53:28864 days ago1656366808IN
0x1Eb06EaE...811B59E63
0 ETH0.0073458563.98439956
Withdraw149464102022-06-11 21:04:19880 days ago1654981459IN
0x1Eb06EaE...811B59E63
0 ETH0.0012871722
Withdraw149464102022-06-11 21:04:19880 days ago1654981459IN
0x1Eb06EaE...811B59E63
0 ETH0.0021543722
Withdraw149462352022-06-11 20:25:37880 days ago1654979137IN
0x1Eb06EaE...811B59E63
0 ETH0.0016377916.72478101
Withdraw149462232022-06-11 20:23:03880 days ago1654978983IN
0x1Eb06EaE...811B59E63
0 ETH0.0018572318.9657476
Withdraw148657212022-05-29 9:31:44893 days ago1653816704IN
0x1Eb06EaE...811B59E63
0 ETH0.001033269
Withdraw147605112022-05-12 10:18:07910 days ago1652350687IN
0x1Eb06EaE...811B59E63
0 ETH0.01587311162.06147851
Withdraw147509992022-05-10 21:46:58912 days ago1652219218IN
0x1Eb06EaE...811B59E63
0 ETH0.006544856.99511055
Withdraw147424562022-05-09 12:35:45913 days ago1652099745IN
0x1Eb06EaE...811B59E63
0 ETH0.0040549235.31212542
Withdraw147280432022-05-07 5:52:29916 days ago1651902749IN
0x1Eb06EaE...811B59E63
0 ETH0.0028701725
Withdraw146444062022-04-24 0:54:30929 days ago1650761670IN
0x1Eb06EaE...811B59E63
0 ETH0.0019517117
Withdraw146133532022-04-19 4:04:41934 days ago1650341081IN
0x1Eb06EaE...811B59E63
0 ETH0.0021308721.76000549
Withdraw145959662022-04-16 11:06:13936 days ago1650107173IN
0x1Eb06EaE...811B59E63
0 ETH0.001722115
Withdraw145632172022-04-11 8:02:20942 days ago1649664140IN
0x1Eb06EaE...811B59E63
0 ETH0.001722115
Withdraw145631642022-04-11 7:52:25942 days ago1649663545IN
0x1Eb06EaE...811B59E63
0 ETH0.0019517117
Withdraw145537632022-04-09 20:43:21943 days ago1649537001IN
0x1Eb06EaE...811B59E63
0 ETH0.0034438530
Withdraw145527422022-04-09 16:59:49943 days ago1649523589IN
0x1Eb06EaE...811B59E63
0 ETH0.003802433.12001759
Withdraw145107682022-04-03 3:22:49950 days ago1648956169IN
0x1Eb06EaE...811B59E63
0 ETH0.0042975437.42492243
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x9ce30183...d2EB8561A
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Vyper_contract

Compiler Version
vyper:0.2.12

Optimization Enabled:
N/A

Other Settings:
GNU AGPLv3 license

Contract Source Code (Vyper language format)

# @version 0.2.12

"""
@title Unagii Vault V2 0.1.1
@author stakewith.us
@license AGPL-3.0-or-later
"""

from vyper.interfaces import ERC20


interface DetailedERC20:
    def decimals() -> uint256: view


interface UnagiiToken:
    def minter() -> address: view
    def token() -> address: view
    def decimals() -> uint256: view
    def totalSupply() -> uint256: view
    def balanceOf(owner: address) -> uint256: view
    def mint(receiver: address, amount: uint256): nonpayable
    def burn(spender: address, amount: uint256): nonpayable
    def lastBlock(owner: address) -> uint256: view


# used for migrating to new Vault contract
interface Vault:
    def oldVault() -> address: view
    def token() -> address: view
    def uToken() -> address: view
    def fundManager() -> address: view
    def initialize(): nonpayable
    def balanceOfVault() -> uint256: view
    def debt() -> uint256: view
    def lockedProfit() -> uint256: view
    def lastReport() -> uint256: view


interface FundManager:
    def vault() -> address: view
    def token() -> address: view
    # returns loss = debt - total assets in fund manager
    def withdraw(amount: uint256) -> uint256: nonpayable


event Migrate:
    vault: address
    balanceOfVault: uint256
    debt: uint256
    lockedProfit: uint256


event SetNextTimeLock:
    nextTimeLock: address


event AcceptTimeLock:
    timeLock: address


event SetGuardian:
    guardian: address


event SetAdmin:
    admin: address


event SetFundManager:
    fundManager: address


event SetPause:
    paused: bool


event SetWhitelist:
    addr: indexed(address)
    approved: bool


event Deposit:
    sender: indexed(address)
    amount: uint256
    diff: uint256
    shares: uint256


event Withdraw:
    owner: indexed(address)
    shares: uint256
    amount: uint256


event Borrow:
    fundManager: indexed(address)
    amount: uint256
    borrowed: uint256


event Repay:
    fundManager: indexed(address)
    amount: uint256
    repaid: uint256


event Report:
    fundManager: indexed(address)
    balanceOfVault: uint256
    debt: uint256
    gain: uint256
    loss: uint256
    diff: uint256
    lockedProfit: uint256


event ForceUpdateBalanceOfVault:
    balanceOfVault: uint256


initialized: public(bool)
paused: public(bool)

token: public(ERC20)
uToken: public(UnagiiToken)
fundManager: public(FundManager)
# privileges: time lock >= admin >= guardian
timeLock: public(address)
nextTimeLock: public(address)
guardian: public(address)
admin: public(address)

depositLimit: public(uint256)
# token balance of vault tracked internally to protect against share dilution
# from sending tokens directly to this contract
balanceOfVault: public(uint256)
debt: public(uint256)  # debt to users (amount borrowed by fund manager)
# minimum amount of token to be kept in this vault for cheap withdraw
minReserve: public(uint256)
MAX_MIN_RESERVE: constant(uint256) = 10000
# timestamp of last report
lastReport: public(uint256)
# profit locked from report, released over time at a rate set by lockedProfitDegradation
lockedProfit: public(uint256)
MAX_DEGRADATION: constant(uint256) = 10 ** 18
# rate at which locked profit is released
# 0 = forever, MAX_DEGREDATION = 100% of profit is released 1 block after report
lockedProfitDegradation: public(uint256)
# minimum number of block to wait before deposit / withdraw
# used to protect agains flash attacks
blockDelay: public(uint256)
# whitelisted address can bypass block delay check
whitelist: public(HashMap[address, bool])
# set to true if token has fee on transfer
feeOnTransfer: public(bool)

# address of old Vault contract, used for migration
oldVault: public(Vault)
# constants used for protection when migrating vault funds
MIN_OLD_BAL: constant(uint256) = 9990
MAX_MIN_OLD_BAL: constant(uint256) = 10000


@external
def __init__(token: address, uToken: address, guardian: address, oldVault: address):
    self.timeLock = msg.sender
    self.admin = msg.sender
    self.guardian = guardian
    self.token = ERC20(token)
    self.uToken = UnagiiToken(uToken)

    assert self.uToken.token() == self.token.address, "uToken token != token"

    self.paused = True
    self.blockDelay = 1
    self.minReserve = 500  # 5% of free funds
    # 6 hours
    self.lockedProfitDegradation = convert(MAX_DEGRADATION / 21600, uint256)

    if oldVault != ZERO_ADDRESS:
        self.oldVault = Vault(oldVault)
        assert self.oldVault.token() == token, "old vault token != token"
        assert self.oldVault.uToken() == uToken, "old vault uToken != uToken"


@internal
def _safeApprove(token: address, spender: address, amount: uint256):
    res: Bytes[32] = raw_call(
        token,
        concat(
            method_id("approve(address,uint256)"),
            convert(spender, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(res) > 0:
        assert convert(res, bool), "approve failed"


@internal
def _safeTransfer(token: address, receiver: address, amount: uint256):
    res: Bytes[32] = raw_call(
        token,
        concat(
            method_id("transfer(address,uint256)"),
            convert(receiver, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(res) > 0:
        assert convert(res, bool), "transfer failed"


@internal
def _safeTransferFrom(
    token: address, owner: address, receiver: address, amount: uint256
):
    res: Bytes[32] = raw_call(
        token,
        concat(
            method_id("transferFrom(address,address,uint256)"),
            convert(owner, bytes32),
            convert(receiver, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(res) > 0:
        assert convert(res, bool), "transferFrom failed"


@external
def initialize():
    """
    @notice Initialize vault. Transfer tokens and copy states if old vault is set.
    """
    assert not self.initialized, "initialized"

    if self.oldVault.address == ZERO_ADDRESS:
        assert msg.sender in [self.timeLock, self.admin], "!auth"
        self.lastReport = block.timestamp
    else:
        assert msg.sender == self.oldVault.address, "!old vault"

        assert self.uToken.minter() == self, "minter != self"

        assert (
            self.fundManager.address == self.oldVault.fundManager()
        ), "fund manager != old vault fund manager"
        if self.fundManager.address != ZERO_ADDRESS:
            assert self.fundManager.vault() == self, "fund manager vault != self"

        # check balance of old vault >= old balanceOfVault
        bal: uint256 = self.token.balanceOf(self.oldVault.address)
        balOfVault: uint256 = self.oldVault.balanceOfVault()
        assert bal >= balOfVault, "bal < vault"

        diff: uint256 = self.token.balanceOf(self)
        self._safeTransferFrom(self.token.address, self.oldVault.address, self, bal)
        diff = self.token.balanceOf(self) - diff

        # diff may be <= balOfVault if fee on transfer
        assert diff >= balOfVault * MIN_OLD_BAL / MAX_MIN_OLD_BAL, "diff < min"

        self.balanceOfVault = min(balOfVault, diff)
        self.debt = self.oldVault.debt()
        self.lockedProfit = self.oldVault.lockedProfit()
        self.lastReport = self.oldVault.lastReport()

    self.initialized = True


# Migration steps from this vault to new vault
#
# t = token
# ut = unagi token
# v1 = vault 1
# v2 = vault 2
# f = fund manager
#
# action                         | caller
# ----------------------------------------
# 1. v2.setPause(true)           | admin
# 2. v1.setPause(true)           | admin
# 3. ut.setMinter(v2)            | time lock
# 4. f.setVault(v2)              | time lock
# 5. v2.setFundManager(f)        | time lock
# 6. t.approve(v2, bal)          | v1
# 7. t.transferFrom(v1, v2, bal) | v2
# 8. v2 copy states from v1      | v2
#    - balanceOfVault            |
#    - debt                      |
#    - locked profit             |
#    - last report               |
# 9. v1 set state = 0            | v1
#    - balanceOfVault            |
#    - debt                      |
#    - locked profit             |


@external
def migrate(vault: address):
    """
    @notice Migrate to new vault
    @param vault Address of new vault
    """
    assert msg.sender == self.timeLock, "!time lock"
    assert self.initialized, "!initialized"
    assert self.paused, "!paused"

    assert Vault(vault).token() == self.token.address, "new vault token != token"
    assert Vault(vault).uToken() == self.uToken.address, "new vault uToken != uToken"
    # minter is set to new vault
    assert self.uToken.minter() == vault, "minter != new vault"
    # new vault's fund manager is set to current fund manager
    assert (
        Vault(vault).fundManager() == self.fundManager.address
    ), "new vault fund manager != fund manager"
    if self.fundManager.address != ZERO_ADDRESS:
        # fund manager's vault is set to new vault
        assert self.fundManager.vault() == vault, "fund manager vault != new vault"

    # check balance of vault >= balanceOfVault
    bal: uint256 = self.token.balanceOf(self)
    assert bal >= self.balanceOfVault, "bal < vault"

    assert Vault(vault).oldVault() == self, "old vault != self"

    self._safeApprove(self.token.address, vault, bal)
    Vault(vault).initialize()

    # check all tokens where transferred
    assert self.token.balanceOf(self) == 0, "bal != 0"

    log Migrate(vault, self.balanceOfVault, self.debt, self.lockedProfit)

    # reset state
    self.balanceOfVault = 0
    self.debt = 0
    self.lockedProfit = 0


@external
def setNextTimeLock(nextTimeLock: address):
    """
    @notice Set next time lock
    @param nextTimeLock Address of next time lock
    """
    assert msg.sender == self.timeLock, "!time lock"
    self.nextTimeLock = nextTimeLock
    log SetNextTimeLock(nextTimeLock)


@external
def acceptTimeLock():
    """
    @notice Accept time lock
    @dev Only `nextTimeLock` can claim time lock
    """
    assert msg.sender == self.nextTimeLock, "!next time lock"
    self.timeLock = msg.sender
    self.nextTimeLock = ZERO_ADDRESS
    log AcceptTimeLock(msg.sender)


@external
def setAdmin(admin: address):
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    self.admin = admin
    log SetAdmin(admin)


@external
def setGuardian(guardian: address):
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    self.guardian = guardian
    log SetGuardian(guardian)


@external
def setFundManager(fundManager: address):
    """
    @notice Set fund manager
    @param fundManager Address of new fund manager
    """
    assert msg.sender == self.timeLock, "!time lock"

    assert FundManager(fundManager).vault() == self, "fund manager vault != self"
    assert (
        FundManager(fundManager).token() == self.token.address
    ), "fund manager token != token"

    self.fundManager = FundManager(fundManager)
    log SetFundManager(fundManager)


@external
def setPause(paused: bool):
    assert msg.sender in [self.timeLock, self.admin, self.guardian], "!auth"
    self.paused = paused
    log SetPause(paused)


@external
def setMinReserve(minReserve: uint256):
    """
    @notice Set minimum amount of token reserved in this vault for cheap
            withdrawn by user
    @param minReserve Numerator to calculate min reserve
           0 = all funds can be transferred to fund manager
           MAX_MIN_RESERVE = 0 tokens can be transferred to fund manager
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    assert minReserve <= MAX_MIN_RESERVE, "min reserve > max"
    self.minReserve = minReserve


@external
def setLockedProfitDegradation(degradation: uint256):
    """
    @notice Set locked profit degradation (rate locked profit is released)
    @param degradation Rate of degradation
                 0 = profit is locked forever
                 MAX_DEGRADATION = 100% of profit is released 1 block after report
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    assert degradation <= MAX_DEGRADATION, "degradation > max"
    self.lockedProfitDegradation = degradation


@external
def setDepositLimit(limit: uint256):
    """
    @notice Set limit to total deposit
    @param limit Limit for total deposit
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    self.depositLimit = limit


@external
def setBlockDelay(delay: uint256):
    """
    @notice Set block delay, used to protect against flash attacks
    @param delay Number of blocks to delay before user can deposit / withdraw
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    assert delay >= 1, "delay = 0"
    self.blockDelay = delay


@external
def setFeeOnTransfer(feeOnTransfer: bool):
    """
    @notice Enable calculation of actual amount transferred to this vault
            if token has fee on transfer
    @param feeOnTransfer True = enable calculation
                          False = disable calculation
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    self.feeOnTransfer = feeOnTransfer


@external
def setWhitelist(addr: address, approved: bool):
    """
    @notice Approve or disapprove address to skip check on block delay.
            Approved address can deposit, withdraw and transfer uToken in
            a single transaction
    @param approved Boolean True = approve
                             False = disapprove
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    self.whitelist[addr] = approved
    log SetWhitelist(addr, approved)


@internal
@view
def _totalAssets() -> uint256:
    """
    @notice Total amount of token in this vault + amount in fund manager
    @dev State variable `balanceOfVault` is used to track balance of token in
         this contract instead of `token.balanceOf(self)`. This is done to
         protect against uToken shares being diluted by directly sending token
         to this contract.
    @dev Returns total amount of token in this contract
    """
    return self.balanceOfVault + self.debt


@external
@view
def totalAssets() -> uint256:
    return self._totalAssets()


@internal
@view
def _calcLockedProfit() -> uint256:
    """
    @notice Calculated locked profit
    @dev Returns amount of profit locked from last report. Profit is released
         over time, depending on the release rate `lockedProfitDegradation`.
         Profit is locked after `report` to protect against sandwich attack.
    """
    lockedFundsRatio: uint256 = (
        block.timestamp - self.lastReport
    ) * self.lockedProfitDegradation

    if lockedFundsRatio < MAX_DEGRADATION:
        lockedProfit: uint256 = self.lockedProfit
        return lockedProfit - lockedFundsRatio * lockedProfit / MAX_DEGRADATION
    else:
        return 0


@external
@view
def calcLockedProfit() -> uint256:
    return self._calcLockedProfit()


@internal
@view
def _calcFreeFunds() -> uint256:
    """
    @notice Calculate free funds (total assets - locked profit)
    @dev Returns total amount of tokens that can be withdrawn
    """
    return self._totalAssets() - self._calcLockedProfit()


@external
@view
def calcFreeFunds() -> uint256:
    return self._calcFreeFunds()


@internal
@pure
def _calcSharesToMint(
    amount: uint256, totalSupply: uint256, freeFunds: uint256
) -> uint256:
    """
    @notice Calculate uToken shares to mint
    @param amount Amount of token to deposit
    @param totalSupply Total amount of shares
    @param freeFunds Free funds before deposit
    @dev Returns amount of uToken to mint. Input must be numbers before deposit
    @dev Calculated with `freeFunds`, not `totalAssets`
    """
    # s = shares to mint
    # T = total shares before mint
    # a = deposit amount
    # P = total amount of underlying token in vault + fund manager before deposit
    # s / (T + s) = a / (P + a)
    # sP = aT
    # a = 0               | mint s = 0
    # a > 0, T = 0, P = 0 | mint s = a
    # a > 0, T = 0, P > 0 | mint s = a as if P = 0
    # a > 0, T > 0, P = 0 | invalid, equation cannot be true for any s
    # a > 0, T > 0, P > 0 | mint s = aT / P
    if amount == 0:
        return 0
    if totalSupply == 0:
        return amount
    # reverts if free funds = 0
    return amount * totalSupply / freeFunds


@external
@view
def calcSharesToMint(amount: uint256) -> uint256:
    return self._calcSharesToMint(
        amount, self.uToken.totalSupply(), self._calcFreeFunds()
    )


@internal
@pure
def _calcWithdraw(shares: uint256, totalSupply: uint256, freeFunds: uint256) -> uint256:
    """
    @notice Calculate amount of token to withdraw
    @param shares Amount of uToken shares to burn
    @param totalSupply Total amount of shares before burn
    @param freeFunds Free funds
    @dev Returns amount of token to withdraw
    @dev Calculated with `freeFunds`, not `totalAssets`
    """
    # s = shares
    # T = total supply of shares
    # a = amount to withdraw
    # P = total amount of underlying token in vault + fund manager
    # s / T = a / P (constraints T >= s, P >= a)
    # sP = aT
    # s = 0               | a = 0
    # s > 0, T = 0, P = 0 | invalid (violates constraint T >= s)
    # s > 0, T = 0, P > 0 | invalid (violates constraint T >= s)
    # s > 0, T > 0, P = 0 | a = 0
    # s > 0, T > 0, P > 0 | a = sP / T
    if shares == 0:
        return 0
    # invalid if total supply = 0
    return shares * freeFunds / totalSupply


@external
@view
def calcWithdraw(shares: uint256) -> uint256:
    return self._calcWithdraw(shares, self.uToken.totalSupply(), self._calcFreeFunds())


@external
@nonreentrant("lock")
def deposit(amount: uint256, _min: uint256) -> uint256:
    """
    @notice Deposit token into vault
    @param amount Amount of token to deposit
    @param _min Minimum amount of uToken to be minted
    @dev Returns actual amount of uToken minted
    """
    assert self.initialized, "!initialized"
    assert not self.paused, "paused"
    # check block delay or whitelisted
    assert (
        block.number >= self.uToken.lastBlock(msg.sender) + self.blockDelay
        or self.whitelist[msg.sender]
    ), "block < delay"

    _amount: uint256 = min(amount, self.token.balanceOf(msg.sender))
    assert _amount > 0, "deposit = 0"

    # check deposit limit
    assert self._totalAssets() + _amount <= self.depositLimit, "deposit limit"

    totalSupply: uint256 = self.uToken.totalSupply()
    freeFunds: uint256 = self._calcFreeFunds()

    # amount of tokens that this vault received
    diff: uint256 = 0
    if self.feeOnTransfer:
        # actual amount transferred may be less than `amount`
        # if token has fee on transfer
        diff = self.token.balanceOf(self)
        self._safeTransferFrom(self.token.address, msg.sender, self, _amount)
        diff = self.token.balanceOf(self) - diff
    else:
        self._safeTransferFrom(self.token.address, msg.sender, self, _amount)
        diff = _amount

    assert diff > 0, "diff = 0"

    # calculate with free funds before deposit
    shares: uint256 = self._calcSharesToMint(diff, totalSupply, freeFunds)
    assert shares >= _min, "shares < min"

    self.balanceOfVault += diff
    self.uToken.mint(msg.sender, shares)

    # check token balance >= balanceOfVault
    assert self.token.balanceOf(self) >= self.balanceOfVault, "bal < vault"

    log Deposit(msg.sender, _amount, diff, shares)

    return shares


@external
@nonreentrant("lock")
def withdraw(shares: uint256, _min: uint256) -> uint256:
    """
    @notice Withdraw token from vault
    @param shares Amount of uToken to burn
    @param _min Minimum amount of token that msg.sender will receive
    @dev Returns actual amount of token transferred to msg.sender
    """
    assert self.initialized, "!initialized"
    # check block delay or whitelisted
    assert (
        block.number >= self.uToken.lastBlock(msg.sender) + self.blockDelay
        or self.whitelist[msg.sender]
    ), "block < delay"

    _shares: uint256 = min(shares, self.uToken.balanceOf(msg.sender))
    assert _shares > 0, "shares = 0"

    amount: uint256 = self._calcWithdraw(
        _shares, self.uToken.totalSupply(), self._calcFreeFunds()
    )

    # withdraw from fund manager if amount to withdraw > balance of vault
    if amount > self.balanceOfVault:
        diff: uint256 = self.token.balanceOf(self)
        # loss = debt - total assets in fund manager + any loss from strategies
        loss: uint256 = self.fundManager.withdraw(amount - self.balanceOfVault)
        diff = self.token.balanceOf(self) - diff

        # diff + loss may be >= amount
        if loss > 0:
            # msg.sender must cover all of loss
            amount -= loss
            self.debt -= loss

        self.debt -= diff
        self.balanceOfVault += diff

        if amount > self.balanceOfVault:
            amount = self.balanceOfVault

    self.uToken.burn(msg.sender, _shares)

    assert amount >= _min, "amount < min"
    self.balanceOfVault -= amount

    self._safeTransfer(self.token.address, msg.sender, amount)

    # check token balance >= balanceOfVault
    assert self.token.balanceOf(self) >= self.balanceOfVault, "bal < vault"

    log Withdraw(msg.sender, _shares, amount)

    # actual amount received by msg.sender may be less if fee on transfer
    return amount


@internal
@view
def _calcMinReserve() -> uint256:
    """
    @notice Calculate minimum amount of token that is reserved in vault for
            cheap withdraw by users
    @dev Returns min reserve
    """
    freeFunds: uint256 = self._calcFreeFunds()
    return freeFunds * self.minReserve / MAX_MIN_RESERVE


@external
def calcMinReserve() -> uint256:
    return self._calcMinReserve()


@internal
@view
def _calcMaxBorrow() -> uint256:
    """
    @notice Calculate amount of token available for fund manager to borrow
    @dev Returns amount of token fund manager can borrow
    """
    if (
        (not self.initialized)
        or self.paused
        or self.fundManager.address == ZERO_ADDRESS
    ):
        return 0

    minBal: uint256 = self._calcMinReserve()

    if self.balanceOfVault > minBal:
        return self.balanceOfVault - minBal
    return 0


@external
@view
def calcMaxBorrow() -> uint256:
    return self._calcMaxBorrow()


@external
def borrow(amount: uint256) -> uint256:
    """
    @notice Borrow token from vault
    @dev Only fund manager can borrow
    @dev Returns actual amount that was given to fund manager
    """
    assert self.initialized, "!initialized"
    assert not self.paused, "paused"
    assert msg.sender == self.fundManager.address, "!fund manager"

    available: uint256 = self._calcMaxBorrow()
    _amount: uint256 = min(amount, available)
    assert _amount > 0, "borrow = 0"

    self._safeTransfer(self.token.address, msg.sender, _amount)

    self.balanceOfVault -= _amount
    # include fee on trasfer to debt
    self.debt += _amount

    # check token balance >= balanceOfVault
    assert self.token.balanceOf(self) >= self.balanceOfVault, "bal < vault"

    log Borrow(msg.sender, amount, _amount)

    return _amount


@external
def repay(amount: uint256) -> uint256:
    """
    @notice Repay token to vault
    @dev Only fund manager can borrow
    @dev Returns actual amount that was repaid by fund manager
    """
    assert self.initialized, "!initialized"
    assert msg.sender == self.fundManager.address, "!fund manager"

    _amount: uint256 = min(amount, self.debt)
    assert _amount > 0, "repay = 0"

    diff: uint256 = self.token.balanceOf(self)
    self._safeTransferFrom(self.token.address, msg.sender, self, _amount)
    diff = self.token.balanceOf(self) - diff

    self.balanceOfVault += diff
    # exclude fee on transfer from debt payment
    self.debt -= diff

    # check token balance >= balanceOfVault
    assert self.token.balanceOf(self) >= self.balanceOfVault, "bal < vault"

    log Repay(msg.sender, amount, diff)

    return diff


@external
def report(gain: uint256, loss: uint256):
    """
    @notice Report profit or loss
    @param gain Profit since last report
    @param loss Loss since last report
    @dev Only fund manager can call
    @dev Locks profit to be release over time
    """
    assert self.initialized, "!initialized"
    assert msg.sender == self.fundManager.address, "!fund manager"
    # can't have both gain and loss > 0
    assert (gain >= 0 and loss == 0) or (gain == 0 and loss >= 0), "gain and loss > 0"

    # calculate current locked profit
    lockedProfit: uint256 = self._calcLockedProfit()
    diff: uint256 = 0  # actual amount transferred if gain > 0

    if gain > 0:
        diff = self.token.balanceOf(self)
        self._safeTransferFrom(self.token.address, msg.sender, self, gain)
        diff = self.token.balanceOf(self) - diff

        # free funds = bal + diff + debt - (locked profit + diff)
        self.balanceOfVault += diff
        self.lockedProfit = lockedProfit + diff
    elif loss > 0:
        # free funds = bal + debt - loss - (locked profit - loss)
        self.debt -= loss
        # deduct locked profit
        if lockedProfit > loss:
            self.lockedProfit -= loss
        else:
            # no locked profit to be released
            self.lockedProfit = 0

    self.lastReport = block.timestamp

    # check token balance >= balanceOfVault
    assert self.token.balanceOf(self) >= self.balanceOfVault, "bal < vault"

    # log updated debt and lockedProfit
    log Report(
        msg.sender, self.balanceOfVault, self.debt, gain, loss, diff, self.lockedProfit
    )


@external
def forceUpdateBalanceOfVault():
    """
    @notice Force `balanceOfVault` to equal `token.balanceOf(self)`
    @dev Only use in case of emergency if `balanceOfVault` is > actual balance
    """
    assert self.initialized, "!initialized"
    assert msg.sender in [self.timeLock, self.admin], "!auth"

    bal: uint256 = self.token.balanceOf(self)
    assert bal < self.balanceOfVault, "bal >= vault"

    self.balanceOfVault = bal
    log ForceUpdateBalanceOfVault(bal)


@external
def skim():
    """
    @notice Transfer excess token sent to this contract to admin or time lock
    @dev actual token balance must be >= `balanceOfVault`
    """
    assert msg.sender == self.timeLock, "!time lock"
    self._safeTransfer(
        self.token.address, msg.sender, self.token.balanceOf(self) - self.balanceOfVault
    )


@external
def sweep(token: address):
    """
    @notice Transfer any token (except `token`) accidentally sent to this contract
            to admin or time lock
    @dev Cannot transfer `token`
    """
    assert msg.sender in [self.timeLock, self.admin], "!auth"
    assert token != self.token.address, "protected"
    self._safeTransfer(token, msg.sender, ERC20(token).balanceOf(self))

Contract Security Audit

Contract ABI

[{"name":"Migrate","inputs":[{"name":"vault","type":"address","indexed":false},{"name":"balanceOfVault","type":"uint256","indexed":false},{"name":"debt","type":"uint256","indexed":false},{"name":"lockedProfit","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetNextTimeLock","inputs":[{"name":"nextTimeLock","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"AcceptTimeLock","inputs":[{"name":"timeLock","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetGuardian","inputs":[{"name":"guardian","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetAdmin","inputs":[{"name":"admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetFundManager","inputs":[{"name":"fundManager","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetPause","inputs":[{"name":"paused","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetWhitelist","inputs":[{"name":"addr","type":"address","indexed":true},{"name":"approved","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"Deposit","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false},{"name":"diff","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Withdraw","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"shares","type":"uint256","indexed":false},{"name":"amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Borrow","inputs":[{"name":"fundManager","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false},{"name":"borrowed","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Repay","inputs":[{"name":"fundManager","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false},{"name":"repaid","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Report","inputs":[{"name":"fundManager","type":"address","indexed":true},{"name":"balanceOfVault","type":"uint256","indexed":false},{"name":"debt","type":"uint256","indexed":false},{"name":"gain","type":"uint256","indexed":false},{"name":"loss","type":"uint256","indexed":false},{"name":"diff","type":"uint256","indexed":false},{"name":"lockedProfit","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ForceUpdateBalanceOfVault","inputs":[{"name":"balanceOfVault","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"token","type":"address"},{"name":"uToken","type":"address"},{"name":"guardian","type":"address"},{"name":"oldVault","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"initialize","inputs":[],"outputs":[],"gas":248610},{"stateMutability":"nonpayable","type":"function","name":"migrate","inputs":[{"name":"vault","type":"address"}],"outputs":[],"gas":132522},{"stateMutability":"nonpayable","type":"function","name":"setNextTimeLock","inputs":[{"name":"nextTimeLock","type":"address"}],"outputs":[],"gas":38981},{"stateMutability":"nonpayable","type":"function","name":"acceptTimeLock","inputs":[],"outputs":[],"gas":58909},{"stateMutability":"nonpayable","type":"function","name":"setAdmin","inputs":[{"name":"admin","type":"address"}],"outputs":[],"gas":41562},{"stateMutability":"nonpayable","type":"function","name":"setGuardian","inputs":[{"name":"guardian","type":"address"}],"outputs":[],"gas":41592},{"stateMutability":"nonpayable","type":"function","name":"setFundManager","inputs":[{"name":"fundManager","type":"address"}],"outputs":[],"gas":46178},{"stateMutability":"nonpayable","type":"function","name":"setPause","inputs":[{"name":"paused","type":"bool"}],"outputs":[],"gas":43920},{"stateMutability":"nonpayable","type":"function","name":"setMinReserve","inputs":[{"name":"minReserve","type":"uint256"}],"outputs":[],"gas":40353},{"stateMutability":"nonpayable","type":"function","name":"setLockedProfitDegradation","inputs":[{"name":"degradation","type":"uint256"}],"outputs":[],"gas":40383},{"stateMutability":"nonpayable","type":"function","name":"setDepositLimit","inputs":[{"name":"limit","type":"uint256"}],"outputs":[],"gas":40295},{"stateMutability":"nonpayable","type":"function","name":"setBlockDelay","inputs":[{"name":"delay","type":"uint256"}],"outputs":[],"gas":40443},{"stateMutability":"nonpayable","type":"function","name":"setFeeOnTransfer","inputs":[{"name":"feeOnTransfer","type":"bool"}],"outputs":[],"gas":40455},{"stateMutability":"nonpayable","type":"function","name":"setWhitelist","inputs":[{"name":"addr","type":"address"},{"name":"approved","type":"bool"}],"outputs":[],"gas":42428},{"stateMutability":"view","type":"function","name":"totalAssets","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":5883},{"stateMutability":"view","type":"function","name":"calcLockedProfit","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":8829},{"stateMutability":"view","type":"function","name":"calcFreeFunds","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":28253},{"stateMutability":"view","type":"function","name":"calcSharesToMint","inputs":[{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":34581},{"stateMutability":"view","type":"function","name":"calcWithdraw","inputs":[{"name":"shares","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":34486},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"amount","type":"uint256"},{"name":"_min","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":217581},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"shares","type":"uint256"},{"name":"_min","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":330139},{"stateMutability":"nonpayable","type":"function","name":"calcMinReserve","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":59242},{"stateMutability":"view","type":"function","name":"calcMaxBorrow","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":129639},{"stateMutability":"nonpayable","type":"function","name":"borrow","inputs":[{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":232404},{"stateMutability":"nonpayable","type":"function","name":"repay","inputs":[{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":112883},{"stateMutability":"nonpayable","type":"function","name":"report","inputs":[{"name":"gain","type":"uint256"},{"name":"loss","type":"uint256"}],"outputs":[],"gas":160503},{"stateMutability":"nonpayable","type":"function","name":"forceUpdateBalanceOfVault","inputs":[],"outputs":[],"gas":51024},{"stateMutability":"nonpayable","type":"function","name":"skim","inputs":[],"outputs":[],"gas":22369},{"stateMutability":"nonpayable","type":"function","name":"sweep","inputs":[{"name":"token","type":"address"}],"outputs":[],"gas":20791},{"stateMutability":"view","type":"function","name":"initialized","inputs":[],"outputs":[{"name":"","type":"bool"}],"gas":3258},{"stateMutability":"view","type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"bool"}],"gas":3288},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3318},{"stateMutability":"view","type":"function","name":"uToken","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3348},{"stateMutability":"view","type":"function","name":"fundManager","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3378},{"stateMutability":"view","type":"function","name":"timeLock","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3408},{"stateMutability":"view","type":"function","name":"nextTimeLock","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3438},{"stateMutability":"view","type":"function","name":"guardian","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3468},{"stateMutability":"view","type":"function","name":"admin","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3498},{"stateMutability":"view","type":"function","name":"depositLimit","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3528},{"stateMutability":"view","type":"function","name":"balanceOfVault","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3558},{"stateMutability":"view","type":"function","name":"debt","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3588},{"stateMutability":"view","type":"function","name":"minReserve","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3618},{"stateMutability":"view","type":"function","name":"lastReport","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3648},{"stateMutability":"view","type":"function","name":"lockedProfit","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3678},{"stateMutability":"view","type":"function","name":"lockedProfitDegradation","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3708},{"stateMutability":"view","type":"function","name":"blockDelay","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3738},{"stateMutability":"view","type":"function","name":"whitelist","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"bool"}],"gas":3983},{"stateMutability":"view","type":"function","name":"feeOnTransfer","inputs":[],"outputs":[{"name":"","type":"bool"}],"gas":3798},{"stateMutability":"view","type":"function","name":"oldVault","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3828}]

Deployed Bytecode

0x600436101561000d57613736565b600035601c52600051341561002157600080fd5b638129fc1c8114156106345760005415151561007c576308c379a061014052602061016052600b610180527f696e697469616c697a65640000000000000000000000000000000000000000006101a05261018050606461015cfd5b601354151561012f57600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156100c457600183526100d4565b81516001018083528114156100a8575b505050610140511515610126576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b42600d5561062d565b6013543314151561017f576308c379a061014052602061016052600a610180527f216f6c64207661756c74000000000000000000000000000000000000000000006101a05261018050606461015cfd5b3060206101a0600463075461726101405261015c6003545afa6101a157600080fd5b601f3d116101ae57600080fd5b6000506101a051141515610201576308c379a06101c05260206101e052600e610200527f6d696e74657220213d2073656c66000000000000000000000000000000000000610220526102005060646101dcfd5b60206101a06004636209ec2d6101405261015c6013545afa61022257600080fd5b601f3d1161022f57600080fd5b6000506101a0516004541415156102aa576308c379a06101c05260206101e0526026610200527f66756e64206d616e6167657220213d206f6c64207661756c742066756e64206d610220527f616e616765720000000000000000000000000000000000000000000000000000610240526102005060846101dcfd5b60006004541815610337573060206101a0600463fbfa77cf6101405261015c6004545afa6102d757600080fd5b601f3d116102e457600080fd5b6000506101a051141515610337576308c379a06101c05260206101e052601a610200527f66756e64206d616e61676572207661756c7420213d2073656c66000000000000610220526102005060646101dcfd5b60206101e060246370a08231610160526013546101805261017c6002545afa61035f57600080fd5b601f3d1161036c57600080fd5b6000506101e0516101405260206101e06004639994673d6101805261019c6013545afa61039857600080fd5b601f3d116103a557600080fd5b6000506101e05161016052610160516101405110151515610405576308c379a06101805260206101a052600b6101c0527f62616c203c207661756c740000000000000000000000000000000000000000006101e0526101c050606461019cfd5b602061022060246370a082316101a052306101c0526101bc6002545afa61042b57600080fd5b601f3d1161043857600080fd5b60005061022051610180526101405161016051610180516002546101a0526013546101c052306101e0526101405161020052610200516101e0516101c0516101a05160065801613a70565b610180526101605261014052600050602061022060246370a082316101a052306101c0526101bc6002545afa6104b857600080fd5b601f3d116104c557600080fd5b6000506102205161018051808210156104dd57600080fd5b808203905090506101805261016051612706808202821582848304141761050357600080fd5b80905090509050612710808204905090506101805110151515610565576308c379a06101a05260206101c052600a6101e0527f64696666203c206d696e00000000000000000000000000000000000000000000610200526101e05060646101bcfd5b61016051610180518082111561057b578061057d565b815b90509050600a5560206102006004630dca59c16101a0526101bc6013545afa6105a557600080fd5b601f3d116105b257600080fd5b60005061020051600b55602061020060046344b813966101a0526101bc6013545afa6105dd57600080fd5b601f3d116105ea57600080fd5b60005061020051600e556020610200600463c3535b526101a0526101bc6013545afa61061557600080fd5b601f3d1161062257600080fd5b60005061020051600d555b6001600055005b63ce5494bb811415610c535760043560a01c1561065057600080fd5b600554331415156106a0576308c379a061014052602061016052600a610180527f2174696d65206c6f636b000000000000000000000000000000000000000000006101a05261018050606461015cfd5b60005415156106ee576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b600154151561073c576308c379a0610140526020610160526007610180527f21706175736564000000000000000000000000000000000000000000000000006101a05261018050606461015cfd5b60025460206101a0600463fc0c546a6101405261015c6004355afa61076057600080fd5b601f3d1161076d57600080fd5b6000506101a0511415156107c0576308c379a06101c05260206101e0526018610200527f6e6577207661756c7420746f6b656e20213d20746f6b656e0000000000000000610220526102005060646101dcfd5b60035460206101a0600463633156376101405261015c6004355afa6107e457600080fd5b601f3d116107f157600080fd5b6000506101a051141515610844576308c379a06101c05260206101e052601a610200527f6e6577207661756c742075546f6b656e20213d2075546f6b656e000000000000610220526102005060646101dcfd5b60043560206101a0600463075461726101405261015c6003545afa61086857600080fd5b601f3d1161087557600080fd5b6000506101a0511415156108c8576308c379a06101c05260206101e0526013610200527f6d696e74657220213d206e6577207661756c7400000000000000000000000000610220526102005060646101dcfd5b60045460206101a06004636209ec2d6101405261015c6004355afa6108ec57600080fd5b601f3d116108f957600080fd5b6000506101a051141515610971576308c379a06101c05260206101e0526026610200527f6e6577207661756c742066756e64206d616e6167657220213d2066756e64206d610220527f616e616765720000000000000000000000000000000000000000000000000000610240526102005060846101dcfd5b60006004541815610a005760043560206101a0600463fbfa77cf6101405261015c6004545afa6109a057600080fd5b601f3d116109ad57600080fd5b6000506101a051141515610a00576308c379a06101c05260206101e052601f610200527f66756e64206d616e61676572207661756c7420213d206e6577207661756c7400610220526102005060646101dcfd5b60206101e060246370a0823161016052306101805261017c6002545afa610a2657600080fd5b601f3d11610a3357600080fd5b6000506101e05161014052600a546101405110151515610a92576308c379a061016052602061018052600b6101a0527f62616c203c207661756c740000000000000000000000000000000000000000006101c0526101a050606461017cfd5b3060206101c060046392f73fc06101605261017c6004355afa610ab457600080fd5b601f3d11610ac157600080fd5b6000506101c051141515610b14576308c379a06101e0526020610200526011610220527f6f6c64207661756c7420213d2073656c66000000000000000000000000000000610240526102205060646101fcfd5b610140516002546101605260043561018052610140516101a0526101a05161018051610160516006580161373c565b610140526000506004353b610b5757600080fd5b600060006004638129fc1c6101605261017c60006004355af1610b7957600080fd5b60206101e060246370a0823161016052306101805261017c6002545afa610b9f57600080fd5b601f3d11610bac57600080fd5b6000506101e051151515610bff576308c379a0610200526020610220526008610240527f62616c20213d20300000000000000000000000000000000000000000000000006102605261024050606461021cfd5b60043561016052600a5461018052600b546101a052600e546101c0527fc47a839c70aa320457c80c5abd38ce8b516c72e37be119b7962f67f1f8eb7ac26080610160a16000600a556000600b556000600e55005b6347a02a44811415610cf55760043560a01c15610c6f57600080fd5b60055433141515610cbf576308c379a061014052602061016052600a610180527f2174696d65206c6f636b000000000000000000000000000000000000000000006101a05261018050606461015cfd5b600435600655600435610140527f5c06d5a6f95a574bb95a214c88933831c63fcd6f6c5d1d61a21efb92be19bc2c6020610140a1005b631e39831e811415610d885760065433141515610d51576308c379a061014052602061016052600f610180527f216e6578742074696d65206c6f636b00000000000000000000000000000000006101a05261018050606461015cfd5b33600555600060065533610140527f77b69635186d51fb2d031f67a7995795c8384acb800219c7d30861125d154f026020610140a1005b63704b6c02811415610e7b5760043560a01c15610da457600080fd5b600554610160526008546101805260006101405261014061012060006002818352015b610120516020026101600151331415610de35760018352610df3565b8151600101808352811415610dc7575b505050610140511515610e45576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b600435600855600435610140527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a16020610140a1005b638a0dac4a811415610f6e5760043560a01c15610e9757600080fd5b600554610160526008546101805260006101405261014061012060006002818352015b610120516020026101600151331415610ed65760018352610ee6565b8151600101808352811415610eba575b505050610140511515610f38576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b600435600755600435610140527f31845eceb9cde510c7e8b37f76301c688feb70bc9653aa4c28a3734999840fd86020610140a1005b63232a30608114156111165760043560a01c15610f8a57600080fd5b60055433141515610fda576308c379a061014052602061016052600a610180527f2174696d65206c6f636b000000000000000000000000000000000000000000006101a05261018050606461015cfd5b3060206101a0600463fbfa77cf6101405261015c6004355afa610ffc57600080fd5b601f3d1161100957600080fd5b6000506101a05114151561105c576308c379a06101c05260206101e052601a610200527f66756e64206d616e61676572207661756c7420213d2073656c66000000000000610220526102005060646101dcfd5b60025460206101a0600463fc0c546a6101405261015c6004355afa61108057600080fd5b601f3d1161108d57600080fd5b6000506101a0511415156110e0576308c379a06101c05260206101e052601b610200527f66756e64206d616e6167657220746f6b656e20213d20746f6b656e0000000000610220526102005060646101dcfd5b600435600455600435610140527f5b94aba958ab93884b4020c8f52abddc2584e61c0adf58c3ab88acb28480e6f56020610140a1005b63bedb86fb8114156112105760043560011c1561113257600080fd5b60055461016052600854610180526007546101a05260006101405261014061012060006003818352015b6101205160200261016001513314156111785760018352611188565b815160010180835281141561115c575b5050506101405115156111da576308c379a06101c05260206101e0526005610200527f2161757468000000000000000000000000000000000000000000000000000000610220526102005060646101dcfd5b600435600155600435610140527f140eb9f8b591138e129e4caf389c92df4f0545b902523eee9e63153ecdb2026e6020610140a1005b633deb91c781141561131857600554610160526008546101805260006101405261014061012060006002818352015b61012051602002610160015133141561125b576001835261126b565b815160010180835281141561123f575b5050506101405115156112bd576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b61271060043511151515611310576308c379a0610140526020610160526011610180527f6d696e2072657365727665203e206d61780000000000000000000000000000006101a05261018050606461015cfd5b600435600c55005b637a55036581141561142657600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156113635760018352611373565b8151600101808352811415611347575b5050506101405115156113c5576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b670de0b6b3a76400006004351115151561141e576308c379a0610140526020610160526011610180527f6465677261646174696f6e203e206d61780000000000000000000000000000006101a05261018050606461015cfd5b600435600f55005b63bdc8144b8114156114db57600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156114715760018352611481565b8151600101808352811415611455575b5050506101405115156114d3576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b600435600955005b63fa67ae5a8114156115e257600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156115265760018352611536565b815160010180835281141561150a575b505050610140511515611588576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b6001600435101515156115da576308c379a0610140526020610160526009610180527f64656c6179203d203000000000000000000000000000000000000000000000006101a05261018050606461015cfd5b600435601055005b63f107779f8114156116a75760043560011c156115fe57600080fd5b600554610160526008546101805260006101405261014061012060006002818352015b61012051602002610160015133141561163d576001835261164d565b8151600101808352811415611621575b50505061014051151561169f576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b600435601255005b6353d6fd598114156117bb5760043560a01c156116c357600080fd5b60243560011c156116d357600080fd5b600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156117125760018352611722565b81516001018083528114156116f6575b505050610140511515611774576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b602435601160043560e05260c052604060c02055602435610140526004357ff6019ec0a78d156d249a1ec7579e2321f6ac7521d6e1d2eacf90ba4a184dcceb6020610140a2005b6301e1d1148114156117e15760065801613c21565b610140526101405160005260206000f35b630f73cea68114156118075760065801613c4d565b610140526101405160005260206000f35b63d13e56f181141561182d5760065801613d10565b610140526101405160005260206000f35b63ae074a098114156119245760206101a060046318160ddd6101405261015c6003545afa61185a57600080fd5b601f3d1161186757600080fd5b6000506101a0516101c0526101405161016051610180516101a0516101c05160065801613d10565b6101e0526101c0526101a0526101805261016052610140526101e051610200526101405161016051610180516101a0516101c0516101e05161020051600435610220526101c05161024052610200516102605261026051610240516102205160065801613d6e565b6102c052610200526101e0526101c0526101a0526101805261016052610140526102c05160005260206000f35b639b05f5e4811415611a1b5760206101a060046318160ddd6101405261015c6003545afa61195157600080fd5b601f3d1161195e57600080fd5b6000506101a0516101c0526101405161016051610180516101a0516101c05160065801613d10565b6101e0526101c0526101a0526101805261016052610140526101e051610200526101405161016051610180516101a0516101c0516101e05161020051600435610220526101c05161024052610200516102605261026051610240516102205160065801613df4565b6102c052610200526101e0526101c0526101a0526101805261016052610140526102c05160005260206000f35b63e2bbb1588114156120bd5760145415611a3457600080fd5b60016014556000541515611a87576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b600154151515611ad6576308c379a0610140526020610160526006610180527f70617573656400000000000000000000000000000000000000000000000000006101a05261018050606461015cfd5b6020610260602463952ca92c6101e05233610200526101fc6003545afa611afc57600080fd5b601f3d11611b0957600080fd5b60005061026051601054818183011015611b2257600080fd5b8082019050905043101515611b38576001611b48565b60113360e05260c052604060c020545b1515611b93576308c379a06102805260206102a052600d6102c0527f626c6f636b203c2064656c6179000000000000000000000000000000000000006102e0526102c050606461029cfd5b60043560206101e060246370a0823161016052336101805261017c6002545afa611bbc57600080fd5b601f3d11611bc957600080fd5b6000506101e05180821115611bde5780611be0565b815b9050905061014052600061014051111515611c3a576308c379a061016052602061018052600b6101a0527f6465706f736974203d20300000000000000000000000000000000000000000006101c0526101a050606461017cfd5b6009546101405160065801613c21565b61016052610140526101605161014051818183011015611c6957600080fd5b8082019050905011151515611cbd576308c379a06101805260206101a052600d6101c0527f6465706f736974206c696d6974000000000000000000000000000000000000006101e0526101c050606461019cfd5b60206101e060046318160ddd6101805261019c6003545afa611cde57600080fd5b601f3d11611ceb57600080fd5b6000506101e0516101605261014051610160516101805160065801613d10565b6101a0526101805261016052610140526101a0516101805260006101a05260125415611e1f57602061024060246370a082316101c052306101e0526101dc6002545afa611d5757600080fd5b601f3d11611d6457600080fd5b600050610240516101a0526101405161016051610180516101a0516002546101c052336101e0523061020052610140516102205261022051610200516101e0516101c05160065801613a70565b6101a052610180526101605261014052600050602061024060246370a082316101c052306101e0526101dc6002545afa611dea57600080fd5b601f3d11611df757600080fd5b600050610240516101a05180821015611e0f57600080fd5b808203905090506101a052611e7d565b6101405161016051610180516101a0516002546101c052336101e0523061020052610140516102205261022051610200516101e0516101c05160065801613a70565b6101a052610180526101605261014052600050610140516101a0525b60006101a051111515611ecf576308c379a06101c05260206101e0526008610200527f64696666203d2030000000000000000000000000000000000000000000000000610220526102005060646101dcfd5b6101405161016051610180516101a0516101c0516101a0516101e0526101605161020052610180516102205261022051610200516101e05160065801613d6e565b610280526101c0526101a052610180526101605261014052610280516101c0526024356101c05110151515611f84576308c379a06101e052602061020052600c610220527f736861726573203c206d696e0000000000000000000000000000000000000000610240526102205060646101fcfd5b600a80546101a051818183011015611f9b57600080fd5b808201905090508155506003543b611fb257600080fd5b6000600060446340c10f196101e05233610200526101c051610220526101fc60006003545af1611fe157600080fd5b600a54602061026060246370a082316101e05230610200526101fc6002545afa61200a57600080fd5b601f3d1161201757600080fd5b600050610260511015151561206b576308c379a06102805260206102a052600b6102c0527f62616c203c207661756c740000000000000000000000000000000000000000006102e0526102c050606461029cfd5b610140516101e0526101a051610200526101c05161022052337f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e60606101e0a26101c051600052600060145560206000f35b63441a3e708114156126ef57601454156120d657600080fd5b60016014556000541515612129576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b6020610260602463952ca92c6101e05233610200526101fc6003545afa61214f57600080fd5b601f3d1161215c57600080fd5b6000506102605160105481818301101561217557600080fd5b808201905090504310151561218b57600161219b565b60113360e05260c052604060c020545b15156121e6576308c379a06102805260206102a052600d6102c0527f626c6f636b203c2064656c6179000000000000000000000000000000000000006102e0526102c050606461029cfd5b60043560206101e060246370a0823161016052336101805261017c6003545afa61220f57600080fd5b601f3d1161221c57600080fd5b6000506101e051808211156122315780612233565b815b905090506101405260006101405111151561228d576308c379a061016052602061018052600a6101a0527f736861726573203d2030000000000000000000000000000000000000000000006101c0526101a050606461017cfd5b60206101e060046318160ddd6101805261019c6003545afa6122ae57600080fd5b601f3d116122bb57600080fd5b6000506101e051610200526101405161016051610180516101a0516101c0516101e0516102005160065801613d10565b61022052610200526101e0526101c0526101a05261018052610160526101405261022051610240526101405161016051610180516101a0516101c0516101e05161020051610220516102405161014051610260526102005161028052610240516102a0526102a051610280516102605160065801613df4565b610300526102405261022052610200526101e0526101c0526101a0526101805261016052610140526103005161016052600a5461016051111561253057602061022060246370a082316101a052306101c0526101bc6002545afa6123c757600080fd5b601f3d116123d457600080fd5b600050610220516101805260206102406024632e1a7d4d6101c05261016051600a548082101561240357600080fd5b808203905090506101e0526101dc60006004545af161242157600080fd5b601f3d1161242e57600080fd5b600050610240516101a052602061024060246370a082316101c052306101e0526101dc6002545afa61245f57600080fd5b601f3d1161246c57600080fd5b60005061024051610180518082101561248457600080fd5b808203905090506101805260006101a05111156124db5761016080516101a051808210156124b157600080fd5b80820390509050815250600b80546101a051808210156124d057600080fd5b808203905090508155505b600b805461018051808210156124f057600080fd5b80820390509050815550600a80546101805181818301101561251157600080fd5b80820190509050815550600a5461016051111561253057600a54610160525b6003543b61253d57600080fd5b600060006044639dc29fac61018052336101a052610140516101c05261019c60006003545af161256c57600080fd5b60243561016051101515156125c0576308c379a06101805260206101a052600c6101c0527f616d6f756e74203c206d696e00000000000000000000000000000000000000006101e0526101c050606461019cfd5b600a805461016051808210156125d557600080fd5b80820390509050815550610140516101605160025461018052336101a052610160516101c0526101c0516101a05161018051600658016138d6565b6101605261014052600050600a54602061020060246370a0823161018052306101a05261019c6002545afa61264457600080fd5b601f3d1161265157600080fd5b60005061020051101515156126a5576308c379a061022052602061024052600b610260527f62616c203c207661756c740000000000000000000000000000000000000000006102805261026050606461023cfd5b6101405161018052610160516101a052337ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b5686040610180a261016051600052600060145560206000f35b633347b9b28114156127155760065801613e60565b610140526101405160005260206000f35b6367ff0b0681141561273b5760065801613ec1565b610140526101405160005260206000f35b63c5ebeaec811415612a0c576000541515612795576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b6001541515156127e4576308c379a0610140526020610160526006610180527f70617573656400000000000000000000000000000000000000000000000000006101a05261018050606461015cfd5b60045433141515612834576308c379a061014052602061016052600d610180527f2166756e64206d616e61676572000000000000000000000000000000000000006101a05261018050606461015cfd5b6101405160065801613ec1565b6101605261014052610160516101405260043561014051808211156128665780612868565b815b90509050610160526000610160511115156128c2576308c379a06101805260206101a052600a6101c0527f626f72726f77203d2030000000000000000000000000000000000000000000006101e0526101c050606461019cfd5b610140516101605160025461018052336101a052610160516101c0526101c0516101a05161018051600658016138d6565b6101605261014052600050600a8054610160518082101561291357600080fd5b80820390509050815550600b80546101605181818301101561293457600080fd5b80820190509050815550600a54602061020060246370a0823161018052306101a05261019c6002545afa61296757600080fd5b601f3d1161297457600080fd5b60005061020051101515156129c8576308c379a061022052602061024052600b610260527f62616c203c207661756c740000000000000000000000000000000000000000006102805261026050606461023cfd5b60043561018052610160516101a052337fe1979fe4c35e0cef342fef5668e2c8e7a7e9f5d5d1ca8fee0ac6c427fa4153af6040610180a26101605160005260206000f35b63371fd8e6811415612d0d576000541515612a66576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b60045433141515612ab6576308c379a061014052602061016052600d610180527f2166756e64206d616e61676572000000000000000000000000000000000000006101a05261018050606461015cfd5b600435600b5480821115612aca5780612acc565b815b9050905061014052600061014051111515612b26576308c379a06101605260206101805260096101a0527f7265706179203d203000000000000000000000000000000000000000000000006101c0526101a050606461017cfd5b602061020060246370a0823161018052306101a05261019c6002545afa612b4c57600080fd5b601f3d11612b5957600080fd5b6000506102005161016052610140516101605160025461018052336101a052306101c052610140516101e0526101e0516101c0516101a0516101805160065801613a70565b6101605261014052600050602061020060246370a0823161018052306101a05261019c6002545afa612bcf57600080fd5b601f3d11612bdc57600080fd5b600050610200516101605180821015612bf457600080fd5b8082039050905061016052600a805461016051818183011015612c1657600080fd5b80820190509050815550600b80546101605180821015612c3557600080fd5b80820390509050815550600a54602061020060246370a0823161018052306101a05261019c6002545afa612c6857600080fd5b601f3d11612c7557600080fd5b6000506102005110151515612cc9576308c379a061022052602061024052600b610260527f62616c203c207661756c740000000000000000000000000000000000000000006102805261026050606461023cfd5b60043561018052610160516101a052337f77c6871227e5d2dec8dadd5354f78453203e22e669cd0ec4c19d9a8c5edb31d06040610180a26101605160005260206000f35b63753c09858114156130c7576000541515612d67576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b60045433141515612db7576308c379a061014052602061016052600d610180527f2166756e64206d616e61676572000000000000000000000000000000000000006101a05261018050606461015cfd5b6000600435101515612dcc5760243515612dcf565b60005b15612ddb576001612df3565b6004351515612df05760006024351015612df3565b60005b1515612e3e576308c379a0610140526020610160526011610180527f6761696e20616e64206c6f7373203e20300000000000000000000000000000006101a05261018050606461015cfd5b6101405160065801613c4d565b6101605261014052610160516101405260006101605260006004351115612f8b57602061020060246370a0823161018052306101a05261019c6002545afa612e9257600080fd5b601f3d11612e9f57600080fd5b6000506102005161016052610140516101605160025461018052336101a052306101c0526004356101e0526101e0516101c0516101a0516101805160065801613a70565b6101605261014052600050602061020060246370a0823161018052306101a05261019c6002545afa612f1457600080fd5b601f3d11612f2157600080fd5b600050610200516101605180821015612f3957600080fd5b8082039050905061016052600a805461016051818183011015612f5b57600080fd5b808201905090508155506101405161016051818183011015612f7c57600080fd5b80820190509050600e55612fea565b60006024351115612fea57600b805460243580821015612faa57600080fd5b80820390509050815550602435610140511115612fe457600e805460243580821015612fd557600080fd5b80820390509050815550612fea565b6000600e555b42600d55600a54602061020060246370a0823161018052306101a05261019c6002545afa61301757600080fd5b601f3d1161302457600080fd5b6000506102005110151515613078576308c379a061022052602061024052600b610260527f62616c203c207661756c740000000000000000000000000000000000000000006102805261026050606461023cfd5b600a5461018052600b546101a052604060046101c0376101605161020052600e5461022052337f7c7d4c274383cf61f46bee82092136a188e27c566b0857a2d68d01ae1814cdac60c0610180a2005b63d8dad96281141561328b576000541515613121576308c379a061014052602061016052600c610180527f21696e697469616c697a656400000000000000000000000000000000000000006101a05261018050606461015cfd5b600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156131605760018352613170565b8151600101808352811415613144575b5050506101405115156131c2576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b60206101e060246370a0823161016052306101805261017c6002545afa6131e857600080fd5b601f3d116131f557600080fd5b6000506101e05161014052600a5461014051101515613253576308c379a061016052602061018052600c6101a0527f62616c203e3d207661756c7400000000000000000000000000000000000000006101c0526101a050606461017cfd5b61014051600a5561014051610160527f83a5bfe8bda9655fa2e9a9b551f1adb479366b2ee2f537d890c05e9f565837856020610160a1005b631dd19cb481141561338a57600554331415156132e7576308c379a061014052602061016052600a610180527f2174696d65206c6f636b000000000000000000000000000000000000000000006101a05261018050606461015cfd5b6101405161016051610180516101a0516101c0516002546101e052336102005260206101c060246370a0823161014052306101605261015c6002545afa61332d57600080fd5b601f3d1161333a57600080fd5b6000506101c051600a548082101561335157600080fd5b808203905090506102205261022051610200516101e051600658016138d6565b6101c0526101a052610180526101605261014052600050005b6301681a628114156135365760043560a01c156133a657600080fd5b600554610160526008546101805260006101405261014061012060006002818352015b6101205160200261016001513314156133e557600183526133f5565b81516001018083528114156133c9575b505050610140511515613447576308c379a06101a05260206101c05260056101e0527f2161757468000000000000000000000000000000000000000000000000000000610200526101e05060646101bcfd5b6002546004351415151561349a576308c379a0610140526020610160526009610180527f70726f74656374656400000000000000000000000000000000000000000000006101a05261018050606461015cfd5b60206101c060246370a0823161014052306101605261015c6004355afa6134c057600080fd5b601f3d116134cd57600080fd5b6000506101c0516101e0526101405161016051610180516101a0516101c0516101e0516004356102005233610220526101e05161024052610240516102205161020051600658016138d6565b6101e0526101c0526101a052610180526101605261014052600050005b63158ef93e81141561354e5760005460005260206000f35b635c975abb8114156135665760015460005260206000f35b63fc0c546a81141561357e5760025460005260206000f35b63633156378114156135965760035460005260206000f35b636209ec2d8114156135ae5760045460005260206000f35b63d085835a8114156135c65760055460005260206000f35b63b127df878114156135de5760065460005260206000f35b63452a93208114156135f65760075460005260206000f35b63f851a44081141561360e5760085460005260206000f35b63ecf708588114156136265760095460005260206000f35b639994673d81141561363e57600a5460005260206000f35b630dca59c181141561365657600b5460005260206000f35b631b4a200181141561366e57600c5460005260206000f35b63c3535b5281141561368657600d5460005260206000f35b6344b8139681141561369e57600e5460005260206000f35b63422327168114156136b657600f5460005260206000f35b63d98f60888114156136ce5760105460005260206000f35b639b19251a8114156137045760043560a01c156136ea57600080fd5b601160043560e05260c052604060c0205460005260206000f35b630fa1eeab81141561371c5760125460005260206000f35b6392f73fc08114156137345760135460005260206000f35b505b60006000fd5b6101a05261014052610160526101805260006004610220527f095ea7b3000000000000000000000000000000000000000000000000000000006102405261022060048060208461028001018260208501600060045af15050805182019150506101605160208261028001015260208101905061018051602082610280010152602081019050806102805261028090508051602001806103208284600060045af16137e557600080fd5b505060206103e0610320516103406000610140515af161380457600080fd5b60203d808211156138155780613817565b815b905090506103c0526103c08051602001806101c08284600060045af161383c57600080fd5b505060006101c05111156138d0576101c080602001516000825180602090131561386557600080fd5b809190121561387357600080fd5b806020036101000a8204905090509050151515156138d0576308c379a061022052602061024052600e610260527f617070726f7665206661696c65640000000000000000000000000000000000006102805261026050606461023cfd5b6101a051565b6101a05261014052610160526101805260006004610220527fa9059cbb000000000000000000000000000000000000000000000000000000006102405261022060048060208461028001018260208501600060045af15050805182019150506101605160208261028001015260208101905061018051602082610280010152602081019050806102805261028090508051602001806103208284600060045af161397f57600080fd5b505060206103e0610320516103406000610140515af161399e57600080fd5b60203d808211156139af57806139b1565b815b905090506103c0526103c08051602001806101c08284600060045af16139d657600080fd5b505060006101c0511115613a6a576101c08060200151600082518060209013156139ff57600080fd5b8091901215613a0d57600080fd5b806020036101000a820490509050905015151515613a6a576308c379a061022052602061024052600f610260527f7472616e73666572206661696c656400000000000000000000000000000000006102805261026050606461023cfd5b6101a051565b6101c0526101405261016052610180526101a05260006004610240527f23b872dd00000000000000000000000000000000000000000000000000000000610260526102406004806020846102a001018260208501600060045af1505080518201915050610160516020826102a0010152602081019050610180516020826102a00101526020810190506101a0516020826102a0010152602081019050806102a0526102a090508051602001806103608284600060045af1613b3057600080fd5b50506020610440610360516103806000610140515af1613b4f57600080fd5b60203d80821115613b605780613b62565b815b90509050610420526104208051602001806101e08284600060045af1613b8757600080fd5b505060006101e0511115613c1b576101e0806020015160008251806020901315613bb057600080fd5b8091901215613bbe57600080fd5b806020036101000a820490509050905015151515613c1b576308c379a0610240526020610260526013610280527f7472616e7366657246726f6d206661696c6564000000000000000000000000006102a05261028050606461025cfd5b6101c051565b61014052600a54600b54818183011015613c3a57600080fd5b8082019050905060005260005161014051565b6101405242600d5480821015613c6257600080fd5b80820390509050600f548082028215828483041417613c8057600080fd5b8090509050905061016052670de0b6b3a7640000610160511015613d0057600e54610180526101805161016051610180518082028215828483041417613cc557600080fd5b80905090509050670de0b6b3a76400008082049050905080821015613ce957600080fd5b808203905090506000526000516101405156613d0e565b600060005260005161014051565b005b610140526101405160065801613c21565b610160526101405261016051610140516101605160065801613c4d565b6101805261016052610140526101805180821015613d5b57600080fd5b8082039050905060005260005161014051565b6101a052610140526101605261018052610140511515613d965760006000526000516101a051565b610160511515613db057610140516000526000516101a051565b61014051610160518082028215828483041417613dcc57600080fd5b80905090509050610180518080613de257600080fd5b8204905090506000526000516101a051565b6101a052610140526101605261018052610140511515613e1c5760006000526000516101a051565b61014051610180518082028215828483041417613e3857600080fd5b80905090509050610160518080613e4e57600080fd5b8204905090506000526000516101a051565b61014052610140516101605160065801613d10565b610180526101605261014052610180516101605261016051600c548082028215828483041417613ea457600080fd5b809050905090506127108082049050905060005260005161014051565b610140526000541515613ed5576001613ee9565b60015415613ee4576001613ee9565b600454155b15613efc57600060005260005161014051565b610140516101605160065801613e60565b610180526101605261014052610180516101605261016051600a541115613f5557600a546101605180821015613f4257600080fd5b8082039050905060005260005161014051565b60006000526000516101405156

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.