メインコンテンツまでスキップ

06 · 環境設定と受入検証

公開環境へ接続するためのネットワークパラメータ、デモ資産、照会例、受入チェックリストを提供します。

6.1 環境情報​

項目テスト環境メインネットデモ環境
用途開発、結合テスト、受入BOT Mainnet 機能検証
ネットワークBohr TestnetBOT Mainnet
状態利用可能デモ Suite デプロイ済み
Chain ID968677
RPChttps://rpc.bohr.lifehttps://rpc.botchain.ai
Explorerhttps://scan.bohr.lifehttps://scan.botchain.ai
ネイティブ gas 資産Test BOTBOT

Bohr Testnet と BOT Mainnet のコントラクトアドレス、Token 残高、ID、Claim は共有されません。

6.2 推奨設定構造​

環境ごとに独立した設定ファイルまたは環境変数を使用します。

type RwaEnvironment = {
chainId: number;
rpcUrl: string;
explorerUrl: string;
contracts: {
token: string;
identityRegistry: string;
onchainIdGateway?: string;
idFactory?: string;
claimIssuer?: string;
};
};

テスト環境:

const rwaTestnet = {
chainId: 968,
rpcUrl: 'https://rpc.bohr.life',
explorerUrl: 'https://scan.bohr.life',
contracts: {
token: '0xA7aEb5cc99C558E7A237aA1B3483e71E59e66036',
identityRegistry: '0x5C3f759a7Fe22331750E6CA3293a96C34daE3417',
onchainIdGateway: '0xb62261a7193B6F37A5c6A2c242aD542C840d6f5a',
idFactory: '0xEa3216f557B6598F53fCcd146E63912c4c1be02C',
claimIssuer: '0xEa7E7c89F56f167E12570E15d648460104510d47',
},
};

BOT Mainnet 機能デモ:

const rwaMainnet = {
chainId: 677,
rpcUrl: 'https://rpc.botchain.ai',
explorerUrl: 'https://scan.botchain.ai',
contracts: {
token: '0x58F96a44594C9C5C8DE282Eeb75208B5f11C0c36',
identityRegistry: '0xe0b6FbEa0a9af21ddd455D6cA776478cAbe7c141',
onchainIdGateway: '0xFCF1E45f42aAa5CccA0A035f7a946BC8Fd55Fac6',
idFactory: '0xE97099950DFe98535927a650658c0E964c8d6f67',
claimIssuer: '0xD40b0c8dC960755C2586601Ff505F036FfE9BF59',
},
};

メインネット設定が不足または検証失敗した場合、テストネットアドレスへ自動 fallback してはいけません。メインネット JSON を参照してください。

6.3 公開デモ資産​

項目値
名称Project Real World Asset
シンボルPRWA
Decimals6
適格性 TopicKYC_APPROVED
Topic 値7151541257903274562366177585585886223835338030660388602590463654390840817671
Claim scheme1
許可国コード156, 702

6.3.1 Bohr Testnet アドレス​

コントラクトアドレス
Token0xA7aEb5cc99C558E7A237aA1B3483e71E59e66036
IdentityRegistry0x5C3f759a7Fe22331750E6CA3293a96C34daE3417
IdentityRegistryStorage0x3fae839c1642BDcFBE94b5A8088a56F8fC787707
ClaimTopicsRegistry0x042a938B2cE1e1AdF2b4101D9730722d5c75F773
TrustedIssuersRegistry0x2323413Abd0BF763ed2f3bE9c319A7a05985C2ff
ModularCompliance0x3aa6A97b6d61039A65C5AEf5649523732379aE9C
Token ONCHAINID0x7528D8d23fE511c658564E1cB346ca7D9B72788d
共有コントラクトアドレス
ONCHAINID Gateway0xb62261a7193B6F37A5c6A2c242aD542C840d6f5a
IdFactory0xEa3216f557B6598F53fCcd146E63912c4c1be02C
ClaimIssuer0xEa7E7c89F56f167E12570E15d648460104510d47
TREXGateway0xf73CB3A2830bef113Be01CD5eE5C99d21e43107B
Country Allowlist0x5Da275CcC6eAb8bd43800AB54B9c8Ec48129aB30

6.3.2 BOT Mainnet デモアドレス​

