Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .github/workflows/tron-smart-contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ on:
- 'packages/smart-contracts/test/tron/**'
- 'packages/smart-contracts/tronbox-config.js'
- 'packages/smart-contracts/src/lib/artifacts/ERC20FeeProxy/**'
- 'packages/smart-contracts/src/lib/artifacts/ERC20BatchPayments/**'
- 'packages/smart-contracts/src/contracts/ERC20FeeProxy.sol'
- 'packages/smart-contracts/src/contracts/ERC20BatchPayments.sol'
- 'packages/payment-processor/src/payment/*tron*'
- 'packages/payment-processor/test/payment/*tron*'
- 'packages/currency/src/chains/tron/**'
Expand All @@ -27,6 +30,9 @@ on:
- 'packages/smart-contracts/test/tron/**'
- 'packages/smart-contracts/tronbox-config.js'
- 'packages/smart-contracts/src/lib/artifacts/ERC20FeeProxy/**'
- 'packages/smart-contracts/src/lib/artifacts/ERC20BatchPayments/**'
- 'packages/smart-contracts/src/contracts/ERC20FeeProxy.sol'
- 'packages/smart-contracts/src/contracts/ERC20BatchPayments.sol'
- 'packages/payment-processor/src/payment/*tron*'
- 'packages/payment-processor/test/payment/*tron*'
- 'packages/currency/src/chains/tron/**'
Expand Down Expand Up @@ -76,7 +82,7 @@ jobs:
ls -la build/tron/

# Verify key contracts were compiled
for contract in ERC20FeeProxy TestTRC20 BadTRC20 TRC20True TRC20NoReturn TRC20False TRC20Revert; do
for contract in ERC20FeeProxy ERC20BatchPayments TestTRC20 BadTRC20 TRC20True TRC20NoReturn TRC20False TRC20Revert; do
if [ ! -f "build/tron/${contract}.json" ]; then
echo "ERROR: ${contract}.json not found!"
exit 1
Expand Down Expand Up @@ -109,6 +115,15 @@ jobs:
echo "✓ TestTRC20 has $func"
done

echo "Verifying ERC20BatchPayments ABI..."
for func in batchERC20PaymentsWithReference batchERC20PaymentsMultiTokensWithReference paymentErc20FeeProxy; do
if ! grep -q "$func" build/tron/ERC20BatchPayments.json; then
echo "ERROR: ERC20BatchPayments missing $func!"
exit 1
fi
echo "✓ ERC20BatchPayments has $func"
done

echo "✅ Contract ABI structure verified"

- name: Verify deployment files are valid JSON
Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
"node": ">=22.0.0"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"workspaces": [
"packages/*"
],
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"@requestnetwork/smart-contracts/@openzeppelin/**"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/RequestNetwork/requestNetwork.git"
Expand Down
5 changes: 5 additions & 0 deletions packages/smart-contracts/deployments/tron/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"address": "TCUDPYnS9dH3WvFEaE7wN7vnDa51J4R4fd",
"hexAddress": "411b6ca35d39842cf8fbe49000653a1505412da659",
"creationBlockNumber": 79216121
},
"ERC20BatchPayments": {
"address": "TRZbXXuLd3HW5utzVysA3rpLgU7sVBrd1D",
"hexAddress": "41ab0ad52e1d1615ee6bc20ab8f2a4c498fb89fd10",
"creationBlockNumber": 83104290
}
}
}
7 changes: 6 additions & 1 deletion packages/smart-contracts/deployments/tron/nile.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
"chainId": "3",
"timestamp": "2024-01-01T00:00:00.000Z",
"deployer": "TO_BE_FILLED_ON_DEPLOYMENT",
"note": "Existing deployment from handover document. Run 'yarn tron:deploy:nile' to redeploy.",
"note": "Existing deployment from handover document",
"contracts": {
"ERC20FeeProxy": {
"address": "THK5rNmrvCujhmrXa5DB1dASepwXTr9cJs",
"hexAddress": "41508b3b4059c40bb3aac5da5ac006ccdd9c4dc957",
"creationBlockNumber": 63208782
},
"ERC20BatchPayments": {
"address": "TBAtFt46T7LUW5Sya6PNjw7MQrKkzKEFMx",
"hexAddress": "410d2d78623480a4caf18ea157badd9a8a7311b746",
"creationBlockNumber": 67830042
}
}
}
122 changes: 94 additions & 28 deletions packages/smart-contracts/scripts/tron/deploy-mainnet.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/**
* Tron Mainnet Deployment Script
*
* This script deploys the ERC20FeeProxy to Tron mainnet.
* This script deploys the ERC20FeeProxy and ERC20BatchPayments to Tron mainnet.
*
* ⚠️ WARNING: This deploys to MAINNET with real TRX!
*
Expand All @@ -28,6 +28,18 @@ const PRIVATE_KEY = process.env.TRON_PRIVATE_KEY;
// Safety check
const CONFIRM_MAINNET = process.env.CONFIRM_MAINNET_DEPLOY === 'true';

const MAINNET_DEPLOYMENT_PATH = path.join(__dirname, '../../deployments/tron/mainnet.json');

/**
* Contracts to deploy
*
* Comment out the contracts you don't want to deploy.
*/
const CONTRACTS_TO_DEPLOY = [
//'ERC20FeeProxy',
'ERC20BatchPayments',
];

