ETH Price: $3,448.86 (-0.77%)
Gas: 3 Gwei

Contract

0xB088D7C71ea9eBAed981c103Fc3019B59950d2C9
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw184225842023-10-24 20:45:35273 days ago1698180335IN
0xB088D7C7...59950d2C9
0 ETH0.0020590622
Withdraw167630522023-03-05 15:21:47506 days ago1678029707IN
0xB088D7C7...59950d2C9
0 ETH0.0026206328
Withdraw166827222023-02-22 8:11:35517 days ago1677053495IN
0xB088D7C7...59950d2C9
0 ETH0.0064579869
Withdraw158579102022-10-30 2:32:35633 days ago1667097155IN
0xB088D7C7...59950d2C9
0 ETH0.000748948
Withdraw154722542022-09-04 14:56:36688 days ago1662303396IN
0xB088D7C7...59950d2C9
0 ETH0.0011650911
Withdraw154410852022-08-30 15:14:07693 days ago1661872447IN
0xB088D7C7...59950d2C9
0 ETH0.0022576524.85993482
Withdraw154320072022-08-29 4:24:26694 days ago1661747066IN
0xB088D7C7...59950d2C9
0 ETH0.000544896
Withdraw153649462022-08-18 12:16:51705 days ago1660825011IN
0xB088D7C7...59950d2C9
0 ETH0.0009081510
Withdraw150435862022-06-29 6:01:24755 days ago1656482484IN
0xB088D7C7...59950d2C9
0 ETH0.0022237721
Withdraw150274712022-06-26 5:37:36758 days ago1656221856IN
0xB088D7C7...59950d2C9
0 ETH0.0014886816.39426639
Withdraw149683312022-06-15 15:57:39769 days ago1655308659IN
0xB088D7C7...59950d2C9
0 ETH0.0099043793.50980981
Withdraw149522132022-06-12 20:53:42772 days ago1655067222IN
0xB088D7C7...59950d2C9
0 ETH0.0024521223.15641256
Withdraw149312842022-06-09 7:09:20775 days ago1654758560IN
0xB088D7C7...59950d2C9
0 ETH0.0032914236.24322523
Set Pause148851672022-06-01 13:55:04783 days ago1654091704IN
0xB088D7C7...59950d2C9
0 ETH0.0027089452.78938424
Set Pause144977522022-04-01 2:41:23845 days ago1648780883IN
0xB088D7C7...59950d2C9
0 ETH0.0031235460.86892698
Withdraw144717022022-03-28 1:20:01849 days ago1648430401IN
0xB088D7C7...59950d2C9
0 ETH0.019595320
Withdraw143699932022-03-12 5:08:14864 days ago1647061694IN
0xB088D7C7...59950d2C9
0 ETH0.0015791217.05239966
Deposit143624222022-03-11 0:44:14866 days ago1646959454IN
0xB088D7C7...59950d2C9
0 ETH0.0051285736.45377643
Withdraw142091722022-02-15 6:37:40889 days ago1644907060IN
0xB088D7C7...59950d2C9
0 ETH0.031356333
Withdraw141968242022-02-13 8:47:49891 days ago1644742069IN
0xB088D7C7...59950d2C9
0 ETH0.0031785235
Withdraw141840332022-02-11 9:52:17893 days ago1644573137IN
0xB088D7C7...59950d2C9
0 ETH0.0035410439
Withdraw141820832022-02-11 2:34:04894 days ago1644546844IN
0xB088D7C7...59950d2C9
0 ETH0.0070948967
Deposit141525262022-02-06 12:29:34898 days ago1644150574IN
0xB088D7C7...59950d2C9
0 ETH0.0068803348.89690693
Withdraw141521882022-02-06 11:18:55898 days ago1644146335IN
0xB088D7C7...59950d2C9
0 ETH0.0039675643.69754522
Withdraw141377622022-02-04 6:00:48900 days ago1643954448IN
0xB088D7C7...59950d2C9
0 ETH0.0058056862.69364134
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.