コントラクトアドレス
Token0x58F96a44594C9C5C8DE282Eeb75208B5f11C0c36
IdentityRegistry0xe0b6FbEa0a9af21ddd455D6cA776478cAbe7c141
IdentityRegistryStorage0x344D8266058FcE40D8229F8eF118da5ee6f88c54
ClaimTopicsRegistry0x7778b431b73F57722cBa7D6205F45858D789ACB1
TrustedIssuersRegistry0xC3216525E30E0369B49d75105b3591b647595d63
ModularCompliance0xE0444e1374d5ca5EdF3DAb0bEB54165c8D1968a4
Token ONCHAINID0x651b1Ad7F96A16228e41cDf6c2eb2282C267dE6B
共有プラットフォームアドレス
ONCHAINID Gateway0xFCF1E45f42aAa5CccA0A035f7a946BC8Fd55Fac6
IdFactory0xE97099950DFe98535927a650658c0E964c8d6f67
ClaimIssuer0xD40b0c8dC960755C2586601Ff505F036FfE9BF59
TREX ImplementationAuthority0x658B369FFfE2474310224c6DAe2f320A27A76D2E
ONCHAINID ImplementationAuthority0xA5aeF4767C10fE47d1097b65Da55357B29bbbfF6
IAFactory0x394f0720F519e25d63065690d8565018404b69E8
TREXFactory0xCdc6C38438DEd768028EecFd50a8aAf3ad755a92
TREXGateway0x7a8bea060430D7A6B5ac816137733570425Bb777
Country Allowlist0x8AD1cdF24Bf38E9b649294fb01e2A9E83F0E19E5

BOT Mainnet デモ Suite の Country Allowlist モジュールは本番監査を完了していません。技術機能検証専用であり、実資産を直接載せてはいけません。

Bohr Testnet JSON · BOT Mainnet JSON

6.4 公開照会ウォレット​

サンプルウォレットTestnet ONCHAINID国適格性
Alice0xb450970Eece71044acF7cB7f53Ee51e3BC2EA9220xfAB41B1DfD098F439D75cEA0cb48f70B46052544156true
Bob0xfc996C5378fe0cd03Fd4296075abc07B16b2B12F0xd3b816e7494e918297E3553d65488a7E0682C6A3702true
Cathy0x2b981b025397AE1AFca6f8DC7A2f5C7A868dEe780xb7522A6649a20A0820E292D8D0f35aB792812011156true

秘密鍵は提供されません。write 操作には自分のウォレットを使用してください。

最新の BOT Mainnet 機能デモ Suite は、コントラクトのデプロイとソースコード検証のみ完了しています。公開ウォレットの ONCHAINID 作成、Claim 発行、IdentityRegistry 登録はまだ実施されていません。そのため、現在は isVerified == true の mainnet サンプルウォレットを公開していません。独立した運用初期化とオンチェーン受入検証の完了後に本節を補足します。

negative test には自分が管理する未登録ウォレットを使用します。期待値は contains == false、isVerified == false です。ゼロアドレスを実業務ウォレットに使用しないでください。

6.5 第 1 段階:ネットワークとコントラクトを検証​

例は ethers.js v5 を使用します。v6 では JsonRpcProvider、formatUnits、parseUnits の v6 import を使用してください。

const { ethers } = require('ethers');
const provider = new ethers.providers.JsonRpcProvider('https://rpc.bohr.life');
const network = await provider.getNetwork();
if (network.chainId !== 968) {
throw new Error(`Wrong network: expected 968, got ${network.chainId}`);
}
const TOKEN = '0xA7aEb5cc99C558E7A237aA1B3483e71E59e66036';
const IR = '0x5C3f759a7Fe22331750E6CA3293a96C34daE3417';
if (await provider.getCode(TOKEN) === '0x') {
throw new Error('Token contract not found on current network');
}

write 操作の前に毎回 Chain ID を検証します。

6.6 第 2 段階:資産情報を読み取る​

const token = new ethers.Contract(TOKEN, [
'function name() view returns (string)',
'function symbol() view returns (string)',
'function decimals() view returns (uint8)',
'function totalSupply() view returns (uint256)',
'function identityRegistry() view returns (address)',
'function compliance() view returns (address)',
'function paused() view returns (bool)',
], provider);

const [name, symbol, decimals, supply, registry, compliance, paused] =
await Promise.all([
token.name(), token.symbol(), token.decimals(), token.totalSupply(),
token.identityRegistry(), token.compliance(), token.paused(),
]);
console.log({
name, symbol, decimals,
totalSupply: ethers.utils.formatUnits(supply, decimals),
registry, compliance, paused,
});

名称・シンボルが公開情報と一致し、decimals を読み取れ、identityRegistry() と compliance() がアドレス表に一致することを確認します。

6.7 第 3 段階:残高と適格性を照会​

const wallet = '0xb450970Eece71044acF7cB7f53Ee51e3BC2EA922';
const ir = new ethers.Contract(IR, [
'function contains(address) view returns (bool)',
'function isVerified(address) view returns (bool)',
'function identity(address) view returns (address)',
'function investorCountry(address) view returns (uint16)',
], provider);
const [rawBalance, contains, verified, identity, country] =
await Promise.all([
token.balanceOf(wallet), ir.contains(wallet), ir.isVerified(wallet),
ir.identity(wallet), ir.investorCountry(wallet),
]);
console.log({
balance: ethers.utils.formatUnits(rawBalance, decimals),
contains, verified, identity, country,
});

