import * as dotevnv from "dotenv" import {toUtf8String,parseUnits,ContractFactory, parseEther,JsonRpcProvider, Contract, JsonRpcSigner, Wallet,ContractTransactionResponse, MaxInt256 ,Transaction,formatEther, ZeroHash,ethers,keccak256,id } from 'ethers' import chalk from "chalk"; import {Calulator} from "../inc/calc"; import { TokenIssuer } from "../inc/TokenIssuer"; import { SecurityToken, SecurityToken__factory, } from '../typechain' // import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import { Partition } from '../inc/tokenData'; import {checkReceipt,checkReceipt2, setProvider,getDeploymentAddresses, getElapsed, sleep,getBlockInfo} from '../inc/util' dotevnv.config(); if (!process.env.RPCURL) { console.log(`No rpcur value specified...`) } console.log(`목적 서버 : ${process.env.RPCURL}`); async function getNonce(addr: string): Promise { const nonce = await provider.getTransactionCount(addr); return nonce; } async function info(symbol: string) { const proxy = getDeploymentAddresses(symbol).address; console.log(`토큰 주소 : ${proxy}`); const token = new SecurityToken__factory(issuer).attach(proxy) as SecurityToken; await token.connect(admin); const ops = await token.operators(); console.log(ops); // token.grantRole(keccak256('OPERATOR_ROLE'),'0xaaa') } async function transfer(signer:Wallet,symbol:string,from: Wallet, to: Wallet, amount: number = 1, count: number = 1) { const proxy = getDeploymentAddresses(symbol).address; console.log(`토큰 주소 : ${proxy}`); const token = new SecurityToken__factory(issuer).attach(proxy) as SecurityToken; await token.connect(admin); // const ops = await token.operators(); // console.log(ops); let balance1= await token.balanceOf(from); let balance2 = await token.balanceOf(to); const b = await token.isTokenHolderKYC(from); if(!b) { console.log('holder kyc error'); //return; } const partitions = await token.getDefaultPartitions(); console.log(chalk.yellow('###################### 전송전 잔고 ###################################')) console.log(`balance of sender(${from.address}) = ${balance1}\r\nbalance of receiver(${to.address}) = ${balance2}`); // token.on(token.filters.Transfer, async (...args) => { // const lastArg = args[args.length - 1]; // console.log(lastArg); // console.log('on transfer by partition'); // }) let nonce = await getNonce(signer.address); let txids = []; let proms = []; let firstTx:string = null; let lastTx:string = null; const start = Date.now(); console.log(chalk.cyan(`전송시작 시간 : ${new Date(start).toUTCString()}`)); console.log(chalk.yellow(`sending ${count} transactions`)); for(let i = 0; i < count; i++) { const tx = await token.operatorTransferByPartition.populateTransaction( partitions[0], from.address, to.address, amount, ZeroHash, ZeroHash, { // gasPrice: 0, gasLimit: 2100000, nonce: nonce, type: 2, chainId: 1337 } ); ++nonce; // console.log(tx); const signed = await signer.signTransaction(tx); const pm = provider.send('eth_sendRawTransaction',[signed]); if(i == 0) { firstTx = keccak256(signed); } if (i == count -1) { lastTx = keccak256(signed); } proms.push(pm); } let txs = await Promise.all(proms); const elapsed = getElapsed(start,1000); console.log(`all tx sent in ${elapsed} seconds`); console.log(`first Tx = ${firstTx}`); console.log(`last Tx = ${lastTx}`); let txMap = new Map(); txs.forEach(txid => { // txids.push({txid: txid}); txMap.set(txid,false); }); const blockHashes = await checkReceipt2(txMap,[firstTx as string, lastTx as string], 'wait for receipt...'); const firstBlockHash = blockHashes.get(firstTx); const lastBlockHash = blockHashes.get(lastTx); console.log(`firstBlockHash = ${firstBlockHash} \nlastBlockHash = ${lastBlockHash}`); balance1= await token.balanceOf(from); balance2 = await token.balanceOf(to); console.log(chalk.yellow('###################### 전송후 잔고 ###################################')) console.log(`balance of sender(${from.address}) = ${balance1}\r\nbalance of receiver(${to.address}) = ${balance2}`); // console.log(`balance of sender = ${balance1}, balance of receiver = ${balance2}`); const lastB = await getBlockInfo(lastBlockHash); const lastTimeStamp = parseInt(lastB.timestamp,16); console.log(`eth_getBlockByHash(${lastBlockHash}).timestamp = ${lastTimeStamp}`) const d = new Date(lastTimeStamp * 1000); console.log(chalk.cyan(`전송종료 시간(블록완결시간) : ${d.toUTCString()}`)); console.log(chalk.yellow(`start timestamp = ${start}`)); console.log(chalk.yellow(`end timestamp = ${lastTimeStamp * 1000}`)); const tps = calc.CTPS(count,start,lastTimeStamp * 1000); console.log(`CTPS = ${tps}`); } async function testSecurity(symbol: string, operator: Wallet, tobeOperator: Wallet,holder: Wallet, user1: Wallet, user2: Wallet) { const proxy = getDeploymentAddresses(symbol).address; console.log(`토큰 주소 : ${proxy}`); const token = new SecurityToken__factory(operator).attach(proxy) as SecurityToken; await token.connect(operator); const decimals = await token.decimals(); const digit = 10 ** Number(decimals); console.log(`토큰 자릿수 : ${decimals}`); const partitions = await token.getDefaultPartitions(); //console.log(partitions); console.log(chalk.yellow('###################### 변경전 오퍼레이터 ###################################')) const ops = await token.operators(); console.log(ops); console.log(chalk.yellow(`provided operator = ${operator.address}`)); console.log(chalk.yellow('###################### KYC 전 사용자 잔고 ###################################')) let holderBalance = await token.balanceOf(holder); console.log(`토큰보유자 잔고 = ${Number(holderBalance).toFixed(Number(decimals))}`); let bUser1 = await token.balanceOf(user1); let bUser2 = await token.balanceOf(user2); console.log(chalk.blue( `사용자1 잔고 : ${Number(bUser1).toFixed(Number(decimals))}\r\n사용자2 잔고 : ${Number(bUser2).toFixed(Number(decimals))}` )) console.log(chalk.yellow('###################### 사용자 등록전 전송시도###################################')) if(await token.isTokenHolderKYC(user1)) { console.log(`user1 already kyced .. unKYC user1`); const r = await token.unKYCtokenHolders([user1]); await r.wait(); } if(await token.isTokenHolderKYC(user2)) { console.log(`user2 already kyced .. .. unKYC user2`); const r = await token.unKYCtokenHolders([user2]); await r.wait(); } try { let r = await token.operatorTransferByPartition(partitions[0],holder,user1,1 * digit,ZeroHash,ZeroHash,{gasLimit: 20000000}); console.log(`txhash1 : ${r.hash}`) const receipt1 = await r.wait(); console.log(receipt1.hash); r = await token.operatorTransferByPartition(partitions[0],holder,user2,1 * digit,ZeroHash,ZeroHash,{gasLimit: 20000000}); const receipt2 = await r.wait(); console.log(`txhash2 : ${r.hash}`) console.log('KYC전 토큰전송완료....'); } catch(ex) { console.log(chalk.red('예정된 KYC전 토큰전송에러')); //console.log(ex); } console.log(chalk.yellow('###################### 사용자 등록(KYC) ###################################')) let ret = await token.KYCtokenHolders([user1,user2],{gasLimit: 20000000}); console.log('wait for user KYCed...'); await ret.wait(); console.log(chalk.yellow('###################### 사용자 등록후 전송시도 ###################################')) ret = await token.operatorTransferByPartition(partitions[0],holder,user1,1 * digit ,ZeroHash,ZeroHash,{gasLimit: 20000000}); ret = await token.operatorTransferByPartition(partitions[0],holder,user2,1 * digit ,ZeroHash,ZeroHash,{gasLimit: 20000000}); await ret.wait(); console.log(chalk.yellow('###################### 등록 후 사용자 잔고 ###################################')) bUser1 = await token.balanceOf(user1); bUser2 = await token.balanceOf(user2); console.log(chalk.blue( `balance of user1 : ${Number(bUser1).toFixed(Number(decimals))}\r\nbalance of user2 : ${Number(bUser2).toFixed(Number(decimals))}` )) console.log(chalk.bgCyan('###################### 사용자 권한테스트 종료 ###################################')) return; await sleep(5000,'wait for tx'); await token.KYCtokenHolders([user1,user2],{gasLimit: 20000000}); await sleep(5000,'wait for tx.....'); await token.operatorTransferByPartition(partitions[0],operator,user1,100,ZeroHash,ZeroHash); await token.operatorTransferByPartition(partitions[0],operator,user2,100,ZeroHash,ZeroHash); await sleep(5000,'wait for tx... 정상전송됨'); //console.log() await token.unKYCtokenHolders([user1,user2],{gasLimit: 200000000}) return; console.log(chalk.yellow('###################### 변경전 오퍼레이터 전송시도###################################')) await transfer(tobeOperator,symbol,holder1,holder2); console.log(chalk.yellow('###################### 변경후 오퍼레이터 전송시도###################################')) //await token.grantRole( [keccak256('OPERATOR_ROLE'),tobeOperator.address]); // const t = id('OPERATOR_ROLE'); // console.log(t); // return; await token.grantRole( id('OPERATOR_ROLE'),tobeOperator.address,{ gasLimit: 20000000}); sleep(5000,'wait...'); await transfer(tobeOperator,symbol,holder1,user1); await transfer(tobeOperator,symbol,holder1,user2); console.log(chalk.yellow('###################### 변경후 오퍼레이터 전송시도###################################')) //await transfer(tobeOperator,symbol,holder1,holder2); //token.isu // token.grantRole(keccak256('OPERATOR_ROLE'),'0xaaa') //token.revokeRole(keccak256('OPERATOR_ROLE')) console.log(chalk.yellow('###################### 변경전 오퍼레이터 전송시도###################################')) //await transfer(tobeOperator,symbol,user1,user2); console.log(chalk.yellow('###################### 테스트권한 클리어 ###################################')); await token.revokeRole(id('OPERATOR_ROLE'),tobeOperator,{ gasLimit: 20000000}); await token.unKYCtokenHolders([user1, user2]); } const calc = new Calulator(); const rpcUrl = process.env.RPCURL; const provider = new JsonRpcProvider(rpcUrl); setProvider(provider); const admin = new Wallet('0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3',provider); const issuer = new Wallet('0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63',provider); //const signer = issuer; const holder1 = new Wallet('0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f',provider); const holder2 = new Wallet('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',provider); const user1 = new Wallet('5c7ff82446654833ed4cbd3dc7cca94b114b556def572a5f2f7f29224c757adb'); //0xB22f4c5fA701837dcBd037D60F5d2606050fBbd9 const user2 = new Wallet('509157aeb1308d8ff8db8a3059d4392d92fb66960ef5083eda5a8dcc9118be31'); //0xA59D39340AEF8681248aaB3F71D104897FdF7c84 const newOperator = new Wallet('a0e4679c61e04969499af0c4cdcdc66e9a9f2e3f6cbc17ede9e2137518f8e75d'); //0x1e5Ed00f65556374d7fb2039e2a11aDc64021762 async function main() { await testSecurity('test001',issuer,newOperator,holder1, user1,user2); } main();