Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ungaro committed Dec 26, 2024
1 parent cd05a5e commit 63d533e
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 99 deletions.
7 changes: 4 additions & 3 deletions nest/src/interfaces/IBoringVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
pragma solidity ^0.8.25;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

interface IBoringVault is IERC20, IERC20Metadata {
interface IBoringVault is IERC20 {

/**
* @notice Deposits assets into the vault in exchange for shares
Expand All @@ -26,4 +25,6 @@ interface IBoringVault is IERC20, IERC20Metadata {
*/
function exit(address to, address asset, uint256 assetAmount, address from, uint256 shareAmount) external;

}
// ERC20 interface functions
function decimals() external view returns (uint8);
}
169 changes: 93 additions & 76 deletions nest/src/mocks/MockVault.sol
Original file line number Diff line number Diff line change
@@ -1,117 +1,134 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import { ERC20 } from "@solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "@solmate/utils/SafeTransferLib.sol";
import { Auth, Authority } from "@solmate/auth/Auth.sol";

import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import { IBoringVault } from "../interfaces/IBoringVault.sol";
import { BeforeTransferHook } from "@boringvault/src/interfaces/BeforeTransferHook.sol";

contract MockVault is ERC20, Auth, ERC721Holder, ERC1155Holder, IBoringVault {

using SafeERC20 for IERC20;
contract MockVault is IBoringVault, Auth, ERC721Holder, ERC1155Holder {
using SafeTransferLib for ERC20;

// token => account => balance
mapping(address => mapping(address => uint256)) private _balances;
// State variables
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
BeforeTransferHook public hook;

mapping(address => mapping(address => mapping(address => uint256))) private _allowances;
// Events
event DebugCall(string functionName, bytes data);
event Enter(address indexed from, address indexed asset, uint256 amount, address indexed to, uint256 shares);
event Exit(address indexed to, address indexed asset, uint256 amount, address indexed from, uint256 shares);

IERC20 public asset;
IERC20 public immutable usdc;
IERC20 public immutable usdt;
address public beforeTransferHook;

constructor(
constructor(
address _owner,
string memory _name,
string memory _symbol,
address _usdc
) ERC20(_name, _symbol) Auth(_owner, Authority(address(0))) {
usdc = IERC20(_usdc);
uint8 _decimals
) Auth(_owner, Authority(address(0))) {
name = _name;
symbol = _symbol;
decimals = _decimals;
}

function enter(address from, address asset_, uint256 assetAmount, address to, uint256 shareAmount) external {
if (assetAmount > 0) {
IERC20(asset_).safeTransferFrom(from, address(this), assetAmount);
}
_balances[asset_][to] += shareAmount;
_allowances[asset_][to][msg.sender] = type(uint256).max;
function approve(address spender, uint256 amount) public returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}

function exit(address to, address asset_, uint256 assetAmount, address from, uint256 shareAmount) external {
// Change from checking 'from' balance to checking the actual owner's balance
address owner = from == msg.sender ? to : from;
require(_balances[asset_][owner] >= shareAmount, "MockVault: insufficient balance");
function transfer(address to, uint256 amount) public returns (bool) {
_callBeforeTransfer(msg.sender);
return _transfer(msg.sender, to, amount);
}

uint256 allowed = _allowances[asset_][owner][msg.sender];
function transferFrom(address from, address to, uint256 amount) public returns (bool) {
_callBeforeTransfer(from);
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) {
require(allowed >= shareAmount, "MockVault: insufficient allowance");
_allowances[asset_][owner][msg.sender] = allowed - shareAmount;
}

_balances[asset_][owner] -= shareAmount;

// Changed: Transfer to 'to' instead of msg.sender, and always transfer if we have shares
if (shareAmount > 0) {
IERC20(asset_).safeTransfer(to, shareAmount);
require(allowed >= amount, "MockVault: insufficient allowance");
allowance[from][msg.sender] = allowed - amount;
}
return _transfer(from, to, amount);
}

function transferFrom(address asset_, address from, address to, uint256 amount) external returns (bool) {
require(_balances[asset_][from] >= amount, "MockVault: insufficient balance");
function _transfer(address from, address to, uint256 amount) internal returns (bool) {
require(from != address(0), "MockVault: transfer from zero address");
require(to != address(0), "MockVault: transfer to zero address");
require(balanceOf[from] >= amount, "MockVault: insufficient balance");

uint256 allowed = _allowances[asset_][from][msg.sender];
if (allowed != type(uint256).max) {
require(allowed >= amount, "MockVault: insufficient allowance");
_allowances[asset_][from][msg.sender] = allowed - amount;
}
balanceOf[from] -= amount;
balanceOf[to] += amount;

_balances[asset_][from] -= amount;
_balances[asset_][to] += amount;
emit Transfer(from, to, amount);
return true;
}

function approve(address asset_, address spender, uint256 amount) external returns (bool) {
_allowances[asset_][msg.sender][spender] = amount;
return true;
function _mint(address to, uint256 amount) internal {
require(to != address(0), "MockVault: mint to zero address");
totalSupply += amount;
balanceOf[to] += amount;
emit Transfer(address(0), to, amount);
}

function balanceOf(
address account
) public view virtual override(ERC20, IERC20) returns (uint256) {
// Return total balance across all assets
return _balances[address(usdc)][account] + _balances[address(usdt)][account];
function _burn(address from, uint256 amount) internal {
require(from != address(0), "MockVault: burn from zero address");
require(balanceOf[from] >= amount, "MockVault: insufficient balance");
totalSupply -= amount;
balanceOf[from] -= amount;
emit Transfer(from, address(0), amount);
}

function totalSupply() public view virtual override(ERC20, IERC20) returns (uint256) {
// Return total supply across all assets
return _balances[address(usdc)][address(this)] + _balances[address(usdt)][address(this)];
}
function enter(
address from,
address asset,
uint256 assetAmount,
address to,
uint256 shareAmount
) external override requiresAuth {
emit DebugCall("enter", abi.encode(from, asset, assetAmount, to, shareAmount));

if (assetAmount > 0) {
ERC20(asset).safeTransferFrom(from, address(this), assetAmount);
}

function decimals() public pure virtual override(ERC20, IERC20Metadata) returns (uint8) {
return 6;
}
_mint(to, shareAmount);

function tokenBalance(address token, address account) external view returns (uint256) {
return _balances[token][account];
emit Enter(from, asset, assetAmount, to, shareAmount);
}

function setBalance(address token, uint256 amount) external {
_balances[token][address(this)] = amount;
function exit(
address to,
address asset,
uint256 assetAmount,
address from,
uint256 shareAmount
) external override requiresAuth {
emit DebugCall("exit", abi.encode(to, asset, assetAmount, from, shareAmount));

_burn(from, shareAmount);

if (assetAmount > 0) {
ERC20(asset).safeTransfer(to, assetAmount);
}

emit Exit(to, address(asset), assetAmount, from, shareAmount);
}

function allowance(address asset_, address owner, address spender) external view returns (uint256) {
return _allowances[asset_][owner][spender];
function setBeforeTransferHook(address _hook) external requiresAuth {
hook = BeforeTransferHook(_hook);
}

function setBeforeTransferHook(
address hook
) external {
beforeTransferHook = hook;
function _callBeforeTransfer(address from) internal view {
if (address(hook) != address(0)) hook.beforeTransfer(from);
}

}
receive() external payable {}
}
22 changes: 22 additions & 0 deletions nest/src/vault/NestTeller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { MultiChainLayerZeroTellerWithMultiAssetSupport } from

import { ITeller } from "../interfaces/ITeller.sol";
import { NestBoringVaultModule } from "./NestBoringVaultModule.sol";
import { console } from "forge-std/console.sol";

/**
* @title NestTeller
Expand Down Expand Up @@ -41,7 +42,28 @@ contract NestTeller is NestBoringVaultModule, MultiChainLayerZeroTellerWithMulti
MultiChainLayerZeroTellerWithMultiAssetSupport(_owner, _vault, _accountant, _endpoint)
NestBoringVaultModule(_owner, _vault, _accountant, IERC20(_asset))
{
console.log("Debug: Starting NestTeller constructor");


// Input validation
require(_owner != address(0), "NestTeller: owner cannot be zero address");
require(_vault != address(0), "NestTeller: vault cannot be zero address");
require(_accountant != address(0), "NestTeller: accountant cannot be zero address");
require(_endpoint != address(0), "NestTeller: endpoint cannot be zero address");
require(_asset != address(0), "NestTeller: asset cannot be zero address");
require(_minimumMintPercentage > 0 && _minimumMintPercentage <= 10000, "NestTeller: invalid minimum mint percentage");

console.log("Debug: Owner", _owner);
console.log("Debug: Vault", _vault);
console.log("Debug: Accountant", _accountant);
console.log("Debug: Endpoint", _endpoint);
console.log("Debug: Asset", _asset);
console.log("Debug: MinimumMintPercentage", _minimumMintPercentage);

minimumMintPercentage = _minimumMintPercentage;
console.log("Debug: Set minimumMintPercentage to:", _minimumMintPercentage);

console.log("Debug: NestTeller constructor completed");
}

/**
Expand Down
18 changes: 12 additions & 6 deletions nest/test/NestBoringVaultModuleTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,26 @@ abstract contract NestBoringVaultModuleTest is Test {
owner = address(this);
user = makeAddr("user");

// Deploy mocks
// Deploy mocks in specific order
asset = new MockUSDC();

vault = new MockVault(owner, "Mock Vault", "mVault", 6); // Use 6 for USDC decimals
/*
vault = new MockVault(
owner, // _owner
"Mock Vault", // _name
"MVLT", // _symbol
address(asset) // _usdc
owner, // _owner
"Mock Vault", // _name
"MVLT", // _symbol
address(asset) // _usdc
);

*/
accountant = new MockAccountantWithRateProviders(
address(vault), // _vault
address(asset), // _base
1e18 // startingExchangeRate (1:1 ratio)
);

// Deal some tokens to the vault for initial liquidity
deal(address(asset), address(vault), 1000000e6);
}

// Common tests that apply to all NestBoringVaultModule implementations
Expand Down
Loading

0 comments on commit 63d533e

Please sign in to comment.