Skip to content

Commit 1bdb8a3

Browse files
authored
Merge pull request #166 from MetaMask/chore-veda-adapter
chore: Implement VedaAdapter
2 parents d2811d6 + e2227ef commit 1bdb8a3

9 files changed

Lines changed: 1766 additions & 0 deletions

File tree

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ META_SWAP_ADAPTER_OWNER_ADDRESS=
88
METASWAP_ADDRESS=
99
SWAPS_API_SIGNER_ADDRESS=
1010
ARGS_EQUALITY_CHECK_ENFORCER_ADDRESS=
11+
VEDA_ADAPTER_OWNER_ADDRESS=
12+
VEDA_BORING_VAULT_ADDRESS=
13+
VEDA_TELLER_ADDRESS=
14+
VEDA_DEPOSIT_TOKEN_ADDRESS=
1115

1216
# Required for verifying contracts
1317
ETHERSCAN_API_KEY=

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ jobs:
5151
run: forge test -vvv
5252
env:
5353
LINEA_RPC_URL: ${{ secrets.LINEA_RPC_URL }}
54+
ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}
55+
RPC_API_KEY: ${{ secrets.RPC_API_KEY }}

audits/cyfrin/cyfrin-4-26.pdf

220 KB
Binary file not shown.

broadcast/DeployVedaAdapter.s.sol/143/run-1780040823916.json

Lines changed: 85 additions & 0 deletions
Large diffs are not rendered by default.

broadcast/DeployVedaAdapter.s.sol/143/run-latest.json

Lines changed: 85 additions & 0 deletions
Large diffs are not rendered by default.

script/DeployVedaAdapter.s.sol

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// SPDX-License-Identifier: MIT AND Apache-2.0
2+
pragma solidity 0.8.23;
3+
4+
import "forge-std/Script.sol";
5+
import { console2 } from "forge-std/console2.sol";
6+
7+
import { VedaAdapter } from "../src/helpers/VedaAdapter.sol";
8+
9+
/**
10+
* @title DeployVedaAdapter
11+
* @notice Deploys the VedaAdapter contract.
12+
* @dev Fill the required variables in the .env file
13+
* @dev run the script with:
14+
* forge script script/DeployVedaAdapter.s.sol --rpc-url <your_rpc_url> --private-key $PRIVATE_KEY --broadcast
15+
* For deploying on monad add --skip-simulation, because of how monad works the simulation fails because the token is not activated.
16+
*/
17+
contract DeployVedaAdapter is Script {
18+
bytes32 salt;
19+
address deployer;
20+
address vedaAdapterOwner;
21+
address delegationManager;
22+
address boringVault;
23+
address vedaTeller;
24+
address depositToken;
25+
26+
function setUp() public {
27+
salt = bytes32(abi.encodePacked(vm.envString("SALT")));
28+
vedaAdapterOwner = vm.envAddress("VEDA_ADAPTER_OWNER_ADDRESS");
29+
delegationManager = vm.envAddress("DELEGATION_MANAGER_ADDRESS");
30+
boringVault = vm.envAddress("VEDA_BORING_VAULT_ADDRESS");
31+
vedaTeller = vm.envAddress("VEDA_TELLER_ADDRESS");
32+
depositToken = vm.envAddress("VEDA_DEPOSIT_TOKEN_ADDRESS");
33+
deployer = msg.sender;
34+
console2.log("~~~");
35+
console2.log("Owner: %s", vedaAdapterOwner);
36+
console2.log("DelegationManager: %s", delegationManager);
37+
console2.log("BoringVault: %s", boringVault);
38+
console2.log("VedaTeller: %s", vedaTeller);
39+
console2.log("DepositToken: %s", depositToken);
40+
console2.log("Deployer: %s", deployer);
41+
console2.log("Salt:");
42+
console2.logBytes32(salt);
43+
}
44+
45+
function run() public {
46+
console2.log("~~~");
47+
48+
// Foundry's fork mode cannot interact with mUSD on Monad (NotActivated in revm).
49+
// Mock the approve call so simulation passes; the real broadcast executes the
50+
// actual constructor on-chain where the token works correctly.
51+
// vm.mockCall(depositToken, abi.encodeWithSelector(bytes4(keccak256("approve(address,uint256)"))), abi.encode(true));
52+
53+
vm.startBroadcast();
54+
55+
address vedaAdapter =
56+
address(new VedaAdapter{ salt: salt }(vedaAdapterOwner, delegationManager, boringVault, vedaTeller, depositToken));
57+
console2.log("VedaAdapter: %s", vedaAdapter);
58+
59+
vm.stopBroadcast();
60+
61+
// vm.clearMockedCalls();
62+
}
63+
}

