Skip to content

Commit

Permalink
Merge pull request #441 from zajko/deploy_and_run_cep18_in_its
Browse files Browse the repository at this point in the history
Aligning tests and implementation so that a CEP18 contract can be dep…
  • Loading branch information
zajko authored Jun 24, 2024
2 parents 8e02918 + 3422581 commit 21deef7
Show file tree
Hide file tree
Showing 12 changed files with 740 additions and 2,083 deletions.
251 changes: 205 additions & 46 deletions e2e/services/CasperServiceByJsonRPC.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,32 @@ import {
TransactionUtil,
CLU64,
CLU64Type,
encodeBase16
encodeBase16,
TransactionRuntime
} from '../../src/index';
import { sleep } from './utils';
import { Contract } from '../../src/lib/Contracts';

import { FAUCET_PRIV_KEY, NETWORK_NAME, NODE_URL } from '../config';
import { PricingMode } from '../../src/lib/TransactionUtil';
import { Native } from '../../src/lib/TransactionTarget';
import { Transfer } from '../../src/lib/TransactionEntryPoint';
import {
PricingMode,
TransactionCategoryInstallUpgrade,
TransactionCategoryLarge,
TransactionCategoryMint,
makeV1Transaction
} from '../../src/lib/TransactionUtil';
import {
Native,
Session,
Stored,
TransactionSessionKind
} from '../../src/lib/TransactionTarget';
import { Call, Custom, Transfer } from '../../src/lib/TransactionEntryPoint';
import { Standard } from '../../src/lib/TransactionScheduling';
import { InitiatorAddr } from '../../src/lib/InitiatorAddr';
import { Some } from 'ts-results';
import { DEFAULT_DEPLOY_TTL } from '../../src/constants';
import { TransactionInvocationTarget } from '../../src/lib/TransactionInvocationTarget';

config();

