# TellerWithMultiAssetSupport

[Git Source](https://github.com/Ion-Protocol/nucleus-boring-vault/blob/cc0b494b83e17b9b169a73b96050d2810b690477/src/base/Roles/TellerWithMultiAssetSupport.sol)

**Inherits:** Auth, BeforeTransferHook, ReentrancyGuard

## State Variables

### NATIVE

Native address used to tell the contract to handle native asset deposits.

```solidity
address internal constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
```

### MAX\_SHARE\_LOCK\_PERIOD

The maximum possible share lock period.

```solidity
uint256 internal constant MAX_SHARE_LOCK_PERIOD = 3 days;
```

### isSupported

Mapping ERC20s to an isSupported bool.

```solidity
mapping(ERC20 => bool) public isSupported;
```

### depositNonce

The deposit nonce used to map to a deposit hash.

```solidity
uint96 public depositNonce = 1;
```

### shareLockPeriod

After deposits, shares are locked to the msg.sender's address for `shareLockPeriod`.

*During this time all transfers from msg.sender will revert, and deposits are refundable.*

```solidity
uint64 public shareLockPeriod;
```

### isPaused

Used to pause calls to `deposit` and `depositWithPermit`.

```solidity
bool public isPaused;
```

### publicDepositHistory

*Maps deposit nonce to keccak256(address receiver, address depositAsset, uint256 depositAmount, uint256 shareAmount, uint256 timestamp, uint256 shareLockPeriod).*

```solidity
mapping(uint256 => bytes32) public publicDepositHistory;
```

### shareUnlockTime

Maps user address to the time their shares will be unlocked.

```solidity
mapping(address => uint256) public shareUnlockTime;
```

### vault

The BoringVault this contract is working with.

```solidity
BoringVault public immutable vault;
```

### accountant

The AccountantWithRateProviders this contract is working with.

```solidity
AccountantWithRateProviders public immutable accountant;
```

### ONE\_SHARE

One share of the BoringVault.

```solidity
uint256 internal immutable ONE_SHARE;
```

## Functions

### constructor

```solidity
constructor(address _owner, address _vault, address _accountant) Auth(_owner, Authority(address(0)));
```

### pause

Pause this contract, which prevents future calls to `deposit` and `depositWithPermit`.

*Callable by MULTISIG\_ROLE.*

```solidity
function pause() external requiresAuth;
```

### unpause

Unpause this contract, which allows future calls to `deposit` and `depositWithPermit`.

*Callable by MULTISIG\_ROLE.*

```solidity
function unpause() external requiresAuth;
```

### addAsset

Adds this asset as a deposit asset.

*The accountant must also support pricing this asset, else the `deposit` call will revert.*

*Callable by OWNER\_ROLE.*

```solidity
function addAsset(ERC20 asset) external requiresAuth;
```

### removeAsset

Removes this asset as a deposit asset.

*Callable by OWNER\_ROLE.*

```solidity
function removeAsset(ERC20 asset) external requiresAuth;
```

### setShareLockPeriod

Sets the share lock period.

*This not only locks shares to the user address, but also serves as the pending deposit period, where deposits can be reverted.*

*If a new shorter share lock period is set, users with pending share locks could make a new deposit to receive 1 wei shares, and have their shares unlock sooner than their original deposit allows. This state would allow for the user deposit to be refunded, but only if they have not transferred their shares out of there wallet. This is an accepted limitation, and should be known when decreasing the share lock period.*

*Callable by OWNER\_ROLE.*

```solidity
function setShareLockPeriod(uint64 _shareLockPeriod) external requiresAuth;
```

### beforeTransfer

Implement beforeTransfer hook to check if shares are locked.

```solidity
function beforeTransfer(address from) public view;
```

### refundDeposit

Allows DEPOSIT\_REFUNDER\_ROLE to revert a pending deposit.

*Once a deposit share lock period has passed, it can no longer be reverted.*

*It is possible the admin does not setup the BoringVault to call the transfer hook, but this contract can still be saving share lock state. In the event this happens deposits are still refundable if the user has not transferred their shares. But there is no guarantee that the user has not transferred their shares.*

*Callable by STRATEGIST\_MULTISIG\_ROLE.*

```solidity
function refundDeposit(
    uint256 nonce,
    address receiver,
    address depositAsset,
    uint256 depositAmount,
    uint256 shareAmount,
    uint256 depositTimestamp,
    uint256 shareLockUpPeriodAtTimeOfDeposit
)
    external
    requiresAuth;
```

### deposit

Allows users to deposit into the BoringVault, if this contract is not paused.

*Publicly callable.*

```solidity
function deposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint
)
    external
    requiresAuth
    nonReentrant
    returns (uint256 shares);
```

### depositWithPermit

Allows users to deposit into BoringVault using permit.

*Publicly callable.*

```solidity
function depositWithPermit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
)
    external
    requiresAuth
    nonReentrant
    returns (uint256 shares);
```

### bulkDeposit

Allows on ramp role to deposit into this contract.

*Does NOT support native deposits.*

*Callable by SOLVER\_ROLE.*

```solidity
function bulkDeposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    address to
)
    external
    requiresAuth
    nonReentrant
    returns (uint256 shares);
```

### bulkWithdraw

Allows off ramp role to withdraw from this contract.

*Callable by SOLVER\_ROLE.*

```solidity
function bulkWithdraw(
    ERC20 withdrawAsset,
    uint256 shareAmount,
    uint256 minimumAssets,
    address to
)
    external
    requiresAuth
    returns (uint256 assetsOut);
```

### \_erc20Deposit

Implements a common ERC20 deposit into BoringVault.

```solidity
function _erc20Deposit(
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 minimumMint,
    address to
)
    internal
    returns (uint256 shares);
```

### \_afterPublicDeposit

Handle share lock logic, and event.

```solidity
function _afterPublicDeposit(
    address user,
    ERC20 depositAsset,
    uint256 depositAmount,
    uint256 shares,
    uint256 currentShareLockPeriod
)
    internal;
```

## Events

### Paused

```solidity
event Paused();
```

### Unpaused

```solidity
event Unpaused();
```

### AssetAdded

```solidity
event AssetAdded(address indexed asset);
```

### AssetRemoved

```solidity
event AssetRemoved(address indexed asset);
```

### Deposit

```solidity
event Deposit(
    uint256 indexed nonce,
    address indexed receiver,
    address indexed depositAsset,
    uint256 depositAmount,
    uint256 shareAmount,
    uint256 depositTimestamp,
    uint256 shareLockPeriodAtTimeOfDeposit
);
```

### BulkDeposit

```solidity
event BulkDeposit(address indexed asset, uint256 depositAmount);
```

### BulkWithdraw

```solidity
event BulkWithdraw(address indexed asset, uint256 shareAmount);
```

### DepositRefunded

```solidity
event DepositRefunded(uint256 indexed nonce, bytes32 depositHash, address indexed user);
```

## Errors

### TellerWithMultiAssetSupport\_\_ShareLockPeriodTooLong

```solidity
error TellerWithMultiAssetSupport__ShareLockPeriodTooLong();
```

### TellerWithMultiAssetSupport\_\_SharesAreLocked

```solidity
error TellerWithMultiAssetSupport__SharesAreLocked();
```

### TellerWithMultiAssetSupport\_\_SharesAreUnLocked

```solidity
error TellerWithMultiAssetSupport__SharesAreUnLocked();
```

### TellerWithMultiAssetSupport\_\_BadDepositHash

```solidity
error TellerWithMultiAssetSupport__BadDepositHash();
```

### TellerWithMultiAssetSupport\_\_AssetNotSupported

```solidity
error TellerWithMultiAssetSupport__AssetNotSupported();
```

### TellerWithMultiAssetSupport\_\_ZeroAssets

```solidity
error TellerWithMultiAssetSupport__ZeroAssets();
```

### TellerWithMultiAssetSupport\_\_MinimumMintNotMet

```solidity
error TellerWithMultiAssetSupport__MinimumMintNotMet();
```

### TellerWithMultiAssetSupport\_\_MinimumAssetsNotMet

```solidity
error TellerWithMultiAssetSupport__MinimumAssetsNotMet();
```

### TellerWithMultiAssetSupport\_\_PermitFailedAndAllowanceTooLow

```solidity
error TellerWithMultiAssetSupport__PermitFailedAndAllowanceTooLow();
```

### TellerWithMultiAssetSupport\_\_ZeroShares

```solidity
error TellerWithMultiAssetSupport__ZeroShares();
```

### TellerWithMultiAssetSupport\_\_Paused

```solidity
error TellerWithMultiAssetSupport__Paused();
```
