目 录CONTENT

文章目录

aptos链主网合约部署,实现入金出金

懿曲折扇情
2026-01-31 / 0 评论 / 0 点赞 / 12 阅读 / 3,638 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2026-01-31,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
广告 广告

合约代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

/**
 * @title DepositWithdraw
 * @dev 以太坊主网出入金合约
 * 功能:
 * - 用户可以向合约充值ETH
 * - 合约所有者可以提取ETH
 * - 支持查询余额和充值记录
 */
contract DepositWithdraw is Ownable, ReentrancyGuard {
    // 充值事件
    event Deposit(address indexed user, uint256 amount, uint256 timestamp);
    
    // 提款事件
    event Withdraw(address indexed to, uint256 amount, uint256 timestamp);
    
    // 用户充值记录
    mapping(address => uint256) public deposits;
    
    // 用户充值次数
    mapping(address => uint256) public depositCount;
    
    // 总充值金额
    uint256 public totalDeposits;
    
    // 总提款金额
    uint256 public totalWithdraws;
    
    // 最小充值金额(可选,设置为0表示无限制)
    uint256 public minDepositAmount;
    
    // 最大单次提款金额(可选,设置为0表示无限制)
    uint256 public maxWithdrawAmount;
    
    /**
     * @dev 构造函数
     * @param _minDepositAmount 最小充值金额(wei)
     * @param _maxWithdrawAmount 最大单次提款金额(wei)
     */
    constructor(uint256 _minDepositAmount, uint256 _maxWithdrawAmount) Ownable(msg.sender) {
        minDepositAmount = _minDepositAmount;
        maxWithdrawAmount = _maxWithdrawAmount;
    }
    
    /**
     * @dev 充值函数,接收ETH
     */
    function deposit() external payable nonReentrant {
        require(msg.value > 0, "Deposit amount must be greater than 0");
        
        if (minDepositAmount > 0) {
            require(msg.value >= minDepositAmount, "Deposit amount is below minimum");
        }
        
        deposits[msg.sender] += msg.value;
        depositCount[msg.sender] += 1;
        totalDeposits += msg.value;
        
        emit Deposit(msg.sender, msg.value, block.timestamp);
    }
    
    /**
     * @dev 合约所有者提取ETH
     * @param to 接收地址
     * @param amount 提取金额(wei)
     */
    function withdraw(address payable to, uint256 amount) external onlyOwner nonReentrant {
        require(to != address(0), "Invalid address");
        require(amount > 0, "Withdraw amount must be greater than 0");
        require(address(this).balance >= amount, "Insufficient contract balance");
        
        if (maxWithdrawAmount > 0) {
            require(amount <= maxWithdrawAmount, "Withdraw amount exceeds maximum");
        }
        
        totalWithdraws += amount;
        
        (bool success, ) = to.call{value: amount}("");
        require(success, "Withdraw failed");
        
        emit Withdraw(to, amount, block.timestamp);
    }
    
    /**
     * @dev 批量提取ETH(仅所有者)
     * @param recipients 接收地址数组
     * @param amounts 提取金额数组(wei)
     */
    function batchWithdraw(address payable[] calldata recipients, uint256[] calldata amounts) 
        external 
        onlyOwner 
        nonReentrant 
    {
        require(recipients.length == amounts.length, "Arrays length mismatch");
        require(recipients.length > 0, "Empty arrays");
        
        uint256 totalAmount = 0;
        for (uint256 i = 0; i < amounts.length; i++) {
            totalAmount += amounts[i];
        }
        
        require(address(this).balance >= totalAmount, "Insufficient contract balance");
        
        for (uint256 i = 0; i < recipients.length; i++) {
            require(recipients[i] != address(0), "Invalid address");
            require(amounts[i] > 0, "Amount must be greater than 0");
            
            (bool success, ) = recipients[i].call{value: amounts[i]}("");
            require(success, "Batch withdraw failed");
            
            emit Withdraw(recipients[i], amounts[i], block.timestamp);
        }
        
        totalWithdraws += totalAmount;
    }
    
    /**
     * @dev 查询用户总充值金额
     * @param user 用户地址
     * @return 总充值金额(wei)
     */
    function getUserDeposit(address user) external view returns (uint256) {
        return deposits[user];
    }
    
    /**
     * @dev 查询合约总余额
     * @return 合约余额(wei)
     */
    function getContractBalance() external view returns (uint256) {
        return address(this).balance;
    }
    
    /**
     * @dev 更新最小充值金额(仅所有者)
     * @param _minDepositAmount 新的最小充值金额(wei)
     */
    function setMinDepositAmount(uint256 _minDepositAmount) external onlyOwner {
        minDepositAmount = _minDepositAmount;
    }
    
    /**
     * @dev 更新最大提款金额(仅所有者)
     * @param _maxWithdrawAmount 新的最大提款金额(wei)
     */
    function setMaxWithdrawAmount(uint256 _maxWithdrawAmount) external onlyOwner {
        maxWithdrawAmount = _maxWithdrawAmount;
    }
    
    /**
     * @dev 接收ETH的回退函数
     */
    receive() external payable {
        deposit();
    }
    
    /**
     * @dev 回退函数
     */
    fallback() external payable {
        deposit();
    }
}

