Skip to content

Commit d76256d

Browse files
committed
fix: llms
1 parent ea51ea1 commit d76256d

File tree

5 files changed

+333
-231
lines changed

5 files changed

+333
-231
lines changed

.ai/categories/smart-contracts.md

Lines changed: 104 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9637,8 +9637,6 @@ Page Title: viem for Polkadot Hub Smart Contracts
96379637

96389638
# viem
96399639

9640-
!!! smartcontract "PolkaVM Preview Release"
9641-
PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
96429640
## Introduction
96439641

96449642
[viem](https://viem.sh/){target=\_blank} is a lightweight TypeScript library designed for interacting with Ethereum-compatible blockchains. This comprehensive guide will walk you through using viem to interact with and deploy smart contracts to Polkadot Hub.
@@ -9668,13 +9666,13 @@ viem-project/
96689666
│ └── interact.ts
96699667
├── contracts/
96709668
│ └── Storage.sol
9669+
├── abis/
9670+
│ └── Storage.json
96719671
└── artifacts/
9672-
├── Storage.json
9673-
└── Storage.polkavm
9672+
└── Storage.bin
96749673
```
96759674

9676-
## Set Up the Project
9677-
9675+
## Set Up the Proje
96789676
First, create a new folder and initialize your project:
96799677

96809678
```bash
@@ -9685,11 +9683,11 @@ npm init -y
96859683

96869684
## Install Dependencies
96879685

9688-
Install viem along with other necessary dependencies, including [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank}, which enables to compile smart contracts to [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} bytecode:
9686+
Install viem along with other necessary dependencies, including [`solc`](https://www.npmjs.com/package/solc){target=\_blank}, which enables to compile smart contracts EVM bytecode:
96899687

96909688
```bash
96919689
# Install viem and resolc
9692-
npm install viem @parity/resolc
9690+
npm install viem solc
96939691

96949692
# Install TypeScript and development dependencies
96959693
npm install --save-dev typescript ts-node @types/node
@@ -9792,7 +9790,7 @@ After setting up the [Public Client](https://viem.sh/docs/clients/public#public-
97929790
```js title="src/fetchLastBlock.ts"
97939791
import { createPublicClient, http } from 'viem';
97949792

9795-
const transport = http('https://testnet-passet-hub-eth-rpc.polkadot.io');
9793+
const transport = http('https://testnet-passet-hub-eth-rpc.polkadot.io'); // TODO: change to paseo asset hub once ready
97969794

97979795
// Configure the Polkadot Hub chain
97989796
const polkadotHubTestnet = {
@@ -9806,7 +9804,7 @@ After setting up the [Public Client](https://viem.sh/docs/clients/public#public-
98069804
},
98079805
rpcUrls: {
98089806
default: {
9809-
http: ['https://testnet-passet-hub-eth-rpc.polkadot.io'],
9807+
http: ['https://testnet-passet-hub-eth-rpc.polkadot.io'], // TODO: change to paseo asset hub once ready
98109808
},
98119809
},
98129810
} as const;
@@ -9909,60 +9907,82 @@ contract Storage {
99099907

99109908
## Compile the Contract
99119909

9912-
!!! note "Contracts Code Blob Size Disclaimer"
9913-
The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes.
9914-
9915-
For detailed comparisons and migration guidelines, see the [EVM vs. PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits){target=\_blank} documentation page.
9916-
99179910
Create a new file at `src/compile.ts` for handling contract compilation:
99189911

99199912
```typescript title="src/compile.ts"
9920-
import { compile } from '@parity/resolc';
9921-
import { readFileSync, writeFileSync } from 'fs';
9913+
import solc from 'solc';
9914+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
99229915
import { basename, join } from 'path';
99239916

9924-
const compileContract = async (
9917+
const ensureDir = (dirPath: string): void => {
9918+
if (!existsSync(dirPath)) {
9919+
mkdirSync(dirPath, { recursive: true });
9920+
}
9921+
};
9922+
9923+
const compileContract = (
99259924
solidityFilePath: string,
9926-
outputDir: string
9927-
): Promise<void> => {
9925+
abiDir: string,
9926+
artifactsDir: string
9927+
): void => {
99289928
try {
99299929
// Read the Solidity file
99309930
const source: string = readFileSync(solidityFilePath, 'utf8');
9931-
9932-
// Construct the input object for the compiler
9933-
const input: Record<string, { content: string }> = {
9934-
[basename(solidityFilePath)]: { content: source },
9931+
const fileName: string = basename(solidityFilePath);
9932+
9933+
// Construct the input object for the Solidity compiler
9934+
const input = {
9935+
language: 'Solidity',
9936+
sources: {
9937+
[fileName]: {
9938+
content: source,
9939+
},
9940+
},
9941+
settings: {
9942+
outputSelection: {
9943+
'*': {
9944+
'*': ['abi', 'evm.bytecode'],
9945+
},
9946+
},
9947+
},
99359948
};
9936-
9937-
console.log(`Compiling contract: ${basename(solidityFilePath)}...`);
9938-
9949+
9950+
console.log(`Compiling contract: ${fileName}...`);
9951+
99399952
// Compile the contract
9940-
const out = await compile(input);
9941-
9942-
for (const contracts of Object.values(out.contracts)) {
9943-
for (const [name, contract] of Object.entries(contracts)) {
9944-
console.log(`Compiled contract: ${name}`);
9945-
9953+
const output = JSON.parse(solc.compile(JSON.stringify(input)));
9954+
9955+
// Check for errors
9956+
if (output.errors) {
9957+
const errors = output.errors.filter((error: any) => error.severity === 'error');
9958+
if (errors.length > 0) {
9959+
console.error('Compilation errors:');
9960+
errors.forEach((err: any) => console.error(err.formattedMessage));
9961+
return;
9962+
}
9963+
// Show warnings
9964+
const warnings = output.errors.filter((error: any) => error.severity === 'warning');
9965+
warnings.forEach((warn: any) => console.warn(warn.formattedMessage));
9966+
}
9967+
9968+
// Ensure output directories exist
9969+
ensureDir(abiDir);
9970+
ensureDir(artifactsDir);
9971+
9972+
// Process compiled contracts
9973+
for (const [sourceFile, contracts] of Object.entries(output.contracts)) {
9974+
for (const [contractName, contract] of Object.entries(contracts as any)) {
9975+
console.log(`Compiled contract: ${contractName}`);
9976+
99469977
// Write the ABI
9947-
const abiPath = join(outputDir, `${name}.json`);
9948-
writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2));
9978+
const abiPath = join(abiDir, `${contractName}.json`);
9979+
writeFileSync(abiPath, JSON.stringify((contract as any).abi, null, 2));
99499980
console.log(`ABI saved to ${abiPath}`);
9950-
9981+
99519982
// Write the bytecode
9952-
if (
9953-
contract.evm &&
9954-
contract.evm.bytecode &&
9955-
contract.evm.bytecode.object
9956-
) {
9957-
const bytecodePath = join(outputDir, `${name}.polkavm`);
9958-
writeFileSync(
9959-
bytecodePath,
9960-
Buffer.from(contract.evm.bytecode.object, 'hex')
9961-
);
9962-
console.log(`Bytecode saved to ${bytecodePath}`);
9963-
} else {
9964-
console.warn(`No bytecode found for contract: ${name}`);
9965-
}
9983+
const bytecodePath = join(artifactsDir, `${contractName}.bin`);
9984+
writeFileSync(bytecodePath, (contract as any).evm.bytecode.object);
9985+
console.log(`Bytecode saved to ${bytecodePath}`);
99669986
}
99679987
}
99689988
} catch (error) {
@@ -9971,9 +9991,10 @@ const compileContract = async (
99719991
};
99729992

99739993
const solidityFilePath: string = './contracts/Storage.sol';
9974-
const outputDir: string = './artifacts/';
9994+
const abiDir: string = './abis';
9995+
const artifactsDir: string = './artifacts';
99759996

9976-
compileContract(solidityFilePath, outputDir);
9997+
compileContract(solidityFilePath, abiDir, artifactsDir);
99779998
```
99789999

997910000
To compile your contract:
@@ -9982,17 +10003,23 @@ To compile your contract:
998210003
npm run compile
998310004
```
998410005

9985-
After executing this script, you will see the compilation results including the generated `Storage.json` (containing the contract's ABI) and `Storage.polkavm` (containing the compiled bytecode) files in the `artifacts` folder. These files contain all the necessary information for deploying and interacting with your smart contract on Polkadot Hub.
10006+
After executing this script, you will see the compilation results including the generated `Storage.json` (containing the contract's ABI) and `Storage.vin` (containing the compiled bytecode) files in the `artifacts` folder. These files contain all the necessary information for deploying and interacting with your smart contract on Polkadot Hub.
998610007

998710008
## Deploy the Contract
998810009

998910010
Create a new file at `src/deploy.ts` for handling contract deployment:
999010011

999110012
```typescript title="src/deploy.ts"
9992-
import { readFileSync } from 'fs';
9993-
import { join } from 'path';
9994-
import { createWallet } from './createWallet';
9995-
import { publicClient } from './createClient';
10013+
import { existsSync, readFileSync } from 'fs';
10014+
import { dirname, join } from 'path';
10015+
import { fileURLToPath } from 'url';
10016+
import { createWallet } from './createWallet.ts';
10017+
import { publicClient } from './createClient.ts';
10018+
10019+
const __filename = fileURLToPath(import.meta.url);
10020+
const __dirname = dirname(__filename);
10021+
const ABIS_DIR = join(__dirname, '../abis');
10022+
const ARTIFACTS_DIR = join(__dirname, '../artifacts');
999610023

999710024
const deployContract = async (
999810025
contractName: string,
@@ -10001,16 +10028,20 @@ const deployContract = async (
1000110028
try {
1000210029
console.log(`Deploying ${contractName}...`);
1000310030

10031+
const abiPath = join(ABIS_DIR, `${contractName}.json`);
10032+
const bytecodePath = join(ARTIFACTS_DIR, `${contractName}.bin`);
10033+
10034+
if (!existsSync(abiPath) || !existsSync(bytecodePath)) {
10035+
throw new Error(
10036+
`Missing artifacts for ${contractName}. Try running "npm run compile" first.`
10037+
);
10038+
}
10039+
1000410040
// Read contract artifacts
1000510041
const abi = JSON.parse(
10006-
readFileSync(
10007-
join(__dirname, '../artifacts', `${contractName}.json`),
10008-
'utf8'
10009-
)
10042+
readFileSync(abiPath, 'utf8')
1001010043
);
10011-
const bytecode = `0x${readFileSync(
10012-
join(__dirname, '../artifacts', `${contractName}.polkavm`)
10013-
).toString('hex')}` as `0x${string}`;
10044+
const bytecode = `0x${readFileSync(bytecodePath, 'utf8').trim()}` as `0x${string}`;
1001410045

1001510046
// Create wallet
1001610047
const wallet = createWallet(privateKey);
@@ -10056,13 +10087,17 @@ If everything is successful, you will see the address of your deployed contract
1005610087
Create a new file at `src/interact.ts` for interacting with your deployed contract:
1005710088

1005810089
```typescript title="src/interact.ts"
10059-
import { publicClient } from './createClient';
10060-
import { createWallet } from './createWallet';
1006110090
import { readFileSync } from 'fs';
10091+
import { dirname, join } from 'path';
10092+
import { fileURLToPath } from 'url';
10093+
import { publicClient } from './createClient.ts';
10094+
import { createWallet } from './createWallet.ts';
1006210095

10063-
const STORAGE_ABI = JSON.parse(
10064-
readFileSync('./artifacts/Storage.json', 'utf8')
10065-
);
10096+
const __filename = fileURLToPath(import.meta.url);
10097+
const __dirname = dirname(__filename);
10098+
const ABI_PATH = join(__dirname, '../abis/Storage.json');
10099+
10100+
const STORAGE_ABI = JSON.parse(readFileSync(ABI_PATH, 'utf8'));
1006610101

1006710102
const interactWithStorage = async (
1006810103
contractAddress: `0x${string}`,
@@ -10107,7 +10142,6 @@ const PRIVATE_KEY = 'INSERT_PRIVATE_KEY';
1010710142
const CONTRACT_ADDRESS = 'INSERT_CONTRACT_ADDRESS';
1010810143

1010910144
interactWithStorage(CONTRACT_ADDRESS, PRIVATE_KEY);
10110-
1011110145
```
1011210146

1011310147
Ensure to replace `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` with the proper values.

0 commit comments

Comments
 (0)