|
|
|
@@ -0,0 +1,305 @@ |
|
|
|
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<number> { |
|
|
|
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<string,boolean>(); |
|
|
|
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(); |
|
|
|
|
|
|
|
|