Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/BitcoinuNameSyncL1.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Optimism Stack用のクロスチェーンメッセージング
interface ICrossDomainMessenger {
function sendMessage(
address _target,
bytes calldata _message,
uint32 _gasLimit
) external;
function xDomainMessageSender() external view returns (address);
}
/**
* @title BitcoinuNameSyncL1
* @dev イーサリアムメインネット側の名前同期コントラクト
* L2からのリクエストに応答してトークン名を送信
* トークンのブリッジ機能は標準ブリッジに任せる
*/
contract BitcoinuNameSyncL1 {
// L1トークンコントラクト
address public immutable l1Token;
// L2名前同期コントラクトごとの情報
struct L2SyncInfo {
bool approved; // 承認されているか
address messenger; // 対応するL1メッセンジャーアドレス
}
// L2名前同期コントラクトアドレス => L2情報
mapping(address => L2SyncInfo) public l2SyncInfo;
// L2コントラクトの配列(管理用)
address[] public l2SyncList;
// オーナー
address public owner;
event L2SyncContractAdded(address indexed l2Contract, address indexed messenger);
event L2SyncContractRemoved(address indexed l2Contract);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// ガスリミット設定
uint32 public constant NAME_UPDATE_GAS_LIMIT = 100000;
event NameSyncRequested(
string newName,
string newSymbol,
uint256 timestamp
);
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call");
_;
}
/**
* @dev コンストラクタ
* @param _l1Token L1トークンアドレス(Bitcoinuコントラクト)
*/
constructor(address _l1Token) {
require(_l1Token != address(0), "Invalid L1 token");
l1Token = _l1Token;
owner = msg.sender;
// L1トークンのname()とsymbol()が呼び出せることを確認
(bool successName, ) = _l1Token.staticcall(
abi.encodeWithSignature("name()")
);
(bool successSymbol, ) = _l1Token.staticcall(
abi.encodeWithSignature("symbol()")
);
require(
successName && successSymbol,
"L1 token must implement name() and symbol()"
);
}
/**
* @dev オーナーを変更
* @param newOwner 新しいオーナーアドレス
*/
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Invalid address");
address oldOwner = owner;
owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev L2名前同期コントラクトを追加
* @param _l2SyncContract 追加するL2名前同期コントラクトアドレス
* @param _l1Messenger そのL2に対応するL1メッセンジャーアドレス
*/
function addL2SyncContract(address _l2SyncContract, address _l1Messenger) external onlyOwner {
require(_l2SyncContract != address(0), "Invalid L2 contract");
require(_l1Messenger != address(0), "Invalid messenger");
require(!l2SyncInfo[_l2SyncContract].approved, "Contract already added");
l2SyncInfo[_l2SyncContract] = L2SyncInfo({
approved: true,
messenger: _l1Messenger
});
l2SyncList.push(_l2SyncContract);
emit L2SyncContractAdded(_l2SyncContract, _l1Messenger);
}
/**
* @dev L2名前同期コントラクトのメッセンジャーアドレスを更新
* @param _l2SyncContract L2コントラクトアドレス
* @param _l1Messenger 新しいL1メッセンジャーアドレス
*/
function updateL2Messenger(address _l2SyncContract, address _l1Messenger) external onlyOwner {
require(l2SyncInfo[_l2SyncContract].approved, "Contract not found");
require(_l1Messenger != address(0), "Invalid messenger");
l2SyncInfo[_l2SyncContract].messenger = _l1Messenger;
}
/**
* @dev L2名前同期コントラクトを削除
* @param _l2SyncContract 削除するL2コントラクトアドレス
*/
function removeL2SyncContract(address _l2SyncContract) external onlyOwner {
require(l2SyncInfo[_l2SyncContract].approved, "Contract not found");
delete l2SyncInfo[_l2SyncContract];
// 配列から削除
for (uint256 i = 0; i < l2SyncList.length; i++) {
if (l2SyncList[i] == _l2SyncContract) {
l2SyncList[i] = l2SyncList[l2SyncList.length - 1];
l2SyncList.pop();
break;
}
}
emit L2SyncContractRemoved(_l2SyncContract);
}
/**
* @dev 承認されたL2コントラクトの数を取得
*/
function getL2SyncCount() external view returns (uint256) {
return l2SyncList.length;
}
/**
* @dev L2からのリクエストに応答してトークン名を送信
* L2名前同期コントラクトからのクロスチェーンメッセージでのみ呼び出し可能
* @param requestingL2Contract リクエスト元のL2コントラクトアドレス
*/
function respondWithTokenInfo(address requestingL2Contract) external {
// リクエスト元のL2コントラクトが承認されているか確認
require(
l2SyncInfo[requestingL2Contract].approved,
"L2 contract not approved"
);
// 対応するメッセンジャーからのメッセージか確認
address expectedMessenger = l2SyncInfo[requestingL2Contract].messenger;
require(
msg.sender == expectedMessenger,
"Only corresponding messenger can call"
);
// メッセンジャーを通じてメッセージが送られてきたか確認
ICrossDomainMessenger messenger = ICrossDomainMessenger(expectedMessenger);
require(
messenger.xDomainMessageSender() == requestingL2Contract,
"Invalid message sender"
);
// L1トークンコントラクトから現在の名前を取得
(bool successName, bytes memory dataName) = l1Token.staticcall(
abi.encodeWithSignature("name()")
);
(bool successSymbol, bytes memory dataSymbol) = l1Token.staticcall(
abi.encodeWithSignature("symbol()")
);
require(successName && successSymbol, "Failed to read token info");
string memory tokenName = abi.decode(dataName, (string));
string memory tokenSymbol = abi.decode(dataSymbol, (string));
// L2に名前とシンボルを返信
bytes memory message = abi.encodeWithSignature(
"receiveTokenInfo(string,string)",
tokenName,
tokenSymbol
);
messenger.sendMessage(
requestingL2Contract,
message,
NAME_UPDATE_GAS_LIMIT
);
emit NameSyncRequested(tokenName, tokenSymbol, block.timestamp);
}
}"
}
},
"settings": {
"evmVersion": "paris",
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}
}}
Submitted on: 2025-11-05 14:37:44
Comments
Log in to comment.
No comments yet.