src/helpers/VedaAdapter.sol

Lines changed: 399 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Based on:
2+
// https://github.com/Se7en-Seas/boring-vault/blob/main/src/base/Roles/TellerWithMultiAssetSupport.sol
3+
// https://github.com/Veda-Labs/boring-vault/blob/dev/oct-2025/src/base/Roles/TellerWithYieldStreaming.sol
4+
5+
// SPDX-License-Identifier: MIT AND Apache-2.0
6+
pragma solidity 0.8.23;
7+
8+
/**
9+
* @title IVedaTeller
10+
* @notice Interface for the user-facing functions of Veda's TellerWithMultiAssetSupport.
11+
* @dev Uses `address` for asset parameters to avoid importing Solmate's ERC20.
12+
* The Teller is the entry/exit point for the BoringVault. All functions use `requiresAuth`,
13+
* so callers must be authorized on the Teller's Authority.
14+
*/
15+
interface IVedaTeller {
16+
/**
17+
* @notice Allows users to deposit into the BoringVault, if the contract is not paused.
18+
* @dev Shares are minted to `msg.sender`. A share lock period may apply.
19+
* @param depositAsset The ERC20 token to deposit
20+
* @param depositAmount The amount to deposit
21+
* @param minimumMint The minimum shares the user expects to receive
22+
* @param referralAddress Address used for referral tracking
23+
* @return shares The number of vault shares minted
24+
*/
25+
function deposit(
26+
address depositAsset,
27+
uint256 depositAmount,
28+
uint256 minimumMint,
29+
address referralAddress
30+
)
31+
external
32+
payable
33+
returns (uint256 shares);
34+
35+
/**
36+
* @notice Allows an authorized caller to deposit into the BoringVault for another address, if this contract is not paused.
37+
* @dev Intended for router-like integrations; this selector should remain role-gated.
38+
* @param depositAsset The ERC20 token to deposit
39+
* @param depositAmount The amount to deposit
40+
* @param minimumMint The minimum shares the user expects to receive
41+
* @param to The address that will receive the minted vault shares
42+
* @param referralAddress Address used for referral tracking
43+
* @return shares The number of vault shares minted
44+
*/
45+
function deposit(
46+
address depositAsset,
47+
uint256 depositAmount,
48+
uint256 minimumMint,
49+
address to,
50+
address referralAddress
51+
)
52+
external
53+
payable
54+
returns (uint256 shares);
55+
56+
/**
57+
* @notice Allows users to withdraw from the BoringVault.
58+
* @dev Available on TellerWithYieldStreaming. Burns shares from `msg.sender` and sends
59+
* underlying assets to `to`. Updates vested yield before withdrawal.
60+
* @param withdrawAsset The ERC20 token to receive
61+
* @param shareAmount The amount of vault shares to burn
62+
* @param minimumAssets The minimum underlying assets expected
63+
* @param to The address that will receive the underlying assets
64+
* @return assetsOut The amount of underlying assets sent
65+
*/
66+
function withdraw(
67+
address withdrawAsset,
68+
uint256 shareAmount,
69+
uint256 minimumAssets,
70+
address to
71+
)
72+
external
73+
returns (uint256 assetsOut);
74+
}

0 commit comments

Comments
 (0)