Expand Down Expand Up @@ -286,9 +300,9 @@ describe('CasperServiceByJsonRPC', () => {
runtimeArgs,
transactionTarget,
transactionEntryPoint,
transactionScheduling
transactionScheduling,
TransactionCategoryMint
);

const signedTransaction = TransactionUtil.signTransaction(
transaction,
faucetKey
Expand Down Expand Up @@ -401,33 +415,34 @@ describe('CasperServiceByJsonRPC', () => {
assert.exists(named_key);
});

//TODO we need a new wasm that works with 2.0
xit('should deploy wasm over rpc', async () => {
it('CEP18 should work deployed via "account_put_deploy"', async () => {
const casperClient = new CasperClient(NODE_URL);
const erc20 = new Contract(casperClient);
const wasmPath = path.resolve(__dirname, './contract.wasm');
const cep18 = new Contract(casperClient);
const wasmPath = path.resolve(__dirname, './cep18.wasm');
const wasm = new Uint8Array(fs.readFileSync(wasmPath, null).buffer);
let id = Date.now();

const tokenName = 'TEST';
const tokenSymbol = 'TST';
const tokenName = 'TEST-' + id;
const tokenSymbol = 'TST-' + id;
const tokenDecimals = 8;
const tokenTotlaSupply = 500_000_000_000;
const tokenTotalSupply = 500_000;

const args = RuntimeArgs.fromMap({
message: CLValueBuilder.string(tokenName),
const runtimeArgs = RuntimeArgs.fromMap({
name: CLValueBuilder.string(tokenName),
symbol: CLValueBuilder.string(tokenSymbol),
decimals: CLValueBuilder.u8(tokenDecimals),
total_supply: CLValueBuilder.u256(tokenTotlaSupply)
total_supply: CLValueBuilder.u256(tokenTotalSupply),
events_mode: CLValueBuilder.u8(0)
});
const signedDeploy = erc20.install(

const signedDeploy = cep18.install(
wasm,
args,
'200000000000',
runtimeArgs,
'50000000000',
faucetKey.publicKey,
NETWORK_NAME,
[faucetKey]
);

await client.deploy(signedDeploy);

await sleep(2500);
Expand All @@ -439,66 +454,197 @@ describe('CasperServiceByJsonRPC', () => {
};
const { AddressableEntity } = await client.getEntity(entity_identifier);
const contractHash = AddressableEntity!.named_keys.find((i: NamedKey) => {
return i.name === 'erc20_token_contract';
return i.name === 'cep18_contract_hash_' + tokenName;
})?.key;

assert.exists(contractHash);

erc20.setContractHash(contractHash!);

const fetchedTokenName = await erc20.queryContractData(['name']);
const fetchedTokenSymbol = await erc20.queryContractData(['symbol']);
const fetchedTokenDecimals: BigNumber = await erc20.queryContractData([
cep18.setContractHash(contractHash!);
cep18.setContractName(`cep18_contract_hash_${tokenName}`);
const fetchedTokenName = await cep18.queryContractData(['name']);
const fetchedTokenSymbol = await cep18.queryContractData(['symbol']);
const fetchedTokenDecimals: BigNumber = await cep18.queryContractData([
'decimals'
]);
const fetchedTokenTotalSupply: BigNumber = await erc20.queryContractData([
const fetchedTokenTotalSupply: BigNumber = await cep18.queryContractData([
'total_supply'
]);

const balanceOf = async (erc20: Contract, owner: CLKeyParameters) => {
const balanceKey = Buffer.from(
CLValueParsers.toBytes(CLValueBuilder.key(owner)).unwrap()
).toString('base64');
const balance: BigNumber = (
await erc20.queryContractDictionary('balances', balanceKey)
).value();
return balance;
};

const balanceOfFaucet = await balanceOf(erc20, faucetKey.publicKey);
const balanceOfFaucet = await balanceOf(cep18, faucetKey.publicKey);

assert.equal(tokenName, fetchedTokenName);
assert.equal(tokenSymbol, fetchedTokenSymbol);
assert.equal(tokenDecimals, fetchedTokenDecimals.toNumber());
assert.equal(tokenTotlaSupply, fetchedTokenTotalSupply.toNumber());
assert.equal(balanceOfFaucet.toNumber(), tokenTotlaSupply);
assert.equal(tokenTotalSupply, fetchedTokenTotalSupply.toNumber());
assert.equal(balanceOfFaucet.toNumber(), tokenTotalSupply);

// Test `callEntrypoint` method: Transfter token
const recipient = Ed25519.new().publicKey;
const transferAmount = 2_000;

const transferArgs = RuntimeArgs.fromMap({
recipient: CLValueBuilder.key(recipient),
amount: CLValueBuilder.u256(2_000)
});

const transferDeploy = erc20.callEntrypoint(
const transferDeploy = cep18.callEntrypoint(
'transfer',
transferArgs,
faucetKey.publicKey,
NETWORK_NAME,
'2500000000',
[faucetKey]
);

const { deploy_hash } = await client.deploy(transferDeploy);
await sleep(2500);
result = await client.waitForDeploy(transferDeploy, 100000);

assert.equal(result.deploy.hash, deploy_hash);
expect(result.deploy.session).to.have.property('StoredContractByHash');
// expect(result.execution_results[0].result).to.have.property('Success');
expect(result.deploy.session).to.have.property('StoredContractByName');
expect(result.execution_info!.execution_result!).to.have.property(
'Version2'
);
let amorphicExecutionResult: any = result.execution_info!.execution_result!;
if (amorphicExecutionResult['Version2']) {
expect(amorphicExecutionResult['Version2'].error_message).to.be.null;
}
const balanceOfRecipient = await balanceOf(cep18, recipient);
assert.equal(balanceOfRecipient.toNumber(), transferAmount);
});

//This needs to wait for a fix in the node which currently prevents wasm transactions
xit('CEP18 should work deployed via "account_put_transaction"', async () => {
const casperClient = new CasperClient(NODE_URL);
const cep18 = new Contract(casperClient);
const wasmPath = path.resolve(__dirname, './cep18.wasm');
const wasm = new Uint8Array(fs.readFileSync(wasmPath, null).buffer);
const paymentAmount = 10000000000;
let id = Date.now();

const tokenName = 'TEST-' + id;
const tokenSymbol = 'TST-' + id;
const tokenDecimals = 8;
const tokenTotalSupply = 500_000;
const runtimeArgs = RuntimeArgs.fromMap({
name: CLValueBuilder.string(tokenName),
symbol: CLValueBuilder.string(tokenSymbol),
decimals: CLValueBuilder.u8(tokenDecimals),
total_supply: CLValueBuilder.u256(tokenTotalSupply),
events_mode: CLValueBuilder.u8(0),
amount: CLValueBuilder.u512(paymentAmount)
});
const params = new TransactionUtil.Version1Params(
InitiatorAddr.fromPublicKey(faucetKey.publicKey),
Date.now(),
DEFAULT_DEPLOY_TTL,
NETWORK_NAME,
PricingMode.buildFixed(3)
);
const transaction = makeV1Transaction(
params,
runtimeArgs,
Session.build(
TransactionSessionKind.Installer,
wasm,
TransactionRuntime.VmCasperV1
),
new Call(),
new Standard(),
TransactionCategoryInstallUpgrade
);
const signedTransaction = transaction.sign([faucetKey]);
await client.transaction(signedTransaction);

await sleep(2500);

let result = await client.waitForTransaction(signedTransaction, 100000);
if (!result) {
assert.fail('Deploy failed');
}
let entity_identifier = {
AccountHash: faucetKey.publicKey.toAccountHashStr()
};
const { AddressableEntity } = await client.getEntity(entity_identifier);
const contractHash = AddressableEntity!.named_keys.find((i: NamedKey) => {
return i.name === 'cep18_contract_hash_' + tokenName;
})?.key;

assert.exists(contractHash);

const balanceOfRecipient = await balanceOf(erc20, recipient);
cep18.setContractHash(contractHash!);
cep18.setContractName(`cep18_contract_hash_${tokenName}`);
const fetchedTokenName = await cep18.queryContractData(['name']);
const fetchedTokenSymbol = await cep18.queryContractData(['symbol']);
const fetchedTokenDecimals: BigNumber = await cep18.queryContractData([
'decimals'
]);
const fetchedTokenTotalSupply: BigNumber = await cep18.queryContractData([
'total_supply'
]);

const balanceOfFaucet = await balanceOf(cep18, faucetKey.publicKey);

assert.equal(tokenName, fetchedTokenName);
assert.equal(tokenSymbol, fetchedTokenSymbol);
assert.equal(tokenDecimals, fetchedTokenDecimals.toNumber());
assert.equal(tokenTotalSupply, fetchedTokenTotalSupply.toNumber());
assert.equal(balanceOfFaucet.toNumber(), tokenTotalSupply);

// Test `callEntrypoint` method: Transfter token
const recipient = Ed25519.new().publicKey;
const transferAmount = 2_000;
const transferArgs = RuntimeArgs.fromMap({
recipient: CLValueBuilder.key(recipient),
amount: CLValueBuilder.u256(2_000)
});

const runEndpointParams = new TransactionUtil.Version1Params(
InitiatorAddr.fromPublicKey(faucetKey.publicKey),
Date.now(),
DEFAULT_DEPLOY_TTL,
NETWORK_NAME,
PricingMode.buildFixed(3)
);
const byHash = new TransactionInvocationTarget();
const contractName = `cep18_contract_hash_${tokenName}`;
byHash.ByName = contractName;
const runEndpointTransaction = makeV1Transaction(
runEndpointParams,
transferArgs,
Stored.build(byHash, TransactionRuntime.VmCasperV1),
Custom.build('transfer'),
new Standard(),
TransactionCategoryLarge
);

const signedRunEndpointTransaction = runEndpointTransaction.sign([
faucetKey
]);
const { transaction_hash } = await client.transaction(
signedRunEndpointTransaction
);
await sleep(2500);
const transferResult = await client.waitForTransaction(
signedRunEndpointTransaction,
100000
);
assert.equal(
transferResult.transaction.Version1.hash,
transaction_hash.Version1!
);

expect(
transferResult.transaction.Version1.body.target.Stored.id
).to.have.property('ByName');
expect(transferResult.execution_info!.execution_result!).to.have.property(
'Version2'
);
let amorphicExecutionResult: any = transferResult.execution_info!
.execution_result!;
if (amorphicExecutionResult['Version2']) {
expect(amorphicExecutionResult['Version2'].error_message).to.be.null;
}

const balanceOfRecipient = await balanceOf(cep18, recipient);
assert.equal(balanceOfRecipient.toNumber(), transferAmount);
});

Expand Down Expand Up @@ -552,3 +698,16 @@ describe('CasperServiceByJsonRPC', () => {
// TODO
xit('speculative_exec');
});

async function balanceOf(
erc20: Contract,
owner: CLKeyParameters
): Promise<BigNumber> {
const balanceKey = Buffer.from(
CLValueParsers.toBytes(CLValueBuilder.key(owner)).unwrap()
).toString('base64');
const balance: BigNumber = (
await erc20.queryContractDictionary('balances', balanceKey)
).value();
return balance;
}
Binary file added e2e/services/cep18.wasm
Binary file not shown.
Loading

0 comments on commit 21deef7

Please sign in to comment.