账户
0x3d...2f03
0x3D...2F03

0x3D...2F03

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.3.10+commit.91361694
语言
Vyper
合同源代码
文件 1 的 1:VestSplitter.vy
# @version 0.3.10
"""
@title VestSplitter
@author Curve Finance
@license MIT
@notice Split VestingEscrow for a distribution of users, and accepts donations and top-ups.
        Made originally to compensate victims of Vyper hack, but can be used for other purposes.
"""

from vyper.interfaces import ERC20


interface VestingEscrow:
    def claim(): nonpayable
    def balanceOf(user: address) -> uint256: view


event Claim:
    recipient: indexed(address)
    claimed: uint256


TOKEN: public(immutable(ERC20))
vest: public(VestingEscrow)
ADMIN: public(immutable(address))

fractions: public(HashMap[address, uint256])
total_fraction: public(uint256)
finalized: public(bool)

last_balance: public(uint256)
total_granted: public(uint256)
claimed: public(HashMap[address, uint256])


@external
def __init__(token: ERC20):
    TOKEN = token
    ADMIN = msg.sender  # Only needed before the distribution is finalized


@external
def set_vest(vest: VestingEscrow):
    assert msg.sender == ADMIN, "Access"
    assert self.vest == empty(VestingEscrow), "Vest already set"
    self.vest = vest


@external
def save_distribution(users: DynArray[address, 200], fractions: DynArray[uint256, 200]):
    assert msg.sender == ADMIN, "Access"
    assert not self.finalized, "Distribution is finalized already"

    for i in range(200):
        if i >= len(users):
            break
        user: address = users[i]
        f_old: uint256 = self.fractions[user]
        f: uint256 = fractions[i]

        self.fractions[user] = f
        self.total_fraction = self.total_fraction + f - f_old


@external
def finalize_distribution():
    assert msg.sender == ADMIN, "Access"
    self.finalized = True


@external
@nonreentrant('lock')
def claim(user: address = msg.sender, use_vest: bool = True):
    vest: VestingEscrow = self.vest
    if use_vest and vest != empty(VestingEscrow) and vest != VestingEscrow(self):
        vest.claim()
    total_granted: uint256 = self.total_granted + (TOKEN.balanceOf(self) - self.last_balance)
    self.total_granted = total_granted

    total_for_user: uint256 = total_granted * self.fractions[user] / self.total_fraction
    to_send: uint256 = total_for_user - self.claimed[user]
    self.claimed[user] = total_for_user
    TOKEN.transfer(user, to_send)

    self.last_balance = TOKEN.balanceOf(self)

    log Claim(user, to_send)


@external
@view
def balanceOf(user: address, use_vest: bool = True) -> uint256:
    total_granted: uint256 = self.total_granted
    vest: VestingEscrow = self.vest
    if use_vest and vest != empty(VestingEscrow) and vest != VestingEscrow(self):
        total_granted += vest.balanceOf(self)
    total_granted = total_granted + TOKEN.balanceOf(self) - self.last_balance
    total_for_user: uint256 = total_granted * self.fractions[user] / self.total_fraction
    return total_for_user - self.claimed[user]
设置
{
  "compilationTarget": {
    "VestSplitter.vy": "VestSplitter"
  },
  "outputSelection": {
    "VestSplitter.vy": [
      "abi",
      "ast",
      "interface",
      "ir",
      "userdoc",
      "devdoc",
      "evm.bytecode.object",
      "evm.bytecode.opcodes",
      "evm.deployedBytecode.object",
      "evm.deployedBytecode.opcodes",
      "evm.deployedBytecode.sourceMap",
      "evm.methodIdentifiers"
    ]
  },
  "search_paths": [
    "."
  ]
}
ABI
[{"anonymous":false,"inputs":[{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"claimed","type":"uint256"}],"name":"Claim","type":"event"},{"inputs":[{"name":"token","type":"address"}],"outputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"name":"vest","type":"address"}],"name":"set_vest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"users","type":"address[]"},{"name":"fractions","type":"uint256[]"}],"name":"save_distribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalize_distribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"user","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"user","type":"address"},{"name":"use_vest","type":"bool"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"user","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"user","type":"address"},{"name":"use_vest","type":"bool"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vest","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ADMIN","outputs":[{"name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"arg0","type":"address"}],"name":"fractions","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_fraction","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finalized","outputs":[{"name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"last_balance","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_granted","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"arg0","type":"address"}],"name":"claimed","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]