Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Please refer to [Cronos: Deploy Smart Contract
](http://localhost:8080/docs/getting-started/cronos-smart-contract.html) for detailed walkthrough
](https://docs.cronos.org/for-dapp-developers/cronos-smart-contract/contract-deployment) Doc for detailed walkthrough
25 changes: 25 additions & 0 deletions hardhat3/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.env

# Node modules
/node_modules

# Compilation output
/dist

# pnpm deploy output
/bundle

# Hardhat Build Artifacts
/artifacts

# Hardhat compilation (v2) support directory
/cache

# Typechain output
/types

# Hardhat coverage reports
/coverage

# Ignition deployments
/ignition/deployments
10 changes: 10 additions & 0 deletions hardhat3/contracts/CronosToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract CronosToken is ERC20 {
constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol) {
_mint(msg.sender, initialSupply);
}
}
75 changes: 75 additions & 0 deletions hardhat3/contracts/CronosToken.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "./CronosToken.sol";

contract CronosTokenTest is Test {
CronosToken token;
address owner;
address alice;
address bob;

uint256 initialSupply = 1_000_000 ether;

function setUp() public {
owner = address(this);
alice = makeAddr("alice");
bob = makeAddr("bob");

// deploy contract
token = new CronosToken("Cronos Token", "CT", initialSupply);
}

/// @notice verify initial supply is correct
function testInitialSupply() public {
assertEq(token.totalSupply(), initialSupply);
assertEq(token.balanceOf(owner), initialSupply);
assertEq(token.name(), "Cronos Token");
assertEq(token.symbol(), "CT");
}

/// @notice test normal transfer
function testTransfer() public {
uint256 amount = 100 ether;

token.transfer(alice, amount);

assertEq(token.balanceOf(alice), amount);
assertEq(token.balanceOf(owner), initialSupply - amount);
}

/// @notice test transfer revert in case of insufficient balance
function testTransferRevert_InsufficientBalance() public {
vm.prank(alice); // let alice(her current balance:0) to trigger tx
vm.expectRevert();
token.transfer(bob, 1 ether);
}

/// @notice test approve / transferFrom
function testApproveAndTransferFrom() public {
uint256 amount = 50 ether;

// owner approves alice
token.approve(alice, amount);
assertEq(token.allowance(owner, alice), amount);

// alice calls transferFrom to transfer owner's tokens to herself
vm.prank(alice);
token.transferFrom(owner, alice, amount);

assertEq(token.balanceOf(alice), amount);
assertEq(token.balanceOf(owner), initialSupply - amount);
}

/// @notice test allowance decreases after transferFrom
function testAllowanceDecreasesAfterTransferFrom() public {
uint256 amount = 20 ether;
token.approve(alice, amount);

vm.prank(alice);
token.transferFrom(owner, alice, 10 ether);

assertEq(token.allowance(owner, alice), 10 ether);
}
}
96 changes: 96 additions & 0 deletions hardhat3/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { configVariable, task, type HardhatUserConfig } from "hardhat/config";
import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers";

const getExplorerApiKey = (chainId: number) => {
let apiKey;
if (chainId === 25) {
apiKey = configVariable("CRONOS_EXPLORER_MAINNET_API_KEY");
} else if (chainId === 338) {
apiKey = configVariable("CRONOS_EXPLORER_TESTNET_API_KEY");
}
if (!apiKey) {
throw Error("Explorer API Key Not Set for chainId: " + chainId);
}
return apiKey;
}

const getHDWallet = () => {
const PRIVATE_KEY = configVariable("PRIVATE_KEY");
if (PRIVATE_KEY) {
return [PRIVATE_KEY]
}
throw Error("Private Key Not Set! Please set up .env");
}

const config: HardhatUserConfig = {
plugins: [hardhatToolboxMochaEthersPlugin],
solidity: {
profiles: {
default: {
version: "0.8.28",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
production: {
version: "0.8.28",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
},
},
networks: {
testnet: {
chainId: 338,
type: "http",
url: "https://evm-t3.cronos.org/",
accounts: getHDWallet(),
chainType: "l1",
},
mainnet: {
chainId: 25,
type: "http",
url: "https://evm.cronos.org/",
accounts: getHDWallet(),
chainType: "l1",
},
},
verify: {
etherscan: {
apiKey: getExplorerApiKey(338),
},
},
chainDescriptors: {
25: {
name: "mainnet",
chainType: "l1",
blockExplorers: {
etherscan: {
name: "mainnet",
url: "https://explorer.cronos.org",
apiUrl: "https://explorer-api.cronos.org/mainnet/api/v1/hardhat/contract"
},
},
},
338: {
name: "testnet",
chainType: "l1",
blockExplorers: {
etherscan: {
name: "testnet",
url: "https://explorer.cronos.org/testnet",
apiUrl: "https://explorer-api.cronos.org/testnet/api/v1/hardhat/contract"
},
},
},
}
};

export default config;
7 changes: 7 additions & 0 deletions hardhat3/ignition/modules/CronosToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

export default buildModule("CronosTokenModule", (m) => {
const counter = m.contract("CronosToken", ["Cronos Token", "CRT", "1000000000000000000000000"]);

return { counter };
});
Loading