公開テストウォレットでは contains と verified が true で、ID と国コードが表に一致する必要があります。

6.8 第 4 段階:イベントを照会​

const latest = await provider.getBlockNumber();
const logs = await token.queryFilter(
token.filters.Transfer(), Math.max(0, latest - 5000), latest
);
for (const log of logs) {
console.log({
txHash: log.transactionHash,
blockNumber: log.blockNumber,
from: log.args.from,
to: log.args.to,
value: ethers.utils.formatUnits(log.args.value, decimals),
});
}

長時間稼働するインデクサーは範囲を分割し、checkpoint から再開して過大なリクエストを避けます。

6.9 write 操作の結合テスト​

操作署名者前提
ONCHAINID 作成投資家テストウォレットtest gas
addClaimONCHAINID 管理ウォレットtest Claim 署名
registerIdentitytest IR Agent発行者またはプラットフォームの支援
mint / burntest Token Agent発行者またはプラットフォームの支援
transferToken 保有者両当事者が適格性とルールを満たす

通常の開発者は Agent 秘密鍵を必要としません。Agent 権限操作は対象資産の発行者が実行します。投資家操作には自分のウォレットを使用し、秘密鍵を送信しないでください。

公開 PRWA デモ資産は現在 pause 中です。通常 transfer は Token Agent が unpause() を呼び出した後にのみ実行できます。

transfer の事前検査と送信​

const recipient = '0xfc996C5378fe0cd03Fd4296075abc07B16b2B12F';
const senderAddress = await signer.getAddress();
const amount = ethers.utils.parseUnits('10', decimals);
if (await token.paused()) {
throw new Error('Token transfers are currently paused');
}
if (!await ir.isVerified(recipient)) {
throw new Error('Recipient is not verified for this asset');
}
const compliance = new ethers.Contract(
await token.compliance(),
['function canTransfer(address,address,uint256) view returns (bool)'],
provider
);
if (!await compliance.canTransfer(senderAddress, recipient, amount)) {
throw new Error('Transfer rejected by compliance rules');
}
const receipt =
await (await token.connect(signer).transfer(recipient, amount)).wait();
console.log(receipt.transactionHash);

approve + transferFrom​

await (await token.connect(ownerSigner).approve(spender, amount)).wait();
await (await token.connect(spenderSigner)
.transferFrom(ownerAddress, recipient, amount)).wait();

事前検査後も状態は変化し得るため、レシートが最終結果です。

6.10 ローンチ受入チェックリスト​

環境​

  • Testnet と Mainnet の設定が独立している。
  • 起動時に Chain ID を厳密に検証する。
  • RPC、Explorer、コントラクトアドレスは公式リリース情報を使用する。
  • Mainnet 設定が Testnet アドレスへ自動 fallback しない。

コントラクト読み取り​

  • Token の名称、シンボル、decimals が正しい。
  • Token に紐づく IR と MC がアドレス表に一致する。
  • アドレスにコントラクト bytecode がある。
  • ABI がデプロイ済みバージョンと一致する。

金額とトランザクション​

  • 全金額で parseUnits / formatUnits を使用する。
  • write 操作で submitted、confirmed、failed を区別する。
  • tx hash が正しい Explorer を指す。
  • 失敗時に最終業務状態を更新しない。
  • retry が mint または burn を重複送信しない。

ID とコンプライアンス​

  • 対象資産の IR で適格性を照会する。
  • contains と isVerified を区別する。
  • 複数資産で誤った IR を再利用しない。
  • KYC 平文はオフチェーンに保持する。
  • コンプライアンス拒否理由を明確に表示する。

セキュリティ​

  • 秘密鍵をフロントエンド、リポジトリ、ログに置かない。
  • Agent と Claim Signer は管理された署名方式を使う。
  • プロキシアドレスのみを使用する。
  • アップグレードとセキュリティ通知を購読する。

6.11 トラブルシューティング順序​

1. Chain ID を確認
2. RPC の利用可否を確認
3. 現在のネットワークでアドレスに bytecode があるか確認
4. Token.name / decimals / identityRegistry を読み取り
5. balance / paused / isFrozen を照会
6. 受取人 contains / isVerified を照会
7. compliance.canTransfer を照会
8. 署名者ロールを確認
9. callStatic / estimateGas で revert 理由を取得
10. 送信後にレシートとイベントを照会

Testnet で成功し Mainnet で失敗する場合は、ネットワーク、コントラクトアドレス、資産適格要件、コンプライアンスルールを比較してください。同一設定と仮定してはいけません。

前へ:05 · コントラクトインターフェースとイベント · 01 · プロジェクトと統合の概要へ