Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More EVM Tutorials #248

Closed
wants to merge 1 commit into from
Closed
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: 2 additions & 0 deletions content/build/_meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export default {
'dev-smart-contracts': 'Choosing a VM',
'evm-general': 'EVM (General)',
'solidity-resources': 'Solidity Resources',
'evm-hardhat': 'EVM Hardhat',
'evm-foundry': 'EVM Foundry',
'evm-cli-tutorial': 'EVM (CLI)',
'cosm-wasm-general': 'CosmWasm (General)',
'nft-contract-tutorial': 'NFT Contracts',
Expand Down
184 changes: 184 additions & 0 deletions content/build/evm-foundry.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
## Deploying EVM contract on Sei

Since Sei is an EVM compatible chain, existing EVM tooling like [foundry forge](https://book.getfoundry.sh/) or other could be re-used.

In this example we will be using [foundry tooling](https://book.getfoundry.sh/).

Install the [foundry tooling](https://book.getfoundry.sh/) by following this [Installation guide](https://book.getfoundry.sh/getting-started/installation.html).

Create a new project following the [Creating New Project Guide](https://book.getfoundry.sh/projects/creating-a-new-project).

Also make sure you have a wallet on Sei network.

Once project is created, tweak the contract code to the following, by adding a `getCounter` function:

```solidity copy
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter {
uint256 public number;

function setNumber(uint256 newNumber) public {
number = newNumber;
}

function increment() public {
number++;
}

function getCount() public view returns (uint256) {
return number;
}
}

```

And the test code to the following:

```solidity copy
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {Counter} from "../src/Counter.sol";

contract CounterTest is Test {
Counter public counter;

function setUp() public {
counter = new Counter();
counter.setNumber(0);
}

function test_Increment() public {
counter.increment();
assertEq(counter.number(), 1);
}

function testFuzz_SetNumber(uint256 x) public {
counter.setNumber(x);
assertEq(counter.number(), x);
}

function test_GetCount() public {
uint256 initialCount = counter.getCount();
counter.increment();
assertEq(counter.getCount(), initialCount + 1);
}
}
```

Run the tests with the following command:

```bash copy
$ forge test
```

If tests pass, deploy the contract to the Sei chain with the following command:

```bash copy
$ forge create --rpc-url $SEI_NODE_URI --mnemonic $MNEMONIC src/Counter.sol:Counter
```

Where `$SEI_NODE_URI` is the URI of the Sei node and `$MNEMONIC` is the mnemonic of the account that will deploy the contract. If you run local Sei node, the address will be `http://localhost:8545` , otherwise you could grab a `evm_rpc` url from the [registry](https://github.com/sei-protocol/chain-registry/blob/main/chains.json). If deployment is successful, you will get the EVM contract address in the output.

```bash copy
[⠒] Compiling...
No files changed, compilation skipped
Deployer: $0X_DEPLOYER_ADDRESS
Deployed to: $0X_CONTRACT_ADDRESS
Transaction hash: $0X_TX_HASH
```

Let's use the `cast` command to query the contract:

```bash copy
$ cast call $0X_CONTRACT_ADDRESS "getCount()(uint256)" --rpc-url $SEI_NODE_URI
```

The command should return `0` as the initial value of the counter.

Now we can use the `cast` command to call the `increment` function:

```bash copy
$ cast send $0X_CONTRACT_ADDRESS "increment()" --mnemonic $MNEMONIC --rpc-url $SEI_NODE_URI
```

If command is successful, you will get the transaction hash and other info back.

Now let's call the `getCount` function again and this case it should return `1`.

## Calling contract from JS client

To call contract from frontend, you could use `ethers` like:

```tsx copy
import {ethers} from "ethers";

const privateKey = <Your Private Key>;
const evmRpcEndpoint = <Your Evm Rpc Endpoint>
const provider = new ethers.JsonRpcProvider(evmRpcEndpoint);
const signer = new ethers.Wallet(privateKey, provider);

if (!signer) {
console.log('No signer found');
return;
}
const abi = [
{
"type": "function",
"name": "setNumber",
"inputs": [
{
"name": "newNumber",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "getCount",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int256",
"internalType": "int256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "increment",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
}
];

// Define the address of the deployed contract
const contractAddress = 0X_CONTRACT_ADDRESS;

// Create a new instance of the ethers.js Contract object
const contract = new ethers.Contract(contractAddress, abi, signer);

// Call the contract's functions
async function getCount() {
const count = await contract.getCount();
console.log(count.toString());
}

async function increment() {
const txResponse = await contract.increment();
const mintedTx = await txResponse.wait();
console.log(mintedTx);
}

await increment();
await getCount();
```
185 changes: 0 additions & 185 deletions content/build/evm-general.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -181,188 +181,3 @@ def endAuction():
# 3. Interaction
send(self.beneficiary, self.highestBid)
```

## Deploying EVM contract on Sei

Since Sei is an EVM compatible chain, existing EVM tooling like [hardhat](https://hardhat.org/), [foundry forge](https://book.getfoundry.sh/) or other could be re-used.

In this example we will be using [foundry tooling](https://book.getfoundry.sh/).

Install the [foundry tooling](https://book.getfoundry.sh/) by following this [Installation guide](https://book.getfoundry.sh/getting-started/installation.html).

Create a new project following the [Creating New Project Guide](https://book.getfoundry.sh/projects/creating-a-new-project).

Also make sure you have a wallet on Sei network.

Once project is created, tweak the contract code to the following, by adding a `getCounter` function:

```solidity copy
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter {
uint256 public number;

function setNumber(uint256 newNumber) public {
number = newNumber;
}

function increment() public {
number++;
}

function getCount() public view returns (uint256) {
return number;
}
}

```

And the test code to the following:

```solidity copy
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {Counter} from "../src/Counter.sol";

contract CounterTest is Test {
Counter public counter;

function setUp() public {
counter = new Counter();
counter.setNumber(0);
}

function test_Increment() public {
counter.increment();
assertEq(counter.number(), 1);
}

function testFuzz_SetNumber(uint256 x) public {
counter.setNumber(x);
assertEq(counter.number(), x);
}

function test_GetCount() public {
uint256 initialCount = counter.getCount();
counter.increment();
assertEq(counter.getCount(), initialCount + 1);
}
}
```

Run the tests with the following command:

```bash copy
$ forge test
```

If tests pass, deploy the contract to the Sei chain with the following command:

```bash copy
$ forge create --rpc-url $SEI_NODE_URI --mnemonic $MNEMONIC src/Counter.sol:Counter
```

Where `$SEI_NODE_URI` is the URI of the Sei node and `$MNEMONIC` is the mnemonic of the account that will deploy the contract. If you run local Sei node, the address will be `http://localhost:8545` , otherwise you could grab a `evm_rpc` url from the [registry](https://github.com/sei-protocol/chain-registry/blob/main/chains.json). If deployment is successful, you will get the EVM contract address in the output.

```bash copy
[⠒] Compiling...
No files changed, compilation skipped
Deployer: $0X_DEPLOYER_ADDRESS
Deployed to: $0X_CONTRACT_ADDRESS
Transaction hash: $0X_TX_HASH
```

Let's use the `cast` command to query the contract:

```bash copy
$ cast call $0X_CONTRACT_ADDRESS "getCount()(uint256)" --rpc-url $SEI_NODE_URI
```

The command should return `0` as the initial value of the counter.

Now we can use the `cast` command to call the `increment` function:

```bash copy
$ cast send $0X_CONTRACT_ADDRESS "increment()" --mnemonic $MNEMONIC --rpc-url $SEI_NODE_URI
```

If command is successful, you will get the transaction hash and other info back.

Now let's call the `getCount` function again and this case it should return `1`.

## Calling contract from JS client

To call contract from frontend, you could use `ethers` like:

```tsx copy
import {ethers} from "ethers";

const privateKey = <Your Private Key>;
const evmRpcEndpoint = <Your Evm Rpc Endpoint>
const provider = new ethers.JsonRpcProvider(evmRpcEndpoint);
const signer = new ethers.Wallet(privateKey, provider);

if (!signer) {
console.log('No signer found');
return;
}
const abi = [
{
"type": "function",
"name": "setNumber",
"inputs": [
{
"name": "newNumber",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "getCount",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int256",
"internalType": "int256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "increment",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
}
];

// Define the address of the deployed contract
const contractAddress = 0X_CONTRACT_ADDRESS;

// Create a new instance of the ethers.js Contract object
const contract = new ethers.Contract(contractAddress, abi, signer);

// Call the contract's functions
async function getCount() {
const count = await contract.getCount();
console.log(count.toString());
}

async function increment() {
const txResponse = await contract.increment();
const mintedTx = await txResponse.wait();
console.log(mintedTx);
}

await increment();
await getCount();
```
Loading