if (!PRIVATE_KEY) {
console.error('Error: TRON_PRIVATE_KEY environment variable is required');
process.exit(1);
Expand All @@ -49,6 +61,13 @@ async function loadArtifact(contractName) {
return JSON.parse(fs.readFileSync(artifactPath, 'utf8'));
}

function loadExistingMainnetDeployment() {
if (!fs.existsSync(MAINNET_DEPLOYMENT_PATH)) {
return null;
}
return JSON.parse(fs.readFileSync(MAINNET_DEPLOYMENT_PATH, 'utf8'));
}

async function confirmDeployment() {
if (CONFIRM_MAINNET) {
return true;
Expand Down Expand Up @@ -92,6 +111,24 @@ async function deployContract(contractName, constructorArgs = []) {
};
}

async function deployContractWrapper({
contractName,
deployments,
blockNumbers,
constructorArgs = [],
}) {
const contract = await deployContract(contractName, constructorArgs);
deployments[contractName] = {
address: contract.address,
hexAddress: contract.hexAddress,
};

// Get block number
const block = await tronWeb.trx.getCurrentBlock();
const blockNumber = block.block_header.raw_data.number;
blockNumbers[contractName] = blockNumber;
}

async function main() {
console.log('╔══════════════════════════════════════════════════════════╗');
console.log('║ TRON MAINNET DEPLOYMENT ║');
Expand Down Expand Up @@ -123,59 +160,88 @@ async function main() {
console.log('\n🚀 Starting mainnet deployment...\n');

const deployments = {};
const blockNumbers = {};
const startTime = Date.now();

try {
// Deploy ERC20FeeProxy only (no test tokens on mainnet)
const erc20FeeProxy = await deployContract('ERC20FeeProxy');
deployments.ERC20FeeProxy = {
address: erc20FeeProxy.address,
hexAddress: erc20FeeProxy.hexAddress,
};
const existingDeployment = loadExistingMainnetDeployment();

// Deploy ERC20FeeProxy
if (CONTRACTS_TO_DEPLOY.includes('ERC20FeeProxy')) {
await deployContractWrapper({ contractName: 'ERC20FeeProxy', deployments, blockNumbers });
await new Promise((resolve) => setTimeout(resolve, 5000));
}

// Deploy ERC20BatchPayments
if (CONTRACTS_TO_DEPLOY.includes('ERC20BatchPayments')) {
const erc20FeeProxyAddress = deployments.ERC20FeeProxy
? deployments.ERC20FeeProxy.address
: existingDeployment.contracts.ERC20FeeProxy.address;
Comment thread
LeoSlrRf marked this conversation as resolved.

// Get block number
const block = await tronWeb.trx.getCurrentBlock();
const blockNumber = block.block_header.raw_data.number;
if (!erc20FeeProxyAddress) {
console.error(
'ERC20FeeProxy address not found in deployments/tron/mainnet.json; cannot deploy ERC20BatchPayments',
);
process.exit(1);
}

console.log('Using ERC20FeeProxy at:', erc20FeeProxyAddress);
await deployContractWrapper({
contractName: 'ERC20BatchPayments',
deployments,
blockNumbers,
constructorArgs: [erc20FeeProxyAddress],
});
}

// Print summary
console.log('\n╔══════════════════════════════════════════════════════════╗');
console.log('║ MAINNET DEPLOYMENT SUMMARY ║');
console.log('╚══════════════════════════════════════════════════════════╝\n');

console.log('ERC20FeeProxy:');
console.log(` Address: ${deployments.ERC20FeeProxy.address}`);
console.log(` Block: ${blockNumber}`);
console.log(
` Tronscan: https://tronscan.org/#/contract/${deployments.ERC20FeeProxy.address}`,
);
for (const contractName of Object.keys(deployments)) {
console.log(`${contractName}:`);
console.log(` Address: ${deployments[contractName].address}`);
console.log(` Block: ${blockNumbers[contractName]}`);
console.log(
` Tronscan: https://tronscan.org/#/contract/${deployments[contractName].address}`,
);
}

const newContracts = Object.entries(deployments).reduce((acc, [contractName, contract]) => {
acc[contractName] = {
...contract,
creationBlockNumber: blockNumbers[contractName],
};
return acc;
}, {});

const contracts = {
...(existingDeployment.contracts || {}),
...newContracts,
};
Comment thread
LeoSlrRf marked this conversation as resolved.

// Save deployment info
// Save deployment info (merge with existing mainnet.json)
const deploymentInfo = {
network: 'mainnet',
chainId: '1',
timestamp: new Date().toISOString(),
deployer: deployerAddress,
deploymentDuration: `${(Date.now() - startTime) / 1000}s`,
contracts: {
ERC20FeeProxy: {
...deployments.ERC20FeeProxy,
creationBlockNumber: blockNumber,
},
},
contracts,
};

const outputPath = path.join(__dirname, '../../deployments/tron/mainnet.json');
fs.writeFileSync(outputPath, JSON.stringify(deploymentInfo, null, 2));
console.log(`\nDeployment info saved to: ${outputPath}`);
fs.mkdirSync(path.dirname(MAINNET_DEPLOYMENT_PATH), { recursive: true });
fs.writeFileSync(MAINNET_DEPLOYMENT_PATH, JSON.stringify(deploymentInfo, null, 2));
console.log(`\nDeployment info saved to: ${MAINNET_DEPLOYMENT_PATH}`);

// Next steps
console.log('\n╔══════════════════════════════════════════════════════════╗');
console.log('║ NEXT STEPS ║');
console.log('╚══════════════════════════════════════════════════════════╝\n');
console.log('1. Verify contract on Tronscan');
console.log('2. Run verification script: yarn tron:verify:mainnet');
console.log('3. Update artifact registry in:');
console.log(' packages/smart-contracts/src/lib/artifacts/ERC20FeeProxy/index.ts');
console.log('3. Update artifact registry with new deployment addresses');
console.log('4. Test with a real TRC20 token payment');
} catch (error) {
console.error('\n❌ Deployment failed:', error.message);
Expand Down
48 changes: 28 additions & 20 deletions packages/smart-contracts/scripts/tron/deploy-nile.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,19 @@ async function deployContract(contractName, constructorArgs = []) {
parameters: constructorArgs,
});

console.log(`${contractName} deployed at: ${contract.address}`);
console.log(`Base58 address: ${tronWeb.address.fromHex(contract.address)}`);
const base58Address = tronWeb.address.fromHex(contract.address);
const block = await tronWeb.trx.getCurrentBlock();
const creationBlockNumber = block.block_header.raw_data.number;

return contract;
console.log(`${contractName} deployed at: ${contract.address}`);
console.log(`Base58 address: ${base58Address}`);
console.log(`Block: ${creationBlockNumber}`);

return {
address: base58Address,
hexAddress: contract.address,
creationBlockNumber,
};
}

async function main() {
Expand All @@ -85,30 +94,25 @@ async function main() {

try {
// 1. Deploy ERC20FeeProxy
const erc20FeeProxy = await deployContract('ERC20FeeProxy');
deployments.ERC20FeeProxy = {
address: tronWeb.address.fromHex(erc20FeeProxy.address),
hexAddress: erc20FeeProxy.address,
};
deployments.ERC20FeeProxy = await deployContract('ERC20FeeProxy');

// 2. Deploy ERC20BatchPayments
deployments.ERC20BatchPayments = await deployContract('ERC20BatchPayments', [
deployments.ERC20FeeProxy.address,
]);

// 2. Deploy TestTRC20 for testing
const testToken = await deployContract('TestTRC20', [
// 3. Deploy TestTRC20 for testing
deployments.TestTRC20 = await deployContract('TestTRC20', [
'1000000000000000000000000000', // 1 billion tokens
'Nile Test TRC20',
'NTRC20',
18,
]);
deployments.TestTRC20 = {
address: tronWeb.address.fromHex(testToken.address),
hexAddress: testToken.address,
};

// 3. Deploy test token variants
const trc20NoReturn = await deployContract('TRC20NoReturn', ['1000000000000000000000000000']);
deployments.TRC20NoReturn = {
address: tronWeb.address.fromHex(trc20NoReturn.address),
hexAddress: trc20NoReturn.address,
};
// 4. Deploy test token variants
deployments.TRC20NoReturn = await deployContract('TRC20NoReturn', [
'1000000000000000000000000000',
]);

// Print summary
console.log('\n╔══════════════════════════════════════════════════════════╗');
Expand All @@ -119,6 +123,7 @@ async function main() {
console.log(`${name}:`);
console.log(` Base58: ${info.address}`);
console.log(` Hex: ${info.hexAddress}`);
console.log(` Block: ${info.creationBlockNumber}`);
}

// Save deployment info
Expand All @@ -141,6 +146,9 @@ async function main() {
console.log('╚══════════════════════════════════════════════════════════╝\n');
console.log('1. Verify contracts on Nile Tronscan:');
console.log(' https://nile.tronscan.org/#/contract/' + deployments.ERC20FeeProxy.address);
console.log(
' https://nile.tronscan.org/#/contract/' + deployments.ERC20BatchPayments.address,
);
console.log('\n2. Run tests against deployed contracts:');
console.log(' TRON_PRIVATE_KEY=... yarn tron:test:nile');
console.log('\n3. Update artifact registry with deployment addresses');
Expand Down
Loading
Loading