Routescan 验证失败通常由以下原因导致:
- 编译器版本不匹配 - Remix 使用的编译器版本与部署时不一致
- 优化设置不匹配 - 编译优化选项不一致
- 合约代码格式问题 - 多文件导入在验证时可能有问题
- 验证时机过早 - 合约还未完全确认就尝试验证
-
等待合约完全部署
- 确保交易已确认(至少等待几个区块)
- 在 Routescan 上确认合约地址存在
-
打开 Remix 的 "Contract Verification" 插件
- 在 Remix 左侧面板找到 "Contract Verification" 插件
- 如果没有,在插件管理器中搜索并安装
-
填写验证信息
- Contract Address:
0xdb38C9D838b119ffa1e25731970dB41c01Cb7CE5 - Chain: Sepolia (Chain ID: 11155111)
- Compiler Version:
0.8.0(必须与部署时一致) - Optimization: 如果部署时启用了优化,选择
Yes,否则选择No - Runs: 如果启用了优化,通常设置为
200或10000
- Contract Address:
-
合约代码
- 将完整的 Bank.sol 代码粘贴到验证框中
- 确保代码与部署时完全一致
-
构造函数参数
- Bank 合约的构造函数没有参数,留空即可
-
点击验证
- 访问 Routescan Sepolia
- 搜索你的合约地址:
0xdb38C9D838b119ffa1e25731970dB41c01Cb7CE5 - 点击 "Contract" 标签页
- 点击 "Verify and Publish"
- 选择验证方式:
- Via Standard JSON Input (推荐)
- Via Solidity (Single file)
- Via Solidity (Standard JSON Input)
如果上述方法都失败,使用标准 JSON Input:
-
在 Remix 中:
- 编译合约
- 在 "Solidity Compiler" 插件中,点击 "Compilation Details"
- 复制 "Standard JSON Input" 的内容
-
在 Routescan 验证页面:
- 选择 "Via Standard JSON Input"
- 粘贴 JSON 内容
- 填写合约地址和编译器版本
- 提交验证
以下是完整的单文件合约代码,可以直接在 Remix 中使用:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Bank {
// 管理员地址
address public owner;
// 记录每个地址的存款金额
mapping(address => uint256) public deposits;
// 记录存款金额前3名的用户地址
address[3] public topDepositors;
// 记录前3名用户的存款金额
uint256[3] public topDepositAmounts;
// 事件
event Deposit(address indexed user, uint256 amount);
event Withdraw(address indexed owner, uint256 amount);
// 自定义错误
error NotOwner();
error InvalidDepositAmount();
error InvalidWithdrawAmount();
error InsufficientBalance(uint256 requested, uint256 available);
error WithdrawFailed();
// 修饰符:仅管理员可调用
modifier onlyOwner() {
if(msg.sender != owner) revert NotOwner();
_;
}
constructor() {
owner = msg.sender;
}
// receive 函数:允许直接向合约发送 ETH
receive() external payable {
deposit();
}
// fallback 函数:处理其他调用
fallback() external payable {
deposit();
}
// 存款函数(也可以显式调用)
function deposit() public payable {
if (msg.value == 0) revert InvalidDepositAmount();
deposits[msg.sender] += msg.value;
// 更新前3名用户
updateTopDepositors(msg.sender, deposits[msg.sender]);
emit Deposit(msg.sender, msg.value);
}
// 更新前3名存款用户
function updateTopDepositors(address user, uint256 amount) internal {
// 检查用户是否已经在列表中
bool alreadyInList = false;
uint256 existingIndex = 0;
for (uint256 i = 0; i < 3; i++) {
if (topDepositors[i] == user) {
alreadyInList = true;
existingIndex = i;
break;
}
}
if (alreadyInList) {
// 如果用户已在列表中,更新金额并重新排序
topDepositAmounts[existingIndex] = amount;
sortTopDepositors();
} else {
// 如果用户不在列表中,检查是否可以进入前3名
for (uint256 i = 0; i < 3; i++) {
if (amount > topDepositAmounts[i]) {
// 插入新用户并排序
shiftAndInsert(i, user, amount);
break;
}
}
}
}
// 插入新用户到指定位置并保持排序
function shiftAndInsert(uint256 index, address user, uint256 amount) internal {
// 从后往前移动,为新用户腾出位置
for (uint256 i = 2; i > index; i--) {
topDepositors[i] = topDepositors[i - 1];
topDepositAmounts[i] = topDepositAmounts[i - 1];
}
// 插入新用户
topDepositors[index] = user;
topDepositAmounts[index] = amount;
}
// 对前3名进行排序(从大到小)
function sortTopDepositors() internal {
// 简单的冒泡排序
for (uint256 i = 0; i < 2; i++) {
for (uint256 j = 0; j < 2 - i; j++) {
if (topDepositAmounts[j] < topDepositAmounts[j + 1]) {
// 交换金额
uint256 tempAmount = topDepositAmounts[j];
topDepositAmounts[j] = topDepositAmounts[j + 1];
topDepositAmounts[j + 1] = tempAmount;
// 交换地址
address tempAddr = topDepositors[j];
topDepositors[j] = topDepositors[j + 1];
topDepositors[j + 1] = tempAddr;
}
}
}
}
// 提取资金(仅管理员)
function withdraw(uint256 amount) public onlyOwner {
if (amount == 0) revert InvalidWithdrawAmount();
if (address(this).balance < amount) revert InsufficientBalance(amount, address(this).balance);
(bool success, ) = payable(owner).call{value: amount}("");
if (!success) revert WithdrawFailed();
emit Withdraw(owner, amount);
}
// 获取合约总余额
function getBalance() public view returns (uint256) {
return address(this).balance;
}
// 获取用户的存款金额
function getDeposit(address user) public view returns (uint256) {
return deposits[user];
}
}- 编译器版本:
0.8.0(必须与部署时完全一致) - 优化设置:检查部署时是否启用了优化
- 合约代码:与部署时完全一致(包括注释和格式)
- 构造函数参数:无参数(留空)
- 合约地址:
0xdb38C9D838b119ffa1e25731970dB41c01Cb7CE5 - 网络:Sepolia (Chain ID: 11155111)
- 等待时间:确保合约已完全部署并确认
A: 在 Remix 的 "Solidity Compiler" 插件中查看当前选择的版本,这通常就是部署时使用的版本。
A: 在 Remix 编译器中,如果 "Enable optimization" 选项被勾选,则启用了优化。默认通常是关闭的。
A:
- 尝试使用 "Via Standard JSON Input" 方法
- 确保合约代码完全一致(包括空格和换行)
- 等待更长时间后再试(有时需要等待几分钟)
- 检查合约是否真的部署成功(在区块浏览器上查看)