入金

6f2190e792ddc11b3d4d63d9e1930cf deposit 0.01
操作账户: 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf
合约地址: 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf
操作: deposit
网络: mainnet 

正在充值 0.01 APT (1000000 octas)...
交易哈希: 0x4a2b762b65fa26a337ca5da5fad16e6cb8690b347872546afb6cb430fd746967
✅ 充值成功!

区块链浏览器中的方法是deposit

image-1769796958817

出金

✅ 出金操作成功!

交易信息:
交易哈希: 0x859dac290fd7a6e29afb7c6ed7801bef639dbf5776236b97ed9b3da1d79f3d0d
提取金额: 0.005 APT
接收地址: 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf

区块链浏览器中的方法是withdraw

image-1769796993911

主网合约部署,入金,合约地址出金

# Aptos链出入金合约

这是一个用于Aptos链的出入金智能合约,支持用户充值和合约所有者提款功能。

## 功能特性

- ✅ **APT 充值功能**: 用户可以向合约充值APT
- ✅ **APT 提款功能**: 合约所有者可以提取APT
- ✅ **通用代币功能**: 支持任意代币类型(包括自定义USDT),使用泛型实现
- ✅ **灵活配置**: 不依赖官方代币地址,支持您自己部署的代币合约
- ✅ **批量提款**: 支持批量提取到多个地址
- ✅ **安全保护**: Move语言内置安全特性
- ✅ **权限控制**: 只有所有者可以提款
- ✅ **事件记录**: 记录所有充值和提款事件
- ✅ **查询功能**: 可以查询用户充值金额和合约余额

## 合约参数

### APT 参数
- **最小充值金额**: 1 octas (0.00000001 APT)
- **最小提款金额**: 1 octas (0.00000001 APT)

### 通用代币参数(包括USDT等)
- **最小充值金额**: 1 最小单位
- **最小提款金额**: 1 最小单位

⚠️ **重要提示**: 
1. 在 Aptos 链上,所有交易的 gas 费用必须使用 APT 支付。即使您只有其他代币,也需要少量 APT 来支付 gas 费用。
2. 合约使用泛型设计,**不依赖官方代币地址**,支持您自己部署的代币合约。
3. 使用代币功能时,需要提供完整的代币类型路径,例如:`0x您的地址::模块名::代币类型名`

## 前置要求

1. **安装Aptos CLI**

