VirtualsBondingAdapter
0xdeef773d61719a3181e35e9281600db8ba063f71
Verification
Verified
0.8.17+commit.8df45f5f
Type
Contract
2,150 bytes
ABI entries
7
2 read · 2 write
License
none
Contract information
- Address
- 0xdeef773d61719a3181e35e9281600db8ba063f71
- Chain
- Robinhood Chain (4663)
- Compiler
- 0.8.17+commit.8df45f5f
- Optimization
- Enabled
- Creator
- 0x399EfA78cA…Df9EFDf6Ad
- Creation tx
- 0xe3a084c871…3d486fa5ef
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (2)
ASSET_TOKEN() → address
ROUTER() → address
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "_router",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "ForceApproveFailed",
"type": "error"
},
{
"inputs": [],
"name": "SafeTransferFailed",
"type": "error"
},
{
"inputs": [],
"name": "ASSET_TOKEN",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "ROUTER",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "address",
"name": "pool",
"type": "address"
},
{
"internalType": "bytes",
"name": "moreInfo",
"type": "bytes"
}
],
"name": "sellBase",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "address",
"name": "pool",
"type": "address"
},
{
"internalType": "bytes",
"name": "moreInfo",
"type": "bytes"
}
],
"name": "sellQuote",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import {IAdapter} from "@interfaces/IAdapter.sol";
import {IERC20} from "@interfaces/IERC20.sol";
import {RefundLib} from "@libraries/RefundLib.sol";
import {SafeERC20} from "@libraries/SafeERC20.sol";
/// @notice Virtuals Protocol BondingV2/V4 swap interface
interface IVirtualsBonding {
function buy(uint256 amountIn, address tokenAddress, uint256 amountOutMin, uint256 deadline)
external
payable
returns (bool);
function sell(uint256 amountIn, address tokenAddress, uint256 amountOutMin, uint256 deadline)
external
returns (bool);
}
/// @notice Virtuals Protocol FRouter interface (for reading assetToken)
interface IFRouterV2 {
function assetToken() external view returns (address);
}
/// @title VirtualsBondingAdapter
/// @notice Adapter for Virtuals Protocol BondingV2/V4 on Base
/// @dev moreInfo = abi.encode(fromToken, toToken)
/// pool = BondingV2 or BondingV4 contract address.
/// Swaps are routed through the FRouter which pulls tokens via safeTransferFrom.
contract VirtualsBondingAdapter is IAdapter {
using SafeERC20 for IERC20;
address public immutable ROUTER;
address public immutable ASSET_TOKEN;
constructor(address _router) {
ROUTER = _router;
ASSET_TOKEN = IFRouterV2(_router).assetToken();
}
function sellBase(address to, address pool, bytes memory moreInfo) external override {
_bondingSwap(to, pool, moreInfo);
}
function sellQuote(address to, address pool, bytes memory moreInfo) external override {
_bondingSwap(to, pool, moreInfo);
}
function _bondingSwap(address to, address pool, bytes memory moreInfo) internal {
(address fromToken, address toToken) = abi.decode(moreInfo, (address, address));
uint256 fromAmount = IERC20(fromToken).balanceOf(address(this));
require(fromAmount > 0, "VirtualsBondingAdapter: zero balance");
IERC20(fromToken).safeApprove(ROUTER, 0);
IERC20(fromToken).safeApprove(ROUTER, fromAmount);
if (fromToken == ASSET_TOKEN) {
// Buy: spend ASSET_TOKEN to buy agent token
IVirtualsBonding(pool).buy(fromAmount, toToken, 0, block.timestamp);
IERC20(toToken).safeTransfer(to, IERC20(toToken).balanceOf(address(this)));
} else {
// Sell: sell agent token for ASSET_TOKEN
IVirtualsBonding(pool).sell(fromAmount, fromToken, 0, block.timestamp);
IERC20(ASSET_TOKEN).safeTransfer(to, IERC20(ASSET_TOKEN).balanceOf(address(this)));
}
RefundLib.refund(fromToken);
}
}
Chain explorer6545msChain node84ms