mirror of
https://github.com/logos-storage/logos-storage-contracts-eth.git
synced 2026-01-04 06:13:09 +00:00
vault: rename Fund -> FundId
This commit is contained in:
parent
62aea75295
commit
2900bed8fd
@ -62,64 +62,67 @@ contract Vault is VaultBase, Pausable, Ownable {
|
||||
/// Extracts the address of the account holder and the discriminator from the
|
||||
/// account id.
|
||||
function decodeAccountId(
|
||||
AccountId account
|
||||
AccountId id
|
||||
) public pure returns (address holder, bytes12 discriminator) {
|
||||
return Accounts.decodeId(account);
|
||||
return Accounts.decodeId(id);
|
||||
}
|
||||
|
||||
/// The amount of tokens that are currently in an account.
|
||||
/// This includes available and designated tokens. Available tokens can be
|
||||
/// transfered to other accounts, but designated tokens cannot.
|
||||
function getBalance(Fund fund, AccountId id) public view returns (uint128) {
|
||||
function getBalance(
|
||||
FundId fundId,
|
||||
AccountId accountId
|
||||
) public view returns (uint128) {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
Balance memory balance = _getBalance(controller, fund, id);
|
||||
Balance memory balance = _getBalance(controller, fundId, accountId);
|
||||
return balance.available + balance.designated;
|
||||
}
|
||||
|
||||
/// The amount of tokens that are currently designated in an account
|
||||
/// These tokens can no longer be transfered to other accounts.
|
||||
function getDesignatedBalance(
|
||||
Fund fund,
|
||||
AccountId id
|
||||
FundId fundId,
|
||||
AccountId accountId
|
||||
) public view returns (uint128) {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
Balance memory balance = _getBalance(controller, fund, id);
|
||||
Balance memory balance = _getBalance(controller, fundId, accountId);
|
||||
return balance.designated;
|
||||
}
|
||||
|
||||
/// Returns the status of the lock on the fund. Most operations on the vault
|
||||
/// can only be done by the controller when the funds are locked. Withdrawal
|
||||
/// can only be done when the funds are unlocked.
|
||||
function getLockStatus(Fund fund) public view returns (LockStatus) {
|
||||
function getLockStatus(FundId fundId) public view returns (LockStatus) {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
return _getLockStatus(controller, fund);
|
||||
return _getLockStatus(controller, fundId);
|
||||
}
|
||||
|
||||
/// Returns the expiry time of the lock on the fund. A locked fund unlocks
|
||||
/// automatically at this timestamp.
|
||||
function getLockExpiry(Fund fund) public view returns (Timestamp) {
|
||||
function getLockExpiry(FundId fundId) public view returns (Timestamp) {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
return _getLockExpiry(controller, fund);
|
||||
return _getLockExpiry(controller, fundId);
|
||||
}
|
||||
|
||||
/// Locks the fund until the expiry timestamp. The lock expiry can be extended
|
||||
/// later, but no more than the maximum timestamp.
|
||||
function lock(
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
Timestamp expiry,
|
||||
Timestamp maximum
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_lock(controller, fund, expiry, maximum);
|
||||
_lock(controller, fundId, expiry, maximum);
|
||||
}
|
||||
|
||||
/// Delays unlocking of a locked fund. The new expiry should be later than
|
||||
/// the existing expiry, but no later than the maximum timestamp that was
|
||||
/// provided when locking the fund.
|
||||
/// Only allowed when the lock has not unlocked yet.
|
||||
function extendLock(Fund fund, Timestamp expiry) public whenNotPaused {
|
||||
function extendLock(FundId fundId, Timestamp expiry) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_extendLock(controller, fund, expiry);
|
||||
_extendLock(controller, fundId, expiry);
|
||||
}
|
||||
|
||||
/// Deposits an amount of tokens into the vault, and adds them to the balance
|
||||
@ -127,12 +130,12 @@ contract Vault is VaultBase, Pausable, Ownable {
|
||||
/// contract.
|
||||
/// Only allowed when the fund is locked.
|
||||
function deposit(
|
||||
Fund fund,
|
||||
AccountId id,
|
||||
FundId fundId,
|
||||
AccountId accountId,
|
||||
uint128 amount
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_deposit(controller, fund, id, amount);
|
||||
_deposit(controller, fundId, accountId, amount);
|
||||
}
|
||||
|
||||
/// Takes an amount of tokens from the account balance and designates them
|
||||
@ -140,24 +143,24 @@ contract Vault is VaultBase, Pausable, Ownable {
|
||||
/// transfered to other accounts.
|
||||
/// Only allowed when the fund is locked.
|
||||
function designate(
|
||||
Fund fund,
|
||||
AccountId id,
|
||||
FundId fundId,
|
||||
AccountId accountId,
|
||||
uint128 amount
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_designate(controller, fund, id, amount);
|
||||
_designate(controller, fundId, accountId, amount);
|
||||
}
|
||||
|
||||
/// Transfers an amount of tokens from one account to the other.
|
||||
/// Only allowed when the fund is locked.
|
||||
function transfer(
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
AccountId from,
|
||||
AccountId to,
|
||||
uint128 amount
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_transfer(controller, fund, from, to, amount);
|
||||
_transfer(controller, fundId, from, to, amount);
|
||||
}
|
||||
|
||||
/// Transfers tokens from one account the other over time.
|
||||
@ -168,40 +171,43 @@ contract Vault is VaultBase, Pausable, Ownable {
|
||||
/// Only allowed when the balance is sufficient to sustain the flow until the
|
||||
/// fund unlocks, even if the lock expiry time is extended to its maximum.
|
||||
function flow(
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
AccountId from,
|
||||
AccountId to,
|
||||
TokensPerSecond rate
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_flow(controller, fund, from, to, rate);
|
||||
_flow(controller, fundId, from, to, rate);
|
||||
}
|
||||
|
||||
/// Burns an amount of designated tokens from the account.
|
||||
/// Only allowed when the fund is locked.
|
||||
function burnDesignated(
|
||||
Fund fund,
|
||||
AccountId account,
|
||||
FundId fundId,
|
||||
AccountId accountId,
|
||||
uint128 amount
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_burnDesignated(controller, fund, account, amount);
|
||||
_burnDesignated(controller, fundId, accountId, amount);
|
||||
}
|
||||
|
||||
/// Burns all tokens from the account.
|
||||
/// Only allowed when the fund is locked.
|
||||
/// Only allowed when no funds are flowing into or out of the account.
|
||||
function burnAccount(Fund fund, AccountId account) public whenNotPaused {
|
||||
function burnAccount(
|
||||
FundId fundId,
|
||||
AccountId accountId
|
||||
) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_burnAccount(controller, fund, account);
|
||||
_burnAccount(controller, fundId, accountId);
|
||||
}
|
||||
|
||||
/// Freezes a fund. Stops all tokens flows and disallows any operations on the
|
||||
/// fund until it unlocks.
|
||||
/// Only allowed when the fund is locked.
|
||||
function freezeFund(Fund fund) public whenNotPaused {
|
||||
function freezeFund(FundId fundId) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_freezeFund(controller, fund);
|
||||
_freezeFund(controller, fundId);
|
||||
}
|
||||
|
||||
/// Transfers all ERC20 tokens in the account out of the vault to the account
|
||||
@ -210,9 +216,9 @@ contract Vault is VaultBase, Pausable, Ownable {
|
||||
/// ⚠️ The account holder can also withdraw itself, so when designing a smart
|
||||
/// contract that controls funds in the vault, don't assume that only this
|
||||
/// smart contract can initiate a withdrawal ⚠️
|
||||
function withdraw(Fund fund, AccountId account) public whenNotPaused {
|
||||
function withdraw(FundId fund, AccountId accountId) public whenNotPaused {
|
||||
Controller controller = Controller.wrap(msg.sender);
|
||||
_withdraw(controller, fund, account);
|
||||
_withdraw(controller, fund, accountId);
|
||||
}
|
||||
|
||||
/// Allows an account holder to withdraw its tokens from a fund directly,
|
||||
@ -221,12 +227,12 @@ contract Vault is VaultBase, Pausable, Ownable {
|
||||
/// Only allowed when the fund is unlocked.
|
||||
function withdrawByRecipient(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
AccountId account
|
||||
FundId fund,
|
||||
AccountId accountId
|
||||
) public {
|
||||
(address holder, ) = Accounts.decodeId(account);
|
||||
(address holder, ) = Accounts.decodeId(accountId);
|
||||
require(msg.sender == holder, VaultOnlyAccountHolder());
|
||||
_withdraw(controller, fund, account);
|
||||
_withdraw(controller, fund, accountId);
|
||||
}
|
||||
|
||||
function pause() public onlyOwner {
|
||||
|
||||
@ -17,14 +17,14 @@ import "./Locks.sol";
|
||||
/// The lock invariant ensures that there is a maximum time that a fund can be
|
||||
/// locked:
|
||||
///
|
||||
/// (∀ controller ∈ Controller, fund ∈ Fund:
|
||||
/// (∀ controller ∈ Controller, fund ∈ FundId:
|
||||
/// lock.expiry <= lock.maximum
|
||||
/// where lock = _locks[controller][fund])
|
||||
///
|
||||
/// The account invariant ensures that the outgoing token flow can be sustained
|
||||
/// for the maximum time that a fund can be locked:
|
||||
///
|
||||
/// (∀ controller ∈ Controller, fund ∈ Fund, account ∈ AccountId:
|
||||
/// (∀ controller ∈ Controller, fund ∈ FundId, account ∈ AccountId:
|
||||
/// flow.outgoing * (lock.maximum - flow.updated) <= balance.available
|
||||
/// where lock = _locks[controller][fund])
|
||||
/// and flow = _accounts[controller][fund][account].flow
|
||||
@ -32,7 +32,7 @@ import "./Locks.sol";
|
||||
///
|
||||
/// The flow invariant ensures that incoming and outgoing flow rates match:
|
||||
///
|
||||
/// (∀ controller ∈ Controller, fund ∈ Fund:
|
||||
/// (∀ controller ∈ Controller, fund ∈ FundId:
|
||||
/// (∑ account ∈ AccountId: accounts[account].flow.incoming) =
|
||||
/// (∑ account ∈ AccountId: accounts[account].flow.outgoing)
|
||||
/// where accounts = _accounts[controller][fund])
|
||||
@ -47,12 +47,12 @@ abstract contract VaultBase {
|
||||
/// Represents a smart contract that can redistribute and burn tokens in funds
|
||||
type Controller is address;
|
||||
/// Unique identifier for a fund, chosen by the controller
|
||||
type Fund is bytes32;
|
||||
type FundId is bytes32;
|
||||
|
||||
/// Each fund has its own time lock
|
||||
mapping(Controller => mapping(Fund => Lock)) private _locks;
|
||||
mapping(Controller => mapping(FundId => Lock)) private _locks;
|
||||
/// Each account holder has its own set of accounts in a fund
|
||||
mapping(Controller => mapping(Fund => mapping(AccountId => Account)))
|
||||
mapping(Controller => mapping(FundId => mapping(AccountId => Account)))
|
||||
private _accounts;
|
||||
|
||||
constructor(IERC20 token) {
|
||||
@ -61,32 +61,32 @@ abstract contract VaultBase {
|
||||
|
||||
function _getLockStatus(
|
||||
Controller controller,
|
||||
Fund fund
|
||||
FundId fundId
|
||||
) internal view returns (LockStatus) {
|
||||
return _locks[controller][fund].status();
|
||||
return _locks[controller][fundId].status();
|
||||
}
|
||||
|
||||
function _getLockExpiry(
|
||||
Controller controller,
|
||||
Fund fund
|
||||
FundId fundId
|
||||
) internal view returns (Timestamp) {
|
||||
return _locks[controller][fund].expiry;
|
||||
return _locks[controller][fundId].expiry;
|
||||
}
|
||||
|
||||
function _getBalance(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
AccountId id
|
||||
FundId fundId,
|
||||
AccountId accountId
|
||||
) internal view returns (Balance memory) {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
LockStatus lockStatus = lock.status();
|
||||
if (lockStatus == LockStatus.Locked) {
|
||||
Account memory account = _accounts[controller][fund][id];
|
||||
Account memory account = _accounts[controller][fundId][accountId];
|
||||
account.update(Timestamps.currentTime());
|
||||
return account.balance;
|
||||
}
|
||||
if (lockStatus == LockStatus.Unlocked || lockStatus == LockStatus.Frozen) {
|
||||
Account memory account = _accounts[controller][fund][id];
|
||||
Account memory account = _accounts[controller][fundId][accountId];
|
||||
account.update(lock.flowEnd());
|
||||
return account.balance;
|
||||
}
|
||||
@ -95,41 +95,41 @@ abstract contract VaultBase {
|
||||
|
||||
function _lock(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
Timestamp expiry,
|
||||
Timestamp maximum
|
||||
) internal {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.NoLock, VaultFundAlreadyLocked());
|
||||
lock.expiry = expiry;
|
||||
lock.maximum = maximum;
|
||||
_checkLockInvariant(lock);
|
||||
_locks[controller][fund] = lock;
|
||||
_locks[controller][fundId] = lock;
|
||||
}
|
||||
|
||||
function _extendLock(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
Timestamp expiry
|
||||
) internal {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
require(lock.expiry <= expiry, VaultInvalidExpiry());
|
||||
lock.expiry = expiry;
|
||||
_checkLockInvariant(lock);
|
||||
_locks[controller][fund] = lock;
|
||||
_locks[controller][fundId] = lock;
|
||||
}
|
||||
|
||||
function _deposit(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
AccountId id,
|
||||
FundId fundId,
|
||||
AccountId accountId,
|
||||
uint128 amount
|
||||
) internal {
|
||||
Lock storage lock = _locks[controller][fund];
|
||||
Lock storage lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
Account storage account = _accounts[controller][fund][id];
|
||||
Account storage account = _accounts[controller][fundId][accountId];
|
||||
|
||||
account.balance.available += amount;
|
||||
lock.value += amount;
|
||||
@ -143,74 +143,74 @@ abstract contract VaultBase {
|
||||
|
||||
function _designate(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
AccountId id,
|
||||
FundId fundId,
|
||||
AccountId accountId,
|
||||
uint128 amount
|
||||
) internal {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
Account memory account = _accounts[controller][fund][id];
|
||||
Account memory account = _accounts[controller][fundId][accountId];
|
||||
require(amount <= account.balance.available, VaultInsufficientBalance());
|
||||
|
||||
account.balance.available -= amount;
|
||||
account.balance.designated += amount;
|
||||
_checkAccountInvariant(account, lock);
|
||||
|
||||
_accounts[controller][fund][id] = account;
|
||||
_accounts[controller][fundId][accountId] = account;
|
||||
}
|
||||
|
||||
function _transfer(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
AccountId from,
|
||||
AccountId to,
|
||||
uint128 amount
|
||||
) internal {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
Account memory sender = _accounts[controller][fund][from];
|
||||
Account memory sender = _accounts[controller][fundId][from];
|
||||
require(amount <= sender.balance.available, VaultInsufficientBalance());
|
||||
|
||||
sender.balance.available -= amount;
|
||||
_checkAccountInvariant(sender, lock);
|
||||
|
||||
_accounts[controller][fund][from] = sender;
|
||||
_accounts[controller][fundId][from] = sender;
|
||||
|
||||
_accounts[controller][fund][to].balance.available += amount;
|
||||
_accounts[controller][fundId][to].balance.available += amount;
|
||||
}
|
||||
|
||||
function _flow(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
FundId fundId,
|
||||
AccountId from,
|
||||
AccountId to,
|
||||
TokensPerSecond rate
|
||||
) internal {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
Account memory sender = _accounts[controller][fund][from];
|
||||
Account memory sender = _accounts[controller][fundId][from];
|
||||
sender.flowOut(rate);
|
||||
_checkAccountInvariant(sender, lock);
|
||||
_accounts[controller][fund][from] = sender;
|
||||
_accounts[controller][fundId][from] = sender;
|
||||
|
||||
Account memory receiver = _accounts[controller][fund][to];
|
||||
Account memory receiver = _accounts[controller][fundId][to];
|
||||
receiver.flowIn(rate);
|
||||
_accounts[controller][fund][to] = receiver;
|
||||
_accounts[controller][fundId][to] = receiver;
|
||||
}
|
||||
|
||||
function _burnDesignated(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
AccountId id,
|
||||
FundId fundId,
|
||||
AccountId accountId,
|
||||
uint128 amount
|
||||
) internal {
|
||||
Lock storage lock = _locks[controller][fund];
|
||||
Lock storage lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
Account storage account = _accounts[controller][fund][id];
|
||||
Account storage account = _accounts[controller][fundId][accountId];
|
||||
require(account.balance.designated >= amount, VaultInsufficientBalance());
|
||||
|
||||
account.balance.designated -= amount;
|
||||
@ -222,49 +222,53 @@ abstract contract VaultBase {
|
||||
|
||||
function _burnAccount(
|
||||
Controller controller,
|
||||
Fund fund,
|
||||
AccountId id
|
||||
FundId fundId,
|
||||
AccountId accountId
|
||||
) internal {
|
||||
Lock storage lock = _locks[controller][fund];
|
||||
Lock storage lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
Account memory account = _accounts[controller][fund][id];
|
||||
Account memory account = _accounts[controller][fundId][accountId];
|
||||
require(account.flow.incoming == account.flow.outgoing, VaultFlowNotZero());
|
||||
uint128 amount = account.balance.available + account.balance.designated;
|
||||
|
||||
lock.value -= amount;
|
||||
|
||||
delete _accounts[controller][fund][id];
|
||||
delete _accounts[controller][fundId][accountId];
|
||||
|
||||
_token.safeTransfer(address(0xdead), amount);
|
||||
}
|
||||
|
||||
function _freezeFund(Controller controller, Fund fund) internal {
|
||||
Lock storage lock = _locks[controller][fund];
|
||||
function _freezeFund(Controller controller, FundId fundId) internal {
|
||||
Lock storage lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Locked, VaultFundNotLocked());
|
||||
|
||||
lock.frozenAt = Timestamps.currentTime();
|
||||
}
|
||||
|
||||
function _withdraw(Controller controller, Fund fund, AccountId id) internal {
|
||||
Lock memory lock = _locks[controller][fund];
|
||||
function _withdraw(
|
||||
Controller controller,
|
||||
FundId fundId,
|
||||
AccountId accountId
|
||||
) internal {
|
||||
Lock memory lock = _locks[controller][fundId];
|
||||
require(lock.status() == LockStatus.Unlocked, VaultFundNotUnlocked());
|
||||
|
||||
Account memory account = _accounts[controller][fund][id];
|
||||
Account memory account = _accounts[controller][fundId][accountId];
|
||||
account.update(lock.flowEnd());
|
||||
uint128 amount = account.balance.available + account.balance.designated;
|
||||
|
||||
lock.value -= amount;
|
||||
|
||||
if (lock.value == 0) {
|
||||
delete _locks[controller][fund];
|
||||
delete _locks[controller][fundId];
|
||||
} else {
|
||||
_locks[controller][fund] = lock;
|
||||
_locks[controller][fundId] = lock;
|
||||
}
|
||||
|
||||
delete _accounts[controller][fund][id];
|
||||
delete _accounts[controller][fundId][accountId];
|
||||
|
||||
(address owner, ) = Accounts.decodeId(id);
|
||||
(address owner, ) = Accounts.decodeId(accountId);
|
||||
_token.safeTransfer(owner, amount);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user