```bash
# macOS
brew install aptos

# 或使用脚本安装
curl -fsSL "https://aptos.dev/scripts/install_cli.py" | python3
  1. 安装Node.js依赖
npm install

配置环境变量

  1. 复制 .env.example.env
  2. 填写以下配置:
# Aptos网络(mainnet/testnet/devnet)
NETWORK=mainnet

# 部署账户私钥(必须)
PRIVATE_KEY=0x你的私钥

获取私钥

你可以使用Aptos CLI生成新账户:

aptos key generate --output-file key.json

然后从生成的 key.json 文件中获取私钥。

编译合约

npm run compile

或者直接使用Aptos CLI:

aptos move compile

部署合约

部署到主网

npm run deploy:mainnet

部署到测试网

npm run deploy:testnet

部署到开发网

npm run deploy:devnet

测试合约

运行测试脚本

测试脚本会自动执行入金和出金操作,并验证结果:

# 使用npm脚本
npm run test:contract <合约地址>

# 或直接使用node
node scripts/test.js <合约地址>

测试脚本会:

  1. ✅ 检查初始状态(账户余额、合约余额、用户充值记录)
  2. ✅ 执行入金操作(充值 0.01 APT)
  3. ✅ 验证入金结果(检查余额变化)
  4. ✅ 执行出金操作(提取 0.005 APT)
  5. ✅ 验证出金结果(检查余额变化)
  6. ✅ 显示测试总结

注意:

  • 确保账户有足够的APT支付测试费用(至少 0.02 APT + gas费用)
  • 测试账户必须是合约所有者才能执行出金操作
  • 测试会在主网/测试网/开发网上执行,取决于 .env 中的 NETWORK 配置

合约使用

充值APT

用户可以通过调用 deposit 函数充值:

// 使用交互脚本
node scripts/interact.js <合约地址> deposit 1.0

或者使用Aptos CLI:

aptos move run \
  --function-id <合约地址>::deposit_withdraw::deposit \
  --args u64:100000000 \
  --private-key-file key.json

充值代币(支持任意代币,包括自定义USDT)

用户可以通过调用 deposit_coin 函数充值任意代币:

// 使用交互脚本
// 格式: depositCoin <代币类型> <金额>
// 示例:使用您部署的USDT合约
node scripts/interact.js <合约地址> depositCoin 0x您的地址::usdt::USDT 100.0

或者使用Aptos CLI:

aptos move run \
  --function-id <合约地址>::deposit_withdraw::deposit_coin \
  --type-args <代币类型完整路径> \
  --args u64:100000000 \
  --private-key-file key.json

⚠️ 注意:

  • 代币类型需要提供完整路径,格式:<地址>::<模块名>::<类型名>
  • 例如:0x123::usdt::USDT(使用您部署的USDT合约地址)
  • 金额根据代币的小数位数计算(USDT通常使用6位小数)

提款APT(仅所有者)

// 使用交互脚本
node scripts/interact.js <合约地址> withdraw <接收地址> 1.0

提款代币(仅所有者,支持任意代币)

// 使用交互脚本
// 格式: withdrawCoin <代币类型> <接收地址> <金额>
node scripts/interact.js <合约地址> withdrawCoin 0x您的地址::usdt::USDT <接收地址> 100.0

查询功能

// 查询合约 APT 余额
node scripts/interact.js <合约地址> balance

// 查询合约代币余额(支持任意代币)
// 格式: balanceCoin <代币类型>
node scripts/interact.js <合约地址> balanceCoin 0x您的地址::usdt::USDT

// 查询用户 APT 充值金额
node scripts/interact.js <合约地址> userDeposit <用户地址>

合约函数

公共函数 (APT)

  • deposit(amount: u64) - 充值APT到合约
  • get_user_deposit(user: address): u64 - 查询用户APT充值金额
  • get_user_deposit_count(user: address): u64 - 查询用户APT充值次数
  • get_contract_balance(): u64 - 查询合约APT余额
  • get_total_deposits(): u64 - 查询总充值金额
  • get_total_withdraws(): u64 - 查询总提款金额
  • get_owner(): address - 查询合约所有者
  • get_min_deposit_amount(): u64 - 查询最小APT充值金额
  • get_min_withdraw_amount(): u64 - 查询最小APT提款金额

公共函数 (通用代币,支持任意代币类型)

  • deposit_coin<CoinType>(amount: u64) - 充值代币到合约(CoinType为代币类型)
  • withdraw_coin<CoinType>(to: address, amount: u64) - 提取代币到指定地址(仅所有者)
  • batch_withdraw_coin<CoinType>(recipients: vector<address>, amounts: vector<u64>) - 批量提取代币
  • get_contract_balance_coin<CoinType>(): u64 - 查询合约代币余额
  • get_min_deposit_amount_coin(): u64 - 查询最小代币充值金额
  • get_min_withdraw_amount_coin(): u64 - 查询最小代币提款金额

⚠️ 注意: 这些函数使用泛型类型参数 <CoinType>,可以支持任意代币类型,包括您自己部署的USDT合约。

仅所有者函数

  • withdraw(to: address, amount: u64) - 提取APT到指定地址
  • withdraw_coin<CoinType>(to: address, amount: u64) - 提取代币到指定地址(支持任意代币类型)
  • batch_withdraw(recipients: vector<address>, amounts: vector<u64>) - 批量提取APT
  • batch_withdraw_coin<CoinType>(recipients: vector<address>, amounts: vector<u64>) - 批量提取代币

使用Aptos CLI交互

查看合约资源

aptos account list --account <合约地址>

调用函数

# 充值 (示例: 0.01 APT = 1000000 octas)
aptos move run \
  --function-id <合约地址>::deposit_withdraw::deposit \
  --args u64:1000000 \
  --private-key-file key.json

# 提款(仅所有者)(示例: 0.01 APT = 1000000 octas)
aptos move run \
  --function-id <合约地址>::deposit_withdraw::withdraw \
  --args address:<接收地址> u64:1000000 \
  --private-key-file key.json

查看函数

# 查询用户充值金额
aptos move view \
  --function-id <合约地址>::deposit_withdraw::get_user_deposit \
  --args address:<用户地址>

网络信息

主网 (Mainnet)

测试网 (Testnet)

开发网 (Devnet)

安全注意事项

⚠️ 重要提示:

  1. 私钥安全: 永远不要将私钥提交到代码仓库
  2. 测试先行: 建议先在测试网或开发网部署和测试
  3. Gas费用: 确保账户有足够的APT支付gas费用(通常很少)
    • ⚠️ 即使您只有USDT,也需要少量APT来支付gas费用
    • 建议至少保留 0.01 APT 用于支付交易费用
  4. 权限管理: 合约所有者拥有提款权限,请妥善保管私钥
  5. 金额限制:
    • APT最小充值: 1 octas (0.00000001 APT)
    • APT最小提款: 1 octas (0.00000001 APT)
    • 代币最小充值: 1 最小单位
    • 代币最小提款: 1 最小单位
  6. 代币类型: 合约使用泛型设计,不依赖官方代币地址
    • 支持任意代币类型,包括您自己部署的USDT合约
    • 使用时需要提供完整的代币类型路径:<地址>::<模块名>::<类型名>
    • 示例:0x您的地址::usdt::USDT

常见问题

1. 编译错误

如果遇到编译错误,确保:

  • 已安装Aptos CLI
  • Move.toml中的地址配置正确
  • 依赖项版本正确

2. 部署失败

检查:

  • 账户余额是否足够支付gas
  • 私钥格式是否正确(0x开头)
  • 网络连接是否正常

3. 函数调用失败

确保:

  • 调用者权限正确(提款需要所有者)
  • 金额满足最小限制
  • 合约地址正确

如何调用

# 如何给合约充值

## 重要说明

虽然合约地址和钱包地址相同(`0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf`),但这是**正常的**!

在Aptos中:
- 合约模块部署在账户地址下
- 合约地址 = 部署账户地址
- 但合约有**独立的资源存储**

## 余额的区别

### 1. 钱包账户余额
- 这是您个人账户的APT余额
- 存储在账户的 `CoinStore` 资源中
- 可以直接转账使用

### 2. 合约余额
- 这是合约管理的APT余额
- 也存储在 `CoinStore` 资源中,但是合约的资源
- 只能通过合约函数操作

## 如何给合约充值

### 方法一:使用交互脚本(推荐)

```bash
# 充值 0.01 APT
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf deposit 0.01

# 充值 1 APT
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf deposit 1.0

方法二:使用Aptos CLI

# 充值 0.01 APT (1000000 octas)
aptos move run \
  --function-id 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf::deposit_withdraw::deposit \
  --args u64:1000000 \
  --private-key-file key.json

充值流程

当您调用 deposit 函数时:

  1. 从您的账户提取APT

    • 从您的钱包账户的 CoinStore 中提取指定金额
  2. 存入合约

    • 将APT存入合约地址的 CoinStore 资源中
    • 这是合约管理的资源,不是您个人账户的资源
  3. 更新记录

    • 更新您的充值记录(UserDeposit 资源)
    • 更新合约的总充值金额

查询余额

查询钱包账户余额

node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf balance

查询合约余额

# 同样使用balance命令,它会查询合约地址的CoinStore
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf balance

查询您的充值记录

node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf userDeposit 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf

重要提示

⚠️ 不要直接转账到合约地址!

  • 直接转账到地址只会增加账户余额,不会触发合约逻辑
  • 必须通过调用 deposit 函数来充值
  • 这样合约才能正确记录您的充值并更新状态

示例

# 1. 先查询钱包余额
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf balance

# 2. 给合约充值 0.01 APT
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf deposit 0.01

# 3. 再次查询合约余额(应该增加了)
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf balance

# 4. 查询您的充值记录
node scripts/interact.js 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf userDeposit 0xf711b12d67879da3584c636c6a7125cac6f2190e792ddc11b3d4d63d9e1930cf

0

评论区